Project - Rotary XYZ Navigation



Uses a rotary encoder to navigate horizontal X axis, and/or vertical Y axis, and optionally adjust a Z axis value.

Useful for menu navigation, even with nested multi-level sub-menus.
Or use to select and adjust the individual value of a neo-pixel, or LED, or servo, or whatever.

Imagine the 3 axis colours as being connected to the red, green and blue pins of an RGB LED.
Rotate the encoder to adjust the red value up or down, then press the button to adjust the green value,
then press again to adjust the blue value. Press again to wrap around back to red again.
Long press to optionally exit adjustment mode or do anything else you want it to do.

You decide how many different axis you want to step through before wrapping around again, and you decide how many steps each axis has.

It may be easier to understand if you think of it being used to set the time, which only needs 2 axis.
Use the X axis to select Hours, Minutes, or Seconds, then press to the Y axis to adjust the selection up or down. Press again to return back to X.

Or add as many other axis as required.
Eg: adjust to select a specific neo-pixel, then press to adjust its Red value, press again to adjust Green, and again to adjust Blue, then wrap back.

The script is a modification of the previous Rotary Combination Lock, which uses exactly the same circuit.
So you can use the same optional TM1637 4-digit 7-segment display to show the X, Y,  Z values if you wish:
X is shown (4) on the left, Y (2) is on the right, and Z adjusts digit brightness from 0 (off) to 7 (full on).

Short-pressing the button will step through each axis then wrap back to X. 
You can easily stop any axis from wrapping around if you prefer - ie: to prevent jumping from off to full on.

A long press of 2 secs or more can jump wherever you choose - so in the case of setting the clock time, a long press could exit time setting mode.

The X, Y, and Z values are available in those variable names for you to use if needed, ie: perhaps to select an appropriate menu and sub-menu.
Or you might just want to change volume up or down, or position a servo - it is merely a means of adjustment that you may find handy some day.
  
Basic:
'                                              Rotary XYZ Navigation
rotaryA = 4                            'Rotary encoder pulse A output pin
rotaryB = 5                            'Rotary encoder pulse B output pin
buttonpin = 0                         'Rotary encoder selector button pin
TM1637.SETUP 12, 13         'Enter your appropriate SDA and SCL pins
TMbrightness = 4                   '7=bright, 1=dim, 0=off
axis = 0                                  'Currently selected axis: x=0, y=1, z=2
x = 1                                       'X horizontal axis
xmin = 1                                 'x minimum, lower values will wrap around to xmax
xmax = 99                              'x maximum, higher values will wrap around to xmin
y = 1                                       'Y vertical axis
ymin = 1                                  'y minimum, lower values will wrap around to ymax                     
ymax = 99                               'y maximum, higher values will wrap around to ymin
z = 4                                        'Z axis
zmin = 0                                  'z minimum, lower values will wrap around to zmax
zmax = 7                                 'z maximum, higher values will wrap around to zmin
xy$ = ""                                    'used to display both x and y values at the same time
debounce = 120                      'to avoid spurious jitter pulses, reduce to increase rotary response time
lasttime = 0
thistime = 0
start = 0
stop = 0
xy$ = right$(" " + str$(x),2) + right$(" " + str$(y),2)
TM1637.PRINT xy$, 4, 255
pin.mode buttonpin, input, pullup
pin.mode rotaryA, input, pullup
pin.mode rotaryB, input, pullup
interrupt rotaryA, changed
interrupt buttonpin, button
wait

changed:
thistime = millis
if thistime - lasttime > debounce then
 if pin(rotaryA) = 0 then
  if pin(rotaryB) = 0 then
  'down
   if axis = 0 then
    x = x - 1
    if x < xmin then x = xmax
   endif
   if axis = 1 then
    y = y - 1
    if y < ymin then y = ymax
   endif
   if axis = 2 then
    z = z - 1
    if z < zmin then z = zmax
   endif
  else
  'up
   if axis = 0 then
    x = x + 1
    if x > xmax then x = xmin
    endif
   if axis = 1 then
    y = y + 1
    if y > ymax then y = ymin
   endif  
   if axis = 2 then
    z = z + 1
    if z > zmax then z = zmin
   endif
  endif
  xy$ = right$(" " + str$(x),2) + right$(" " + str$(y),2)
  TM1637.PRINT xy$, z, 255
  lasttime = thistime
 endif
endif
return

button:
if pin(buttonpin) = 0 then start = millis else stop = millis
if stop > (start + debounce) then
 if stop - start < 2000 then
  'short press - step through each axis
  axis = axis + 1
  if axis > 2 then axis = 0      'change to 1 if only x and y required
 else
  'long press - put your long press gosub here
  wlog "long press"
 endif
endif
return

'----------- End ----------



Robin Baker,
Jul 4, 2018, 3:15 PM
v.1