View previous topic :: View next topic |
Author |
Message |
RandyP
Joined: 15 Jun 2015 Posts: 16 Location: Dallas, TX
|
Pulse counting routine |
Posted: Sat Jul 04, 2015 1:48 pm |
|
|
Using PIC 16F690, MPLAB 8.92, and PicKit3, and CCS V4.050
I am working on a program in which a number of pulses at Pin RA4 are to be counted and actions taken based on the number of pulses.
The first pulse acts as a start pulse. On seeing the first pulse the program should wait for the falling edge of the pulse and count pulses from there.
The input pulse train is:
start bit: Ton is 2msec, Toff is 2msec,
each pulse after start pulse is:
Ton is 4msec, Toff is 4msec
The pulses are generated by 1st 16F690 (works great) and come out of the chip at pin C4. At C4 there is 10K to gnd, and a 1K to the input of 2nd chip (Pin A4).
Here is the schematic:
Here is what I think I am doing:
And here is the section of code relevant to this task:
Code: |
Valid = 0; // initialize global variable Valid
Pulse = 0; // initialize global variable Pulse
while(!input(PIN_A4)) // wait for PIN_A4 to go low: known starting point
{Valid = 0;}
delay_ms(4); // get to middle of Ton 1st pulse
//***********************************************************************************
if(input(PIN_A4)) // Pulse 1 Ton check
{Pulse = 0.5; // Pulse = 0.5
Valid = 1;}
else{Valid = 0;}
delay_ms(4);
if (!input(PIN_A4)) // Pulse 1 Toff check
{Pulse = Pulse + 0.5; // Pulse = 1.0
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
//***********************************************************************************
if(input(PIN_A4)) // Pulse 2 Ton check
{Pulse = Pulse + 0.5; // Pulse = 1.5
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
if(!input(PIN_A4)) // Pulse 2 Toff check
{Pulse = Pulse + 0.5; // Pulse = 2.0
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
//***********************************************************************************
if(input(PIN_A4)) // Pulse 3 Ton check
{Pulse = Pulse + 0.5; // Pulse = 2.5
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
if(!input(PIN_A4)) // Pulse 3 Toff check
{Pulse = Pulse + 0.5; // Pulse = 3.0
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
//***********************************************************************************
if(input(PIN_A4)) // Pulse 4 Ton check
{Pulse = Pulse + 0.5; // Pulse = 3.5
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
if(!input(PIN_A4)) // Pulse 4 Toff check
{Pulse = Pulse + 0.5; // Pulse = 4.0
Valid = 1;}
else {Valid = 0;}
delay_ms(4);
//***********************************************************************************
if (input(PIN_A4)) // Pulse 5 Ton check (is invalid)
{Pulse = Pulse + 0.5; // Pulse = 3.5
Valid = 0;}
// Convert from number of pulses to channel (pin number)
if (Pulse == 1.0)
{pin = PIN_C0;}
if (Pulse == 2.0)
{pin = PIN_C1;}
if (Pulse == 3.0)
{pin = PIN_C2;}
if (Pulse == 4.0)
{pin = PIN_C3;}
output_low(LastPinHigh);// turn off last led
output_high(pin);// turn on new led
LastPinHigh = pin;// save pin name for next time
|
This is just a section of main code, all variables have been declared. Anyone see anything obviously wrong?
The problem is when I close SW1 LED 1 for both chip should go on. Chip 1 does light LED 1 and properly sends the correct number of pulses to chip 2. But the LEDs for chip 2 turn on and off erratically. I don't want to use RS-232 communications or I2C. Any suggestions?
Randy P _________________ Randy Principe
Electrical Engineering Technician |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sat Jul 04, 2015 3:26 pm |
|
|
For starters, try using integers rather than FP.
Mike
It's more helpful if you post short, complete compilable code we can copy and paste to test. |
|
|
RandyP
Joined: 15 Jun 2015 Posts: 16 Location: Dallas, TX
|
Pulse counting routine |
Posted: Sat Jul 04, 2015 3:36 pm |
|
|
Thanks. Are you saying I can ignore the low part of the pulses and just count the highs? I will try it.
I purposely didn't put the entire code up because it is long. I must say I never thought someone might try to run it... _________________ Randy Principe
Electrical Engineering Technician |
|
|
RandyP
Joined: 15 Jun 2015 Posts: 16 Location: Dallas, TX
|
once more |
Posted: Sat Jul 04, 2015 3:38 pm |
|
|
Oh, I get what you are saying. Create a short compilable program that illustrates my problem. Not necessarily the entire program, much of which is irrelevant to my post. I got it, thanks. _________________ Randy Principe
Electrical Engineering Technician |
|
|
RandyP
Joined: 15 Jun 2015 Posts: 16 Location: Dallas, TX
|
Using a debug would help, but... |
Posted: Sat Jul 04, 2015 3:45 pm |
|
|
I was going to debug with the PicKit3 but the setup required different OSC settings and different pins, etc. and I didn't want to start tearing up my board, so I was turning chip 2's led's on at certain points to help me troubleshoot. Wish I could simulate the whole thing.
Randy _________________ Randy Principe
Electrical Engineering Technician |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Re: once more |
Posted: Sun Jul 05, 2015 2:40 am |
|
|
RandyP wrote: | Oh, I get what you are saying. Create a short compilable program that illustrates my problem. Not necessarily the entire program, much of which is irrelevant to my post. I got it, thanks. |
Yes, most of the regulars here don't trust simulators (Proteus et. al.). We believe real hardware is the only true test.
If you only show us part of your code, we've no way of knowing what's missing, the problem could be in a declaration elsewhere!
A few more points:-
You've got repeating code for each pulse state. Hint, you should be able to reduce to one simpler occurrence.
You're using delay_ms(xx). Ties up your processor, so it can't do anything else.
Mike
PS You could test receiver code in MPLAB_SIM with an external stimulus to take the place of the pulse generator. |
|
|
mbradley
Joined: 11 Jul 2009 Posts: 118 Location: California, USA
|
|
Posted: Mon Jul 06, 2015 12:05 am |
|
|
Just thinking out of the box, what we have here is a serial stream, with a start bit start.
What about tweeking the baud rate on a uart, and then use the count of high bits?
Ex: 0b1100000 would equal 2 pulses
Just a thought. _________________ Michael Bradley
www.mculabs.com
Open Drivers and Projects |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Jul 06, 2015 1:14 am |
|
|
and in the code given, 'beware of latency'.
The code checks for an edge, and then delays, then tests again. If you think about it, the check for edge itself will always test 'true' a short time _after_ the edge (latency of the hardware and code), then add the delay, and the time for the next test, and you will always be a little while _after_ where you expect to be. It shouldn't be too bad as shown (since the data rate is slow), but could well lead to cumulative errors in where you are actually working in the waveform.... |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Mon Jul 06, 2015 3:07 am |
|
|
Adding to the above tips, make sure RA4 (AKA AN3) analog function is disabled.
To debug the system I would first cut the system in half and *make sure* that the first PIC is indeed transmitting what you expect it to transmit. This could be done with an oscilloscope or with a very simple test program such as:
Code: |
output_low(PIN_C5);
while(input(PUSHBUTTON)); // wait for pushbutton for example
output_high(PIN_C5);
delay_ms(2);
output_low(PIN_C5);
delay_ms(2);
output_high(PIN_C5);
delay_ms(4);
output_low(PIN_C5);
delay_ms(4);
output_high(PIN_C5);
delay_ms(4);
output_low(PIN_C5);
while(1); // wait forever.
|
etc.
I don't see in your code that you wait for a RISING edge before waiting for a falling edge while waiting for a start pulse.
Also I can offer my version of the code which you could learn from (I haven't tested it).
Code: |
int Pulse;
Pulse=0;
// ASSUMING that the system wakes up without a transmission in progress.
// if a transmission is in progress, data bits will be treated as start bits!
while(!input(PIN_A4)); // wait for rising edge of start bit
while(input(PIN_A4)); // wait for falling edge of start bit
delay_ms(4);
// now it's the middle of Ton (or end of pulse chain)
// the While sentence tests if line is high (there is a pulse) or low (the end of the pulse chain) :
while(input(PIN_A4)) {
// now it's the middle of Ton, pulse is present
Pulse++; // increase pulse counter
while(input(PIN_A4)) ; // wait for falling edge. This is important to keep sync and avoid latency issues.
delay_ms(6); // skip Toff and half of the next Ton
//now we are at the next sampling point
}
// Pulse will contain number of pulses.
|
Other things to consider: if for any reason the two PIC loose sync (for example noise on the line triggers the receiving side by mistake) there should also be some timeouts and re-synchronization in the code. |
|
|
RandyP
Joined: 15 Jun 2015 Posts: 16 Location: Dallas, TX
|
RE: Pulse counting routine |
Posted: Mon Jul 06, 2015 8:26 am |
|
|
Thank you all. Great suggestions.
Somehow I started a new thread without knowing it and thanks to Guy I realized that I was watching the new thread while you were giving great suggestions on the real post. I guess that happened because I put a different subject. Am I correct in that the subject line always has to be the same for one thread?
It turns out the main problem was - say I had one pulse. I would count the first Ton and Toff and pulse would equal 1 (thanks for the tip about floating point Vs int) at that point if the next Ton was low I needed to get out of the string of if's. As it was I would still be counting the next several "lows" giving me an incorrect value of pulse.
I will try some of the previous suggestions to see if I can improve my code.
Thanks again everyone,
Randy _________________ Randy Principe
Electrical Engineering Technician |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Mon Jul 06, 2015 8:47 am |
|
|
Quote: | Am I correct in that the subject line always has to be the same for one thread? |
simply go into the thread you started and click Post Reply. Leave the subject line empty. |
|
|
|