CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Get time between 2 square wave

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

Get time between 2 square wave
PostPosted: Tue Oct 26, 2010 1:03 pm     Reply with quote

I am developing a project that a need to measure the time between 2 sinusoid wave.

The Vin sine wave are lagged by an angle in comparison the other wave taked on the capacitor. I used a RC series network to cause this lag. So I applied this two signal in two comparators to obtain a square wave. Ok.

Now, I am trying to get the time difference between the rise of the 2 square wave.

I tried to use the 2 CCP module on the 16F877A but not worked.

A screenshot with the two wave a need to calculate the time difference between their rises (time between the rise of black one and the rise of the blue one) :

http://img594.imageshack.us/img594/9773/sadast.jpg

My code that not worked:

Code:
#include <16F877A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#byte PIR1=0x0C

#use delay(clock=4000000)

#include <LCD.C>


int16 t1=0,t2=0,t=0;
float ap=0.0;

#int_ccp1
void isr()
{
   
   t1=ccp_1;
   
}

#int_ccp2
void isr2()
{
   
   t2=ccp_2;
   t=t1-t2;
   ccp_1=0;
   
}

void main()
{
   lcd_init();
       
   setup_ccp1 (CCP_CAPTURE_RE);
   setup_ccp2 (CCP_CAPTURE_RE);
   setup_timer_1 (T1_INTERNAL); 
   enable_interrupts (INT_CCP1|INT_CCP2);                //Habilitar Interrupções
   enable_interrupts (global);   
   
   while (TRUE)
   {
      //t=t2-t1;
      ap=t*1.0;
      printf (lcd_putc, "\nT = %6.1f", ap);
   }
}
     
     


CCS 4.057

bye
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 26, 2010 1:50 pm     Reply with quote

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=40173
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Sun Nov 14, 2010 7:01 pm     Reply with quote

I am back here to say that I tried this idea by Ttelmah from the topic suggested:

Quote:
CCP.

This is the best way to do what you want.
This is a hardware module in most PICs (you will need to choose one that has it), with a whole range of abilities to do with timing, and pulse generation. One ability, is to capture the reading on an internal counter (normally Timer1, but some of the PIC18's also allow Timer3 to be used), when an 'event' occurs. The events can be programmed to be the rising edge, or falling edge, on the CCP pins.
Accuracy will far exceed any software solution.

Look in the examples, at EX_CCPMP.C

In this, the two CCP modules are used. One to record when a signal rises, and the other when it falls. Each time a CCP records a value, there is an interrupt, and the code uses the second interrupt, on the falling edge, then subtracts the rising edge count, from the falling edge count, to give the pulse width. The same signal is fed to both CCP pins.
In your case, you simply connect your two signals to the two pins, and program the second CCP, to also use the rising edges (in the example, it is programmed to use the falling edge).

Best Wishes


But this did not worked, I am getting a 0 (zero) result.

The 2 signal that I need to measure the time difference:

http://img580.imageshack.us/img580/6200/graphv.jpg

The circuit:

http://img152.imageshack.us/img152/2093/graph2l.jpg

My code:

Code:
#include <18f4550.h>             //O PIC utilizado, obigatório!
                                 //ser utilizado de 8 bits também.
#FUSES NOWDT                     //Sem Watch dog, evitando reset
#FUSES XT                        //Crystal de oscilação igual a 4mhz
#FUSES PUT                       //Tempo de início do PIC
#FUSES NOPROTECT                 //Codigo sem proteção de leitura, software livre!
#FUSES NODEBUG                   //No Debug mode for ICD
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                     //No EE protection



#use delay(clock=4000000)        //Meu clock
#include <LCD.C>                 //Rotina de LCD modo 4 vias. Obrigatório!

long rise,fall,pulse_width;

#int_ccp2
void isr()
{
   rise = CCP_1;
   fall = CCP_2;

   pulse_width = fall - rise;     // CCP_1 is the time the pulse went high
}                                 // CCP_2 is the time the pulse went low
                                  // pulse_width/(clock/4) is the time

                                  // In order for this to work the ISR
                                  // overhead must be less than the
                                  // low time.  For this program the
                                  // overhead is 45 instructions.  The
                                  // low time must then be at least
                                  // 9 us.

void main()
{
   lcd_init();
   //printf(lcd_putc "\n\rHigh time (sampled every second):\n\r");
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_RE);    // Configure CCP2 to capture fall
   setup_timer_1(T1_INTERNAL);    // Start timer 1

   enable_interrupts(INT_CCP2);   // Setup interrupt on falling edge
   enable_interrupts(GLOBAL);

   while(TRUE) {
      //delay_ms(1000);
      printf(lcd_putc, "\n%lu us ", pulse_width );
   }
}


Compiler 4.057

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Nov 14, 2010 9:11 pm     Reply with quote

I'm not sure about the scale of your timing diagram. What is the
estimated time difference between the two leading edges ? Are the units
in milliseconds or in microseconds ?
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Sun Nov 14, 2010 11:30 pm     Reply with quote

Sorry, I forgot to comment this data.

Zooming on the graph, we have this:

http://img813.imageshack.us/img813/9796/szdfszf.png

Taking the average value of 2.5V of two signals... by approximation, we have a difference of 0,000488s (seconds) or 0.488ms. With a 4Mhz clock and T1 set to internal, is pretty easy for the PIC to catch it, hun?

Thanks...
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Mon Nov 15, 2010 5:10 am     Reply with quote

Some comments:
You show MCLR connected to +6v. Now, this pin won't be _harmed_ by this, but it risks triggering the programming mode. The PIC is rated for 5.5v _max_ supply, with the logic inputs going a maximum of 0.3v above this. MCLR is allowed to go higher, since this connects to the programming circuit, and the voltage on this pin is used as the reference to generate Vpp, but it is not _rated_ to go to this voltage in normal operation. There can be very odd behaviours if the pin is taken to unexpected voltages like this...
Now, you show lots of nice little simulation graphs, but have you actually looked at the signals 'for real' on the PIC pins?. The real world often doesn't do exactly what you expect.....
The code should basically work, with a 'caveat'. You should test if CCP_2, is less than CCP_1. If it is, the timer has wrapped between the edges, and 65536 needs to be added to the result.
You really need to copy the pulse_width value to a local variable, with interrupts disabled, or you will see 'garbage' results as it updates half way through the LCD output....
4.057, is a bit 'borderline' for a compiler that works. Unfortunately, I'd rate the mid 70's as the first V4 compilers I found that actually did what they were meant to. You may have problems because of this....

Best Wishes
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Mon Nov 15, 2010 2:25 pm     Reply with quote

Thanks Ttelmah for the help!

And yes I saw that mistake on MCLR, I forgot to edit that pin. But in real life, I use 5V and a 1K resistor into that pin.

So, I followed your suggest and....

Well I do not know why CCP2 module is not working _in simulation_. On my first program I put the first signal at CCP1 and the second signal at CCP2 and followed the EX_CCPMP.c that tells to capture the two modules when the event occurs on CCP2 and subtract them.

BUT, on the simulation it is not working, so I changed the order, now CCP1 is the second signal and CCP2 is the first signal and a used the CCP1 interrupt and I am not getting more a zero result.

However, the result I getting now is not what I expect. The result I am getting is a variation between 0 and 15000 us. I expect 0.488 ms. But not precisely.

Well, I am posting the new code, take a look and comment please.. I feel I am getting there. Just more details a can not see.

[off-topic]Why can not I declare a variable after interrupt's setups? I tried to declare a variable just after the enable_interrupts(GLOBAL); and I could not.[/off-topic]

Code:
#include <18f4550.h>             //O PIC utilizado, obigatório!
                                 //ser utilizado de 8 bits também.
#FUSES NOWDT                     //Sem Watch dog, evitando reset
#FUSES XT                        //Crystal de oscilação igual a 4mhz
#FUSES PUT                       //Tempo de início do PIC
#FUSES NOPROTECT                 //Codigo sem proteção de leitura, software livre!
#FUSES NODEBUG                   //No Debug mode for ICD
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                     //No EE protection

#use delay(clock=4000000)        //Meu clock
#include <LCD.C>                 //Rotina de LCD modo 4 vias. Obrigatório!

int16 entrada,capacitor,pulse_width;

#int_ccp1
void isr()
{
   entrada = CCP_2;
   capacitor = CCP_1;
}

void setup_pulse()
{
   int16 temp;
   disable_interrupts(global);
   temp=pulse_width;   
   printf(lcd_putc, "\n%lu us ", temp );   
   enable_interrupts(GLOBAL); 
}

void main()
{
   lcd_init();   
   
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_RE);    // Configure CCP2 to capture fall
   setup_timer_1(T1_INTERNAL);    // Start timer 1
   
   enable_interrupts(INT_CCP1);
   enable_interrupts(GLOBAL); 

   while(TRUE)
   {     
      if (capacitor < entrada)
      {
         capacitor+=65536;   
         pulse_width = capacitor - entrada; 
         setup_pulse();     
      }
   }
}


thanks.
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 15, 2010 2:33 pm     Reply with quote

rule number 1: Simulation is NOT the real world

rule number 2: NEVER trust the simulator program, unless YOU wrote it.

I've never found a 'simulator' program in 35 years of cutting code that I would trust your life on or bet my house on.
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Mon Nov 15, 2010 2:48 pm     Reply with quote

On the varible declaration, this is standard C.
In the original C, variables can _only_ be declared at the start of a function defintion. On later improved version like ANSI C, you can declare a variable _at the start of a section_ (piece of code braketted with {}). CCS technically allows this, but it can sometimes be 'fragile' doing this, so it is safer to keep to the original C form. C 'generically' _does not_ allow definitions anywhere else.
Agree with the comments about simulation. MPLAB is the 'best' in this regard. Most others only work if you are 'lucky'....

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 15, 2010 3:15 pm     Reply with quote

I got tired of this so I made it work in hardware.

First I made a program to create the two test waveforms. This program
runs on the first PicDem2-Plus board:
Code:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#define WAVEFORM_0   PIN_B0
#define WAVEFORM_1   PIN_B1

//==========================================
void main()
{

output_low(WAVEFORM_0);
output_low(WAVEFORM_1);

delay_ms(100);

while(1)
  {
   output_high(WAVEFORM_0);
   delay_us(448);
   output_high(WAVEFORM_1);

   delay_ms(40);

   output_low(WAVEFORM_0);
   delay_us(448);
   output_low(WAVEFORM_1);

   delay_ms(40);
  }

}


Then I took one of your original programs, and modified it to use RS-232
output instead of the LCD, and I put it on the 2nd PicDem2-Plus board:
Code:

#include <16F877.h> 
#FUSES NOWDT                     
#FUSES XT                         
#FUSES PUT                       
#FUSES NOPROTECT                 
#FUSES NODEBUG               
#FUSES NOLVP                 
#FUSES NOCPD                 
#use delay(clock=4000000)   
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)   

long rise,fall,pulse_width;

#int_ccp2
void isr()
{
   rise = CCP_1;
   fall = CCP_2;

   pulse_width = fall - rise;   
}


void main()
{
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_RE);    // Configure CCP2 to capture fall
   setup_timer_1(T1_INTERNAL);    // Start timer 1

   enable_interrupts(INT_CCP2);   // Setup interrupt on falling edge
   enable_interrupts(GLOBAL);

   while(TRUE) {
      delay_ms(1000);
      printf("%lu us \n\r", pulse_width );
   }
}


Then I connected the two boards together, with jumper wires.
Pin B0 on board 1 goes to pin C2 on Board 2.
Pin B1 on board 1 goes to pin C1 on Board 2.
Ground on board 1 goes to ground on Board 2.

Then I loaded TeraTerm and ran both boards and I got the following
output, which is in the expected range. All of these was done in less
than 10 minutes. It was compiled with vs. 4.057. I mean, days are
spent with the simulator, but two boards and an oscilloscope works a
lot better.
Quote:

452 us
452 us
452 us
452 us
452 us
452 us
452 us
452 us
452 us
452 us
452 us
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Mon Nov 29, 2010 4:10 am     Reply with quote

Thanks for your reply. The project is almost done. I have just more 1 question.

I just found the math library and want to know if I am using this right. I read that the sine and cosine functions are in radians.. so a made the conversion.

I am using a fake usb to connect the pic to the hyperterminal..... so a need to know if is necessary declare the RS232 protocol...

The code @ PCW 4.057
Code:

#include <18F4550.h>                                                    //The PIC
#device adc=10                                                          //ADC 10bits
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL3,CPUDIV1,VREGEN   //Fuses
#use delay(clock=48000000)                                              //Clock
#include <Math.h>                                                       //To make some calcs

#define USB_CON_SENSE_PIN PIN_B2                                          //Yes!

#include <usb_cdc.h>

void main()
{
   long valor_1, valor_2, diferenca;                                    //Variables
   long tension_1=0, tension_2=0;
   float envio, angulo_degree, angulo_radian, tensao_onda_1, tensao_onda_2, pot_ativa, pot_reativa;

   int16 adc_1, adc_2=0;     
     
   usb_cdc_init();   
   usb_init();   
   
   setup_adc_ports(AN0_TO_AN1);
   setup_adc(ADC_CLOCK_DIV_64);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4); 
   
   for(;;)
   {
      set_adc_channel(0);           
      delay_us(20);                 
     
      adc_1=read_adc(); 
           
      if (adc_1 > tension_1)                    //To find the biggest value
      {           
         valor_1 = get_timer1();
         tension_1 = adc_1;               
      }
                 
      set_adc_channel(1);           
      delay_us(20);                 
     
      adc_2=read_adc();
     
      if (adc_2 > tension_2)                    //To find the biggest value
      {
         valor_2 = get_timer1();
         tension_2 = adc_2;         
      }
     
      diferenca = (valor_2 - valor_1);
     
      if (valor_2 < valor_1)
      {
         diferenca+=65536;
      }
     
      diferenca/=12;                         //Time in microseconds
      envio = (diferenca/1000);              //Time in miliseconds     
     
      usb_task();
     
      if (usb_enumerated())
      { 
         angulo_degree = (360*60*envio)/1000;              //angle in degrees
         angulo_radian = (angulo_degree*PI)/180;    //angle in radians
     
         tensao_onda_1 = (5*tension_1)/1023;       //max value 1
         tensao_onda_2 = (5*tension_2)/1023;       //max value 2
         
         pot_ativa = (((5*tension_1)/1023)*((5*tension_2)/1023)*(cos(angulo_radian)))/2;     //Active power   ?
         pot_reativa = (((5*tension_1)/1023)*((5*tension_2)/1023)*(sin(angulo_radian)))/2;   //reactive power ?
         delay_ms(500);
         printf(usb_cdc_putc,"\f T= %1.2f ms  Tensao Entrada= %2.3f V  Tensao Saida= %1.2f V  Pot. Ativa= %1.2f W  Pot. Reativa= %1.2f VAR" , envio,tensao_onda_1,tensao_onda_2,pot_ativa,pot_reativa);  //show
      }
   }
}


thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 29, 2010 12:45 pm     Reply with quote

Are you using a USB to serial cable like this:
http://www.siig.com/ViewProduct.aspx?pn=JU-CB1S12-S3

If so, the USB end of the cable needs to plug into a USB master, such as
the PC. The 18F4550 can only be a USB slave device. You can't plug
the USB end of the cable into the 18F4550 board.

You can plug the USB-to-serial cable into the PC, and the plug the serial
end of it into a PIC board (with a Max232-type chip on it). But of course
if you are using serial to talk to a PIC, you must use the #use rs232()
statement to define the serial port on the PIC.
bkamen



Joined: 07 Jan 2004
Posts: 1615
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Mon Nov 29, 2010 12:52 pm     Reply with quote

temtronic wrote:
rule number 1: Simulation is NOT the real world

rule number 2: NEVER trust the simulator program, unless YOU wrote it.


Rule #3: Even if you wrote it - are you sure you can trust it?



Honestly, the simulator stuff should become a sticky at the top of the forum thread list with something like a list of "10 Commandments of Simulators."

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Mon Dec 06, 2010 9:25 am     Reply with quote

hi, it is me again.

So, my project worked like a charm on a breadboard.

_BUT_ I needed come back here and tell that the problem that I was having on the simulator was not a simulator issue.

Look at the image below and pay attention on the two red retangles on the 18F4550:

http://img600.imageshack.us/img600/6268/semttulomd.png

The dunbass here, conected the second signal at the PIN B3, the second CCP2! That is because the code was not working. No interrupt was happening.....

The correct PIN is RC1!.

Now, the program works fine on the simulation too.

Thanks!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group