|
|
View previous topic :: View next topic |
Author |
Message |
tssir
Joined: 14 Feb 2016 Posts: 24
|
18F26k22 randomly not waking-up on int_rb |
Posted: Fri May 06, 2016 9:32 am |
|
|
Hello.
I have one pic with a keyboard switch on RB5.
When I press switch, led comes red. When I release it, led comes off.
But, randomly (1/100), pic not execute code above sleep, after an int_rb callback. Red led keep on, while key is released.
Here the minimal code :
Code: | #include <18F26k22.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,NOLVP,NOMCLR,NOPUT,BROWNOUT,NOFCMEN,NOSTVREN,NOPLLEN,NOIESO,NOPBADEN,NOHFOFST,NOSTVREN,NOXINST,NODEBUG,NOCPB,NOWRT,NOWRTC,NOWRTB,NOWRTD,NOEBTR,NOEBTRB
#USE delay(clock=16000000)
#USE fast_io(A)
#USE fast_io(B)
#USE fast_io(C)
#define LED_OFF TRUE
#define LED_ON FALSE
#define IO_LEDB PIN_C2
#define IO_LEDR PIN_C3
#define IO_LEDG PIN_C4
unsigned int8 ioRawBState;
int1 inputRawB(iobOffset)
{
return ((ioRawBState >> iobOffset) & 0x01);
}
#INT_RB
void handler_rb(void)
{
// Keep port b value
ioRawBState=input_b();
}
#SEPARATE
main()
{
// 76543210
set_tris_a(0b00000111);
set_tris_b(0b10110100);
set_tris_c(0b10000000);
// 76543210
port_b_pullups(0b10110000);
// For hardware compliance
output_bit(PIN_C0,false);
output_bit(PIN_C1,false);
output_bit(IO_LEDR,LED_OFF);
output_bit(IO_LEDG,LED_OFF);
output_bit(IO_LEDB,LED_OFF);
output_bit(PIN_A3,true);
output_bit(PIN_A5,false);
output_bit(PIN_A4,false);
output_bit(PIN_A7,true);
output_bit(PIN_A6,false);
enable_interrupts(INT_RB5);
enable_interrupts(GLOBAL);
while(TRUE)
{
output_bit(IO_LEDG,LED_OFF);
sleep(SLEEP_FULL);
output_bit(IO_LEDG,LED_ON);
// Check RB5 saved value
if(!inputRawB(5))
output_bit(IO_LEDR,LED_ON);
else
output_bit(IO_LEDR,LED_OFF);
}
}
|
Green led (IO_LEDG) keep off. Then sleep full stop the execution properly.
If I move "check RB5 saved value" code into int_rb Handler code, it works perfectly. Every time I change RB5, red led (IO_LEDR) is ok. Then, I understand that int_rb is raised every time RB5 changes. But some times, int_rb does not Wake-up sleep command (randomly, I need to test one or two minutes to get error).
I should make some mistakes. But what ... I can't see.
Any idea ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri May 06, 2016 2:23 pm |
|
|
There are actually three different ways of working with INT_RB on different PIC's.
Oldest chips, only clear the condition when a byte wide input is done. So input_b.
Then there are some that have an erratum, and you must use 'bit' operations to clear the latch.
Then there are some that have another erratum/problem, and there must be at least one dummy instruction between the read and clearing the interrupt, and the read must not be done using MOVFF.
Yours is one of the third type.
It's hidden away in section 10.3.2 of the data sheet.....
You have to be sneaky:
So:
Code: |
#INT_RB
void handler_rb(void)
{
// Keep port b value
ioRawBState=input_b() & 0xFF;
}
|
Doing the '&' makes the compiler code it as a MOVF, not a MOVFF, and add one more instruction afterwards to write the result. |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Sun May 08, 2016 2:15 pm |
|
|
Thank you for those informations.
I tried this codes :
Code: | #include <18F26k22.h>
#DEVICE ADC=10
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,NOLVP,NOMCLR,NOPUT,BROWNOUT,NOFCMEN,NOSTVREN,NOPLLEN,NOIESO,NOPBADEN,NOHFOFST,NOSTVREN,NOXINST,NODEBUG,NOCPB,NOWRT,NOWRTC,NOWRTB,NOWRTD,NOEBTR,NOEBTRB
#USE delay(clock=16000000)
#USE fast_io(A)
#USE fast_io(B)
#USE fast_io(C)
#define LED_OFF TRUE
#define LED_ON FALSE
#define IO_LEDB PIN_C2
#define IO_LEDR PIN_C3
#define IO_LEDG PIN_C4
unsigned int8 ioRawBState;
int1 inputRawB(iobOffset)
{
return ((ioRawBState >> iobOffset) & 0x01);
}
#INT_RB
void handler_rb(void)
{
// Keep port b value
ioRawBState=input_b() & 0xFF; // Correction from Ttelmah 20160506
output_bit(IO_LEDB,LED_ON);
}
#SEPARATE
main()
{
// 76543210
set_tris_a(0b00000111);
set_tris_b(0b10110100);
set_tris_c(0b10000000);
// 76543210
port_b_pullups(0b10110000);
// For hardware compliance
output_bit(PIN_C0,false);
output_bit(PIN_C1,false);
output_bit(IO_LEDR,LED_OFF);
output_bit(IO_LEDG,LED_OFF);
output_bit(IO_LEDB,LED_OFF);
output_bit(PIN_A3,true);
output_bit(PIN_A5,false);
output_bit(PIN_A4,false);
output_bit(PIN_A7,true);
output_bit(PIN_A6,false);
enable_interrupts(INT_RB5);
enable_interrupts(GLOBAL);
while(TRUE)
{
output_bit(IO_LEDG,LED_OFF);
sleep(SLEEP_FULL);
output_bit(IO_LEDB,LED_OFF);
output_bit(IO_LEDG,LED_ON);
// Check RB5 saved value
if(!inputRawB(5))
output_bit(IO_LEDR,LED_ON);
else
output_bit(IO_LEDR,LED_OFF);
}
} |
The problem still exists, after 3 minutes of random pushing button.
I change code to detect interrupt call. In accordance with above code, blue led keeps "on" only at start. After each push/release on button (RB5 with internal pull-up), red led is "on" then "off". In normal operation no green led (IO_LEDG) and no blue (IO_LEDB).
After many tries on pushing button, red led and blue led keeps "on" after released button.
Conclusion : Interrupt handler is called at each RB5 changes, but no wake-up some times (blue led go "off" if sleep instruction is waking).
Strangely, this problem occur only on release button event. Never at push. I.e. at low->high changes.
Then I must modify my design. Full sleep when waiting push, and idle sleep with timer to check release (active sensing).
It's insane ... but it's the only way to get reliability. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Sun May 08, 2016 3:46 pm |
|
|
OK, go back to basic I/O 101.
What is the 'pushbutton'? Some cheap generic PB or a real PB designed for interfacing to a computer?
What kind of pullup and conditioning do you have for the PB?
What does the signal look like on a scope? Nice clean edges or 'noisy'?
Did you install a Schmitt chip in between the PB and the PIC?
Before you try any 'fancy' code, like sleeping.... confirm you get 1 input for every push of the button EVERY time. Yup, a dull boring job to do at least 1000 random presses but it has to be done.
If you can get 1000 perfect responses from your PB circuit then you've probably eliminated it as the source of 'random' failures.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon May 09, 2016 12:45 am |
|
|
Make one other change:
Code: |
sleep(SLEEP_FULL);
delay_cycles(1);
output_bit(IO_LEDB,LED_OFF);
|
The instruction _following_ the sleep instruction, is 'prefetched'. The read of it has already started, when you go to sleep. This is why it should be a 'NOP' (delay_cycles(1) codes as a NOP in CCS). Now if it wakes and interrupts, it is actually going to be 'inside' the operation to turn the LED 'OFF', when the interrupt is called to also turn it 'ON'. Don't know the effect of this, but this is why Microchip tell you to have a NOP here....
You are also never going to see the LED go 'ON' from the interrupt, since the instruction it returns to, turns it OFF. Rather pointless bit of code.
I would echo Temtronic's comments about the actual button/circuit. 'Real' buttons do not give nice simple on/off behaviour. They give multiple (often dozens!) of edges for a switch change. Often more on release than make.
Have a look at:
<http://www.labbookpages.co.uk/electronics/debounce.html>
Use bit_test instead of inputRawB. That is why the compiler has such functions!...
Further comment though. What decoupling have you got close to the actual chip?. The symptom you actually have is not of a chip failing to wake but a chip where the code is actually hung. Probably processor spiked by RF signal into an undriven pin, or simply spiked by the current transition as it switches the LED's.
Have you got a 0.1uF right adjacent to the PIC's supply connections?. What decoupling is on the supply?. What is the supply?. What are you doing with the unused pins?.
The chip is probably doing something like toggling the various LED's on and off several times at high speed, and it is this that is resulting in things going wrong....
One thing that would give problems, if the signal is giving nasty little 'spike' bounces, is this entry in the data sheet:
"If a change on the I/O pin should occur
when the read operation is being executed
(start of the Q2 cycle), then the RBIF
interrupt flag may not get set. Furthermore,
since a read or write on a port affects all
bits of that port, care must be taken when
using multiple pins in Interrupt-on-change
mode. Changes on one pin may not be
seen while servicing changes on another
pin."
If the edge just happens to change in the instruction reading the port in the interrupt handler, then potentially you have the value in ioRawBState, not matching what is actually on the port. The interrupt will not be re-triggered, and the code will fail.
You need to process the input signal to make it give clean edges, for the code to ever really hope to work...
Given that this chip only talks about the latches being changed when a port read is done, you could potentially 'bodge' the interrupt handler like this:
Code: |
#INT_RB noclear
void handler_rb(void)
{
// Keep port b value
do
{
ioRawBState=input_b() & 0xFF;
clear_interrupt(INT_RB);
}
while (bit_test(ioRawBState,5)!=input(PIN_B5));
}
|
This should then reload the ioRawState value, if the port has changed during the previous instruction. If it changes during the test, the interrupt flag will be set, so the routine will execute again (this is why the interrupt must only be cleared between the first read and the test).
This is a 'bodge' route, but could handle the situation of the input changing in the routine.
Beware though. You have three bits of RB4:7, set as inputs. If you poll the other ones of these (reading elsewhere in the code), these can potentially trigger the same problem. Much better to use these bits as outputs.
Last edited by Ttelmah on Mon May 09, 2016 8:05 am; edited 2 times in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Mon May 09, 2016 7:59 am |
|
|
As to Mr. T's comments about RF....
These days it is very important to bypass evry chip and input pin to eliminate any RF signal from giving false inputs! With the huge amount of 'wireless' devices around( modems,cameras,cellfones,etc) the air is not as 'clean' as it used to be. even power lines are great 'antenna'.
20 years ago had a 'semi random' PITA problem that was finally found to be 'cross talk' on a certain span pair in a certain cable in the Bell Telephone network. When I ran out of 'adjustments' on my system I had Bell rewire THEIR wires to eliminate the cross talk. problem solved. That event only took about 3 months to debug......sigh.
Have to ask , what is the power supply? It should be rated for 5-10X the overall max of the system at full load and be sure to use bypass caps where it enters the PCB! An underrated supply can 'dip' just enough to cause 'problems' but not enough to reset the PIC, BTDT.....
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon May 09, 2016 8:04 am |
|
|
I just updated my post with a bodge for one potential problem, but like you, was wondering about everything else in the circuit!... |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Mon May 09, 2016 8:45 am |
|
|
Pushbutton on RB5 is a simple CMS keyboard switch.
It is welded to multi-strand cable, then connect to PCB with Graupner JR connector (https://www.graupner.de/Servo-Verlaengerungsk0-3qmm-500mm/S8178/).
From an electrical point of view, the pushbutton is connected to RB5 by only a 4.7kOhm serie resistor. No schmitt trigger IC.
Just when I wanted to program the software débouncer, I noticed this problem. I can not use an hardware debouncer, because RB5 should be alternatively used with a serial signal remote control or a simple switch remote control. Software manage both modes with the same input.
I try asked modifications :
Code: | .................... while(TRUE)
.................... {
.................... output_bit(IO_LEDG,LED_OFF);
00120: BSF F8B.4
.................... sleep(SLEEP_FULL);
00122: MOVFF FD3,00
00126: BCF FD3.7
00128: SLEEP
0012A: MOVFF 00,FD3
.................... delay_cycles(1); // Correction from Ttelmah 20160509
0012E: NOP
.................... output_bit(IO_LEDB,LED_OFF);
00130: BSF F8B.2
|
Same result : Some times, red and blue led keeps "on" after releasing pushbutton.
I check signal by oscilloscope. I notice no significant noise. Push button signal is very clean. Direct to the ground.
But release button can sometimes be very dirty, as you can see :
Ok, it should be a good clue, because I only have problem with released pushbutton. But if it's a debouncing problem, why interruption raise without waking-up (demonstrated by previous tests) ?
All pins are connected and used. Supply output capacitor is a MnO2 680uF 4V 100mOhm (1 cm distant to SOIC CPU), with a MIC5225 regulator. It is battery powered, with a buck/boost converter for multi-voltage tests only. Pic is connected to a Bluetooth tranceiver, a TSK 433MHz tranceiver, a thermal sensor, mosfets drivers, leds, ... But test program disable all devices, except one RGB leds. No ground loop. Simple two sided PCB.
As asked, I add 100nF ceramic capacitor, directly welded on SOIC package pin 19 and 20 (VDD and VSS). I add 100nF plastic capacitor close to push-button, in parallel (not best debouncer, but for test). Now the push-button signal is always very clean, but very slow (16ms to reach VDD after released, with internal pull-up, not a problem for me).
After many, many, tries, the problem is solved. To reach my design, I need to add hardware debouncer on switch side (because I can not debounce on PCB side).
But I can not understand why pic not waking-up after interruption.
1) Maybe a strange side effect of something.
2) Or my led program test is not correct (green led if not going to sleep, blue led if not waking-up after interruption, red led if released is not computed by main function).
3) Or a slower input is usefull for full working wake-up (pic not recommended for a full software debounce).
Anyway, thank you for your advices. |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Mon May 09, 2016 8:49 am |
|
|
Sorry, I just saw that you have completed your posts while I was writing the mine while testing.
So I'll read yours now. |
|
|
tssir
Joined: 14 Feb 2016 Posts: 24
|
|
Posted: Mon May 09, 2016 9:13 am |
|
|
I experienced the same kind of problems with insufficient supply, that cause strange pic behaviour. Then I use a input diode to isolate Pic supply, good full protected regulator, and large capacitor in case of supply drop.
Ttelmah procedure is very clever. I would not have thought. |
|
|
|
|
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
|