View previous topic :: View next topic |
Author |
Message |
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
Using watchdog timer for timeout function |
Posted: Tue Oct 23, 2012 5:56 pm |
|
|
What I'm trying to do seems quite simple, but after 2 days of searching the forums, I have yet to come up with a solution.
I'm using a PIC 18F4520, MP LAB ver. 8.80.00.00, and PCW ver. 3.249.23.12.
My application is for GPS vehicle tracking. In the receiver I'm using RS-232 for internal communication with a data radio module. If the GPS data from the vehicle satisfies a certain condition, I send an output pin high, and if it meets a different condition, I send it low. I need to provide for the contingency that I send the pin high, and then I stop receiving data from the transmitter. After 4-8 seconds, if I don't get a low start bit, I need to send the output pin back to low.
I was told that the watchdog timer can handle this, but I can't figure out how to get it to work. I tried modifying the library file ex_wdt18.c, but I haven't been able to figure out how to set the conditions for resetting the timer (start bit) and executing a command when it times out (no start bit after 4-8 s).
I did manage to set the configuration bits to WDT and WDT1024, but that's about as far as I've gotten.
Any help would be very much appreciated. _________________ Always remember, things are never so bad that they can't get worse. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Tue Oct 23, 2012 7:50 pm |
|
|
Thanks much! I didn't think to look there. This should work even better than the WDT. _________________ Always remember, things are never so bad that they can't get worse. |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Tue Oct 23, 2012 9:15 pm |
|
|
Well, I tried it, and it didn't work. I think the problem is that every second I am getting 28 bytes (8-bit integers) of GPS data, and if I throw in an extra getc() to watch for the timeout, that will shift all my data up by 1 byte and cause the entire system to fail.
I tried using an if conditional to look at the first byte in the 28-byte data stream by its currently assigned name and send the pin low if it equals zero, but that didn't do anything. When I killed the power to the transmitter, the output pin in the receiver just stayed high.
Any idea what I'm doing wrong here? _________________ Always remember, things are never so bad that they can't get worse. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 23, 2012 9:36 pm |
|
|
I don't understand what you mean by an extra getc ? How do you get
the incoming bytes ? What do you use other than getc ? |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Wed Oct 24, 2012 1:13 am |
|
|
In the Main loop I have
Code: |
if(input(RXData) == 0) // Did we get a low start bit ?
{
GetBurst(); // Get data packet
|
Then have a subroutine with 28 consecutive lines of getc()s to get 28 bytes of GPS data from the radio.
Code: |
void GetBurst()
{
data01=getc(ac);
if(data01 == 0) // Did we get a timeout from RS-232?
{
putc(0xCA, mc); // Send cancellation byte to 2nd MCU.
Reset(); // Reset variables.
return;
}
data02=getc(ac);
data03=getc(ac);
data04=getc(ac);
.
.
.
data27=getc(ac);
data28=getc(ac);
return;
}
|
As you can see, I have tried looking at my first data byte, data01, to check for the timeout byte, but it simply doesn't work, and I can't figure out why.
The sample code shows a getc() to get the zero-value byte from the RS-232 timeout, but if I put that in, it will get my first byte of data, then my second byte will be assigned to data1 and the third byte to data2...
I have tried putting this code
Code: |
if(data01 == 0) // Did we get a timeout from RS-232?
{
putc(0xCA, mc); // Send cancellation byte to 2nd MCU.
Reset(); // Reset variables.
return;
}
|
in the main loop, but it doesn't work there, either.
Any ideas? _________________ Always remember, things are never so bad that they can't get worse. |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Thu Oct 25, 2012 2:14 pm |
|
|
Update:
I tried adding an extra non-zero char byte (all others are int 8) at the beginning of my data from the TX for the timeout byte. The idea was that if this byte is a zero character (0x30), that will cause the if statement to be true and send the cancellation byte. I then added an extra getc() at the beginning of the GetBurst() routine to get this character.
Code: | void GetBurst()
{
char killbyte;
killbyte=getc(ac);
if(killbyte == 0) // Did we get a timeout from RS-232?
{
putc(0xCA, mc); // Send cancellation byte to 2nd MCU.
Reset(); // Reset variables.
return;
}
data01=getc(ac);
data02=getc(ac);
data03=getc(ac);
data04=getc(ac);
.
.
.
data27=getc(ac);
data28=getc(ac);
return;
} |
However, this somehow messed up the data causing the entire system not to function.
The problem is that the documentation assumes you will only be receiving a single byte of data and not a stream of multiple bytes. How can I apply the RS-232 timeout function when my data comes in a stream of 28 bytes? _________________ Always remember, things are never so bad that they can't get worse.
Last edited by jlucas on Thu Oct 25, 2012 2:20 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 25, 2012 2:20 pm |
|
|
You shouldn't have multiple getc() statements. You should have a for()
loop with one getc() in it. If the getc() returns 0, and the RS232_ERRORS
variable is also 0, then it timed out. In that case, break out of the for()
loop. |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Thu Oct 25, 2012 2:29 pm |
|
|
Well, then, I'm going to have to come up with a completely different solution. In normal operation it is highly likely that one of my data bytes will equal 0x30, and I can't have it cancelling every time I get a byte with that value. If each event lasts 10 sec, and I'm getting 28 bytes each second, that means there's a better than even chance that one of my data bytes will equal 0x30 and cause a premature cancellation.
Any hope for getting the watchdog timer to work for this? I don't need precise timing. I just can't leave the system hung up indefinitely if it doesn't get a cancellation from the TX. _________________ Always remember, things are never so bad that they can't get worse. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Thu Oct 25, 2012 2:42 pm |
|
|
0x30 != 0......
The return value is _binary_ 0 or 1.
The digit '0' is 0x30.
Best Wishes |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Thu Oct 25, 2012 2:56 pm |
|
|
The instructions were to declare this variable as a char, not an int 1.
The point is, my data can contain ANY 8-bit value from 0 to 255, so I can't have any value cause a timeout every time it comes in. I just need a timeout for when I stop receiving data for 4-8 sec . _________________ Always remember, things are never so bad that they can't get worse. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 25, 2012 3:32 pm |
|
|
Quote: | my data can contain ANY 8-bit value from 0 to 255
|
The CCS getc() timeout feature works with any data from 0 to 255. The
RS232_ERRORS variable normally returns a value of 0x90 (with the
18F4520) for any character received, if there is no timeout. This is true
even if the character that is received is a NULL (0x00).
RS232_ERRORS will only return 0x00 if you get a timeout with getc(). |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Thu Oct 25, 2012 3:43 pm |
|
|
I don't think I'm ever going to get the RS232 timeout function to work in my system as I have it now, and it's going to take a MAJOR rewrite of the code to make it compatible with this scheme.
All I want is for the 18F4520 to send a byte to the other chip if it doesn't receive any data for 4-8 sec. Is there any other way to do this that doesn't use RS232_ERRORS?
I've tried using the delay_ms(n) function, but that brings the entire system to a halt while it runs.
I think the watchdog timer might be my only hope, but that doesn't seem to work as advertised, either. _________________ Always remember, things are never so bad that they can't get worse. |
|
|
jlucas
Joined: 08 May 2011 Posts: 41 Location: Carthage, MO
|
|
Posted: Thu Oct 25, 2012 4:54 pm |
|
|
Quote: | I want to clarify something before going any further:
1. If you don't get any characters from the GPS device for 4-8 seconds
then you want to send a character to the GPS device. Is that true? |
Actually, I want to send the character to a different device, a 16F685. I already have one-way RS-232 communication with that chip.
Code: | #use rs232(baud=9600, xmit=PIN_B0, stream=mc) |
Quote: | 2. Are you using the hardware UART in the 18F4520 to send and receive characters to/from the GPS? |
I'm not using the UART. I have RS-232 set up to send and receive data to and from a data radio module.
Code: | #use rs232(baud=57600, xmit=PIN_E1, rcv=PIN_C0, timeout=10, stream=ac) |
The GPS receiver is in the vehicle transmitter, and it sends only the 28 bytes of data that I need. Right now, I'm working on the code for the receiver to get it to send a byte to the 16F685 when I don't get data from the RF module for 4-8 sec. _________________ Always remember, things are never so bad that they can't get worse. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Oct 25, 2012 5:06 pm |
|
|
Why not use one of the hardware timers?
Mike |
|
|
|