Help please, with Rotary Encoder (code) from 08m to 40X2...

OLDmarty

Senior Member
I cannot see any obvious reason that it wouldn't keep accurate count or why one would interact with the other.

Does it work correctly when you remove your display interfacing code ?

It could be because you are updating your displays every loop rather than only when the values have changed.
Yes, i was wondering about 'where' i placed my display code processing in the main loop and whether i'm missing something by 1 cycle etc.

I'll remove my code sections and just focus on your main loop wih equations and monitor the terminal for any funny changes that i saw today.
I'll send my update tomorrow once i know more ;-)
 

OLDmarty

Senior Member
Hi Hippy,

OK, i have rem'ed out the following sections of my code, so it's basically just the rotary encoder/maths doing its thing:
Code:
;##################################################################
select case countb
    case  0 : gosub blankit
    case  1 : gosub blankit : ROW_1 = _F0    ;Set to Pre-defined value of "$F0"
    case  2 : gosub blankit : ROW_1 = _0F    ;Set to Pre-defined value of "$0F"
    case  3 : gosub blankit : ROW_2 = _F0
    case  4 : gosub blankit : ROW_2 = _0F
    case  5 : gosub blankit : ROW_3 = _F0
    case  6 : gosub blankit : ROW_3 = _0F
    case  7 : gosub blankit : ROW_4 = _F0
    case  8 : gosub blankit : ROW_4 = _0F
    case  9 : gosub blankit : ROW_5 = _F0
    case 10 : gosub blankit : ROW_5 = _0F
    case 11 : gosub blankit : ROW_6 = _F0
    case 12 : gosub blankit : ROW_6 = _0F
    case 13 : gosub blankit : ROW_7 = _F0
    case 14 : gosub blankit : ROW_7 = _0F
    case 15 : gosub blankit : ROW_8 = _F0
    case 16 : gosub blankit : ROW_8 = _0F

    case 17 : gosub blankit
endselect
;##################################################################

;  Get the 7-SEG display value(s) ######
      lookup countA,($30,$6D,$79,$33,$5B,$5F,$70,$7F,$7B,$7E,$30,$6D,$79,$33,$5B,$5F),SEG7_2    ;Load 7-SEG values onto 7-seg Display(s)
      if countA > 8 then        ; when 'counter'(lookup) becomes greater then the 9th digit (0 to 8, is 9 counts)...bring on the 10's digit for numbers 10 to 16.
       SEG7_1 = $30        ; Turn on the 10's digit (1) for numbers 10 to 16 on the LEFT 7-seg display.
       else seg7_1 = $00    ; if 'counter' is 9 or less, then turn OFF the `10's digit (1) again, for numbers 1-9 in the RIGHT 7-seg display.
    endif

After a re-program, the terminal opens and i started turning encoder B to observe the following data of B and A.


Notice B changes by 1's as i turn it, while A changes by 2's and sometimes 1's whenever it feels like it ;-)
As i mentioned yesterday, i saw A changing by 4's on each click of B.

Code:
Here's a capture of todays data.
Also odd to note, that when i turn A a few times, then go back to turning B, i then get "B only" data. 
It's like something between the 2 encoders/maths gets reset or cleared to a clean state,
then both A and B operate correctly without affecting the other.

Additionally odd, is that i can re-power the project and then A and B will still remain independant. 
If i power up the project later in the day, The A/B then sometimes alter each other.

My +5volts is solid and i've changed picaxe chips to rule out the chip is flakey in some way.

Started
A = 17
B = 1
A = 15
B = 2
A = 13
B = 3
A = 11
B = 4
A = 8
B = 5
A = 7
B = 6
A = 5
B = 7
A = 3
B = 8
A = 1
B = 9
A = 16
B = 10
A = 15
B = 11
A = 13
B = 10
A = 11
B = 9
A = 9
B = 8
A = 7
B = 7
A = 5
B = 6
A = 3
B = 5
A = 1
B = 4
A = 17
B = 3
A = 16
A = 15
B = 4
A = 13
B = 5
A = 11
B = 6
A = 8
B = 7
A = 7
B = 8
A = 5
B = 9
A = 3
B = 10
A = 1
B = 11
A = 17
B = 12
A = 15
B = 13
A = 13
B = 14
 

hippy

Technical Support
Staff member
It all seems to work as expected when simulated as far as I tested it, which included the display code, so could it be a hardware issue in moving the pins around ?

Are your pull-up or pull-downs in the right places ?

You could also try swapping the CLK/DAT wiring around in case it is something to do with the encoders themselves. That means the encoders will work in the opposite directions but that can be corrected in software later if that was the issue.
 

OLDmarty

Senior Member
It all seems to work as expected when simulated as far as I tested it, which included the display code, so could it be a hardware issue in moving the pins around ?

Are your pull-up or pull-downs in the right places ?

You could also try swapping the CLK/DAT wiring around in case it is something to do with the encoders themselves. That means the encoders will work in the opposite directions but that can be corrected in software later if that was the issue.
HI Hippy,
Yes, all wiring is correct as i'm using the exact same encoders/box as used in previous code versions when it all worked solid.

I've actually reverted back to some earlier code (for 2 encoders) and re-enabled the LED displays etc which is working solid, but i think there were limitations of the endless and end-stop maths.

I've power cycled the project 10 times and the A/B rotarys have never affected each others settings.

I've now gone back to the latest (yesterday) code, and on first power up, A immediately affected B when i rotated A.
Once B is moved, then both A and B control their own data, not each others.....as i said, i feel something is being cleared for the latest code to work correctly most times, but powering up from the start seems to be loading a variable with something weird, somewhere ;-(

I've now re-re-programmed the previous (2 encoder) code, which works upon 10 powerups without failure, just like when i used it 20 mins ago.

The 2-encoder working code is here, for comparison between yesterdays code i posted:
Code:
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600

;setfreq m16    ;ENABLE this when not using the serial terminal, for final product (sppeds up rotary pot reads and LED matrix updates).

;Initialize:                ' Initialise pins and set up variables
;Setup all the port bits to a clean state...
dirsA=$00:dirsB=$00:dirsC=$FF:dirsD=$00                ;11111111, Port C as OUTPUTS, Port A,B & D as INPUTS
outpinsA=$00:outpinsB=$00:outpinsC=$00:outpinsD=$00        ;00000000, clear ALL Port outputs to all 0's

;
Hi2cSETUP  i2cmaster,%11100000, i2cfast, i2cbyte
PAUSE 10 ; wait 1 ms for the display chip to initialise
Hi2cOUT ($21) ; start clock/oscillator
; $00 turns off the whole row
;

Symbol MASKA = %00010000 ; D.4
Symbol MASKB = %01000000 ; D.6
Symbol MASK  = %01010000 ; All of the above

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

Symbol Buffer1 = b22    ;Temp holding buffer variable

Symbol ROW_1 = b23    ;RGB LEDS 1 & 2
Symbol ROW_2 = b24    ;RGB LEDS 1 & 2
Symbol ROW_3 = b25    ;RGB LEDS 1 & 2
Symbol ROW_4 = b26    ;RGB LEDS 1 & 2
Symbol ROW_5 = b27    ;RGB LEDS 1 & 2
Symbol ROW_6 = b28    ;RGB LEDS 1 & 2
Symbol ROW_7 = b29    ;RGB LEDS 1 & 2
Symbol ROW_8 = b30    ;RGB LEDS 1 & 2

Symbol _F0 = b40    ;RGB LEDS 1 & 2
Symbol _0F = b41    ;RGB LEDS 1 & 2

Symbol SEG7_1 = b31    ;SEG7-1 is the LEFT  side display, (the 10's column).
Symbol SEG7_2 = b32    ;SEG7-2 is the RIGHT side display. (the  1's column).
  
Hi2cOUT ($80) ; clear the display
Hi2cOUT ($EF) ' set to full brightness

ROW_1 = $00 : ROW_2 = $00 : ROW_3 = $00 : ROW_4 = $00 : ROW_5 = $00 : ROW_6 = $00 : ROW_7 = $00 : ROW_8 = $00

_F0 = $F0    ;Pre-defined "$F0" buffer
_0F = $0F    ;Pre-defined "$0F" buffer



PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If



  

 
;##################################################################
select case countb
    case  0 : gosub blankit
    case  1 : gosub blankit : ROW_1 = _F0    ;Set to Pre-defined value of "$F0"
    case  2 : gosub blankit : ROW_1 = _0F    ;Set to Pre-defined value of "$0F"
    case  3 : gosub blankit : ROW_2 = _F0    
    case  4 : gosub blankit : ROW_2 = _0F    
    case  5 : gosub blankit : ROW_3 = _F0    
    case  6 : gosub blankit : ROW_3 = _0F
    case  7 : gosub blankit : ROW_4 = _F0    
    case  8 : gosub blankit : ROW_4 = _0F
    case  9 : gosub blankit : ROW_5 = _F0
    case 10 : gosub blankit : ROW_5 = _0F
    case 11 : gosub blankit : ROW_6 = _F0    
    case 12 : gosub blankit : ROW_6 = _0F    
    case 13 : gosub blankit : ROW_7 = _F0    
    case 14 : gosub blankit : ROW_7 = _0F
    case 15 : gosub blankit : ROW_8 = _F0    
    case 16 : gosub blankit : ROW_8 = _0F
endselect
;##################################################################  
   
  
   
   

      lookup countA,($30,$6D,$79,$33,$5B,$5F,$70,$7F,$7B,$7E,$30,$6D,$79,$33,$5B,$5F,$70),SEG7_2    ;Load 7-SEG values onto 7-seg Display(s)
      if countA => 9 then        ; when 'counter'(lookup) becomes greater then the 9th digit (0 to 8, is 9 counts)...bring on the 10's digit for numbers 10 to 16. 
       SEG7_1 = $30        ; Turn on the 10's digit (1) for numbers 10 to 16 on the LEFT 7-seg display. 
       else seg7_1 = $00    ; if 'counter' is 9 or less, then turn OFF thge `10's digit (1) again, for numbers 1-9 in the RIGHT 7-seg display.
    endif
   
   
     ;  SEND_TO_MATRIX:    ;#######
;                              |                   |                   |                   |                    |                     |                     |                    |
;          A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7   A8..A15  |  A0..A7    A8..A15  |  A0..A7    A8..A15  |  A0..A7    A8..A15 |
;                              |                   |                   |                   |                    |                     |                     |                    |
Hi2cOUT $00, (ROW_1, SEG7_1,            ROW_2,  SEG7_2,    ROW_3,    $00,      ROW_4, $00,          ROW_5,   $00,        ROW_6,   $00,         ROW_7,   $00,          ROW_8,   $00)
Hi2cOUT ($81) ; turn on the display

  Loop


Interrupt:

  b0 = pinsD

  If bit4 <> 0 Then
    CountA = CountA + bit5 Min 1 + bit5 - 1 Max 16
  End If

  If bit6 <> 0 Then
        countB = CountB + bit7 Min 1 + bit7 - 1 Max 16
 End If
  
  b0 = b0 And MASK
  SetInt Not b0, MASK, D
  Return

Interrupt_Enable:
  b0 = pinsD And MASK
  SetInt Not b0, MASK, D
  Return
  
  
  blankit:
  ROW_1 = $00 : ROW_2 = $00 : ROW_3 = $00 : ROW_4 = $00 : ROW_5 = $00 : ROW_6 = $00 : ROW_7 = $00 : ROW_8 = $00
  return
 

hippy

Technical Support
Staff member
I cannot see anything significantly different between the code which works and the code which doesn't. I would suggest taking the code which works, adding this at the top and checking it still works ...
Code:
#Define PORT       D         ; D.x

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7
I would then set about altering one thing at a time, replacing the hard-coded name in the working code with the above defined names and checking it still works after each change.

If it stops working the change which stopped it working should be revealed.

If it keeps working then the only thing it could be is the counting calculations, whether limited or roll-over. Change those one at a time and we should see which that is.
 

OLDmarty

Senior Member
I cannot see anything significantly different between the code which works and the code which doesn't. I would suggest taking the code which works, adding this at the top and checking it still works ...
Code:
#Define PORT       D         ; D.x

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7
I would then set about altering one thing at a time, replacing the hard-coded name in the working code with the above defined names and checking it still works after each change.

If it stops working the change which stopped it working should be revealed.

If it keeps working then the only thing it could be is the counting calculations, whether limited or roll-over. Change those one at a time and we should see which that is.
Hmmmm, sadly today i discovered the full code (post #44) is also buggy, where A and B sometimes affect each other.

I only noticed it when i added in the code section from above (post #45), but as i managed to rem out every line of post #45, i noticed the original main code still bugs out after a while.


The bug seems to appear after a certain amount of encoder changes, i haven't found the exact number of times yet, but if i turn encoder A,B,A,B,A,B a few times each way, it's probably after the 8th or 10th time that the bug appears.
It's like a counter value somewhere is interfering, but then cleared buy something else until more encoder 'changes' have occurred to flag the buggy bit again.
 

hippy

Technical Support
Staff member
It's like a counter value somewhere is interfering, but then cleared buy something else until more encoder 'changes' have occurred to flag the buggy bit again.
If there is nothing in the code causing such interaction, nothing in the PICAXE firmware causing that, then it has to be some kind of timing or hardware issue.
 

OLDmarty

Senior Member
If there is nothing in the code causing such interaction, nothing in the PICAXE firmware causing that, then it has to be some kind of timing or hardware issue.
No probs, i'll keep dabbling and try to note some kind of common pattern that makes the problem arise.

On a side note, i think i mentioned this earlier in this thread (or another of my threads), but my 2 encoders are mounted in a plastic enclosure along with 4 analog pots.
The 4 pots are permanently wired into analog inputs on D.0, D.1, D.2 & D.3, while the A/B terminals of each of the 2 encoders are wired into D.4,D.5 and the other encoder into D.6 & D.7.
I *think* the masking in the main code is ruling out D.0 to D.3 having any affect on the program running.

The ribbon cable (IDC16) from this plastic enclosure is connected to my picaxe proto-board and the ribbon is 1 metre long.
There are no decoupling caps on ANY of the PortD pins, could this be a problem with stray coupling along the length of the ribbon cable?
I wouldn't think this would be a problem, unless i sending a few MHz down each wire, but in this case of simple very low frequency switch pulses, i would have thought it wouldn't be a problem?

NOTE:
I do have a 0.1uf on the actual picaxe (40X2) socket between the power/GND pins for general IC decoupling and that's about it.
 

techElder

Well-known member
The ribbon cable (IDC16) from this plastic enclosure is connected to my picaxe proto-board and the ribbon is 1 metre long.
Shorter is "better", but unless you live next door to a radio transmitter that shouldn't cause problems. It is better to use bypass caps on long lines, but that is a somewhat theoretical or CYA type of solution.
 

hippy

Technical Support
Staff member
It could be an issue of stray capacitance or other interference between lines. The best way to check that is to test with shorter wires and with only the encoders connected. If that works reliably but the ribbon cable doesn't then that would suggest it is the cable causing the problem.

Any long wire can act as a receiving antenna and any switching current through a wire can cause it to act as a radiating antenna. What value pull-ups or pull-downs do you have on the encoder signals ? Are they at the encoder end or the PICAXE end ?
 

OLDmarty

Senior Member
It could be an issue of stray capacitance or other interference between lines. The best way to check that is to test with shorter wires and with only the encoders connected. If that works reliably but the ribbon cable doesn't then that would suggest it is the cable causing the problem.
That's a good point, certainly worth trying to eliminate what's really going on.
FYI: i have wired the IDC16 in a unique way so that the D.0 to D.7 bits are all wired along 1 row of the IDC16 connector.
The opposite row of the IDC16 has 4 GND's, 2x5v's and 2x 3.3v's.
This means that EVERY D.x wire has either a GND or a rail on either side of it as an attempt to stop inter-bit cross-coupling when i first started wiring these ribbons for my main test bed.


Any long wire can act as a receiving antenna and any switching current through a wire can cause it to act as a radiating antenna. What value pull-ups or pull-downs do you have on the encoder signals ? Are they at the encoder end or the PICAXE end ?
Ahhh, good point too, the 4K7 pullDOWNS are on the encoder end, not the picaxe end.

I'm starting to feel the picaxe-end (pins) might look disgusting on a CRO if i dare to look ;-)
 
Last edited:
Top