View previous topic :: View next topic |
Author |
Message |
newguy
Joined: 24 Jun 2004 Posts: 1908
|
temperature extremes causing errors |
Posted: Thu Jan 04, 2007 12:18 pm |
|
|
I have a product that works perfectly at room temperature, but sometimes (not always) will start to act up at temperatures around -20C. Needless to say, I need it to work at -20C. I've traced the problem to the "ordinary" startup code at the beginning of the program not always doing what it is supposed to do. I'm going to build in a bulletproof solution by periodically checking the critical registers and reloading them with the correct values if they're not right.
The stuff that's acting up is this:
Code: | void main() {
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_spi(FALSE);
setup_wdt(WDT_ON);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128|RTCC_8_bit);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_CANRX1);
enable_interrupts(INT_CANRX0);
enable_interrupts(GLOBAL);
setup_oscillator(False);
old_portc = 0xff;
old_porta = 0x0f;
can_init();
can_set_mode(CAN_OP_NORMAL);
set_tris_c(0xff);
set_tris_a(0x0f);
output_a(0x00);
set_tris_b(0x08);
output_b(0x00);
init_variables();
while (TRUE) {
// "meat" of program here
}
} |
What I'm having trouble wrapping my head around is the set_tris_c(0xff) line. It seems that sometimes one line (C6 in particular) gets set to an output instead of an input. The processor is a 18F2480, and I'm not using the built-in UART. It's the "industrial" temperature model, rated for -40C to +85C. I have a bunch of external momentary switches hooked up to port C, and each of these lines is externally pulled high by 10k resistors. Closing a switch grounds an input line. The switches are scanned every 13 ms (approx) which is controlled by the timer 0 interrupt. There are no hardware faults/issues - this is purely a software thing. The switch hooked to C7 sometimes has issues as well, but this is purely intermittent - sometimes it works, sometimes not, without cycling the power. If the C6 input isn't working, only cycling the power will correct it.
I suspect the UART is somehow being enabled (or not disabled) since C6 is also the UART's TX output and C7 is its input. I can't see why this should be happening, but the evidence is leading me in this direction.
Does anyone have any anecdotes/opinions on what could be going on? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 04, 2007 12:23 pm |
|
|
It could be a RMW problem with the TRISC register. CCS normally
guards against this by using a shadow register for TRISC. That feature
may not be enabled for the 18F2480 in your version of the compiler.
What's your version ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Jan 04, 2007 12:24 pm |
|
|
3.236. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 04, 2007 1:21 pm |
|
|
Can you post your #fuses statement and all of your #use statements ?
Also, what is the Vdd voltage for the PIC, and the oscillator frequency ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Jan 04, 2007 1:39 pm |
|
|
Geez. It's a 2680, not a 2480. Sorry about that.
Here are the fuses:
Code: | #include <18F2680.h>
#device adc=8
#FUSES WDT
#FUSES WDT1 //Watch Dog Timer uses 1:1 Postscale
#FUSES HS //Crystal osc > 4mhz
#FUSES PROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV28 //Brownout reset at 2.8V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES BBSIZ2K //2K words Boot Block size
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOMCLR //Master Clear pin NOT enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=10000000,RESTART_WDT) |
Oscillator, as you can see, is 10 MHz. Vdd = 5V. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Jan 04, 2007 2:51 pm |
|
|
Whoops, forgot the #use directives. I'm using fast_io for all ports (A, B and C). |
|
|
rwskinner
Joined: 08 Dec 2006 Posts: 125 Location: Texas
|
|
Posted: Thu Jan 04, 2007 4:01 pm |
|
|
I did not look at your code, thats better suited for someone else. But I had a idea that I've seen cause problems.
We had numerous systems in the field that during extreme cold, the switch membrane in the buttons would contract, randomly pushing buttons and fire interrupts. We would have changed system settings just like some one was keying them in that way.
We finally disconnected the keypad and our problem went away. The keypad manufacturer then modified our keypads to fix the problem.
I'm not stating in anyway this is your problem, but I wanted to throw that out there since your talking buttons and extreme cold. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 04, 2007 4:07 pm |
|
|
Quote: | It seems that sometimes one line (C6 in particular) gets set to an output instead of an input |
How do you know that it gets set to an output ? Does the TRISC
register change ? What are the symptoms that tell you it's set to
an output ? Is it a high-level or a low-level output ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Jan 04, 2007 4:48 pm |
|
|
PCM programmer wrote: | Quote: | It seems that sometimes one line (C6 in particular) gets set to an output instead of an input |
How do you know that it gets set to an output ? Does the TRISC
register change ? What are the symptoms that tell you it's set to
an output ? Is it a high-level or a low-level output ? |
Here's what I have observed, along with some more details on my setup.
I have a 10k pullup resistor on that (and all other) input pins. All these inputs get routed to ordinary momentary NO switches. They're not pushbuttons or membrane contact switches (thanks for the idea, though rwskinner), but rather standard snap switches which are hermetically sealed (or are supposed to be). They look like figure 2 at the top of this page: http://dkc3.digikey.com/PDF/C071/1701.pdf
I have 12 switches total that I must monitor: 8 on port C, and 4 on port A. When I tested the unit cold (approx -20C), switch presses were detected and processed correctly for all inputs except for C6, and sometimes (but not always) C7. Repeatedly pushing the switch attached to C7 eventually got that one to work without cycling the power to the unit, so I think (but I'm not entirely sure) that it may have been caused by bad contacts in the switch, or frost on the contacts. I doubt this, however, because it's a brand new switch and it's supposed to be a sealed unit.
No matter how long I waited or how many times I pushed it, the system totally ignored the switch attached to C6. I verified that the input was in fact 5V with the switch open, and it did fall to 0V when it was closed. I then cycled the power and suddenly the system started to recognize the C6 switch again. The unit was still cold when I cycled the power. I haven't had a chance to refreeze the thing & try again, but the system only acted up once. I haven't been able to duplicate that problem once the system started to warm up.
If it was being set to an output, I can't safely say that the PIC wasn't driving that pin high because the PIC wouldn't "win" against a 0 ohm switch. And I'm pretty sure that the idle level for the USART's TX pin (which is C6) is high.
I can verify that the hardware did have the proper voltage levels at pin C6 itself. However, the PIC didn't react to changes on that pin, but did react to changes on all the others (intermittent problems with C7 aside).
I will wait for the next temperature cycle(s) to see if the problem repeats. However, I doubt that it will: I added 4 if's to my timer 0 interrupt code to check the tris register of all 3 ports and change them if they're not correct, and the last one checks the USART and will disable it if it isn't disabled (clear SPEN bit in RCSTA). If the USART was enabled somehow or if the tris weren't correct after initialization, this will take of it. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 04, 2007 5:22 pm |
|
|
I tried to make a simple test program. I don't have your PIC, so
it's worth too much. I ran this on a PicDem2-Plus board and froze
the PIC with chill spray. I jumpered the button on Pin A4 over to
pin C6. It always worked. The LED tracked the button pushes.
I'd have to buy an 18F2680 to test this further.
Code: |
#include <18F452.h>
#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=10000000)
#use fast_io(c)
//================================
void main()
{
int8 value;
set_tris_c(0xFF);
while(1)
{
value = input_c();
if((value & 0x40) == 0)
output_high(PIN_B0); // Turn on LED
else
output_low(PIN_B0); // Turn off LED
} |
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Fri Jan 05, 2007 1:42 pm |
|
|
ESD. At least that's the only thing I can think of to explain it.
I swapped the processor for a new one and now it works without the funny behaviour. Thanks for everyone's time and opinions. |
|
|
|