I seem to be posting a lot at the moment - apologies.
I'm using 08M2 to monitor a mechanical (not optical) rotary encoder with an integrated switch. The output is a serial stream of "L" for one step anticlockwise, "R" for one step clockwise, or "P" for a push on the hardware serial port (which on the 08M2 is also the programming output port).
The code to do this is pretty simple with just one oddity to handle. Basically it interrupts on either the switch or one of the encoder channels and exits the interrupt when all the inputs are back to the default high condition. It uses the state of the second encoder channel at the time of interrupt to decide if the rotation is left or right. The one oddity is that it must handle a button push when the encoder is in a middle state. This is programmed with a standard counter based debounce.
All this works perfectly. Except.....
If I abuse the encoder repeatedly going left, right, pushing, and repushing over and over again then eventually the program will stop responding and nothing will wake it up except a reset.
I've done everything possible to debug this and am coming to the conclusion that there may some sort of a bug in the 08M2 firmware. By putting a toggle c.2 command in the interrupt routine, it looks like the program is running but no output is being produced which suggests that the issue is in the hardware serial output routine (but I may of course be mis-interpreting).
The hardware uses the enhanced serial circuit and the encoder inputs are pulled high with 4K7 resistors and have a 0.1uF capacitor across the contacts, the 08m2 is properly decoupled and the power supply is a bench supply through a LM2940 with all the usual capacitors.
Before anyone suggests it, I can't use sertxd or serout as they take too long to complete and when turning the encoder fast pulses are missed. Nor can I put the writes in the main program as then they would be delayed too much.
I don't think in normal use the bug would arise but the code is going into a module I'm developing for someone else so I want it perfect
Any help appreciated
Peter
I'm using 08M2 to monitor a mechanical (not optical) rotary encoder with an integrated switch. The output is a serial stream of "L" for one step anticlockwise, "R" for one step clockwise, or "P" for a push on the hardware serial port (which on the 08M2 is also the programming output port).
The code to do this is pretty simple with just one oddity to handle. Basically it interrupts on either the switch or one of the encoder channels and exits the interrupt when all the inputs are back to the default high condition. It uses the state of the second encoder channel at the time of interrupt to decide if the rotation is left or right. The one oddity is that it must handle a button push when the encoder is in a middle state. This is programmed with a standard counter based debounce.
Code:
#picaxe 08M2
setfreq m32
symbol switched = b0
symbol reread = b1
symbol notpushed=b2
symbol waspush=b3
symbol debouncecount=b4
symbol rightpossible=b5
symbol nosecondedge=b6
symbol true=1
symbol false=0
'
'Connections
' Encoder switch pulled high and connected to C.1 (pin6)
' Encoder output1 pulled high and connected to C.3 (pin4)
' Encoder output2 pulled high and connected to C.4 (pin3)
'
'
symbol encodermask = %00011010 ' ports c.3, c.4, c.1 pulled high
symbol interruptmask = %00010010 ' allow interrupts on c.4, c.1
symbol rotateleft = %00000010 ' c.1 high, c.4 and c.3 low
symbol rotateright = %00001010 ' c.4 low, c.3 high c.1 high
symbol clicked = %00011000 ' c.1 low, c.4 and c.3 high
hsersetup B9600_32,2
dirsc=0
setint OR 0,interruptmask
disconnect
do
loop
interrupt:
switched=pinsc & encodermask 'look at just the three inputs
rightpossible=false 'initialise the right rotate flag
debouncecount=0
if switched = clicked then 'simple button push
hserout 0,("P")
waspush=true 'set that it can't be pushed again while in the interrupt with switched=clicked
endif
if switched = rotateright then
rightpossible=true 'we have seen the front edge of the leading pulse but don't confirm until we see the edge of the second pulse
waspush=false
endif
if switched = rotateleft then 'both inputs immediately so must be left pulse leading as this doesn't interrupt
hserout 0,("L")
waspush=false
endif
do 'now loop until the interrupt condition is removed
reread=pinsc & encodermask
nosecondedge=reread & clicked 'see if both encoder inputs are now low
if rightpossible=true and nosecondedge=0 then 'we now have both inputs low so the right is confirmed
hserout 0,("R")
rightpossible=false
endif
if switched<>clicked then 'test for push while waiting for rotary to reset
if pinc.1=0 and waspush=false then 'the button has been pushed while the rotary encode is in an intermediate state
inc debouncecount 'increment the debouce counter
if debouncecount > 50 then 'valid button push
hserout 0,("P")
waspush=true 'set that a button push is no longer valid
debouncecount=0 'initialise a counter to debounce the back edge of the button push
endif
endif
if pinc.1=1 and waspush=true then 'the button is no longer pushed so increment a debounce counter
inc debouncecount
if debouncecount>50 then
waspush=false 'set that a push is now allowed again (but only if the original interrupt was not a push)
debouncecount=0
endif
endif
endif
loop until reread=encodermask ' all inputs back to high state
setint OR 0,interruptmask
return
If I abuse the encoder repeatedly going left, right, pushing, and repushing over and over again then eventually the program will stop responding and nothing will wake it up except a reset.
I've done everything possible to debug this and am coming to the conclusion that there may some sort of a bug in the 08M2 firmware. By putting a toggle c.2 command in the interrupt routine, it looks like the program is running but no output is being produced which suggests that the issue is in the hardware serial output routine (but I may of course be mis-interpreting).
The hardware uses the enhanced serial circuit and the encoder inputs are pulled high with 4K7 resistors and have a 0.1uF capacitor across the contacts, the 08m2 is properly decoupled and the power supply is a bench supply through a LM2940 with all the usual capacitors.
Before anyone suggests it, I can't use sertxd or serout as they take too long to complete and when turning the encoder fast pulses are missed. Nor can I put the writes in the main program as then they would be delayed too much.
I don't think in normal use the bug would arise but the code is going into a module I'm developing for someone else so I want it perfect
Any help appreciated
Peter
Last edited: