Moode Forum

Full Version: Rotary encoder guru ?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi, first ever use of a rotary encoder.... connected 3.3v, GND, gpio 23, and 24.....
Config>audio> and set Rotary encoder to 'on'....   set MPD Config>volume control> software   (sort of counter intuitive as an encoder is a hardware item..???? ......but only options are 'disabled' and 'software')

Encoder works but needs several turns (10+) to go from low to high.... which of the parameters in the settings box do I need to change and to what to get quicker control ?

The encoder has a push switch.... is there a gpio pin to connect to that will enable mute toggle with this ?

Thanks !
bob
Hi bob,

up to now I don´t have any experience with rotary encoders, but it´s on my wishlist for the very near future. That´s why I did some www research in the past, maybe the following link is helpful for you. It´s in german, but reference to a script at github.

https://tutorials-raspberrypi.de/raspber...rkeregler/

Further ideas for installing with Arduino, maybe this can give you some additional hints re. scripting

https://www.stuffaboutcode.com/2015/05/r...coder.html
http://henrysbench.capnfatz.com/henrys-b...er-manual/
http://84park.blogspot.com/2017/01/ardui...coder.html

cheers, AnnaBlume
(09-06-2018, 06:43 AM)+3DRONE7 Wrote: [ -> ]Hi, first ever use of a rotary encoder.... connected 3.3v, GND, gpio 23, and 24.....
Config>audio> and set Rotary encoder to 'on'....   set MPD Config>volume control> software   (sort of counter intuitive as an encoder is a hardware item..???? ......but only options are 'disabled' and 'software')

Encoder works but needs several turns (10+) to go from low to high.... which of the parameters in the settings box do I need to change and to what to get quicker control ?

The encoder has a push switch.... is there a gpio pin to connect to that will enable mute toggle with this ?

Thanks !
bob

Hi Bob,
I´m getting a bit deeper into your issue:
What model of rotary encoder do you use? For the KY-040 the wiring of the five pins is (with pins directing down):

left: GND
2nd left: +3.3V
mid: push switch (SW)
2nd right: data (DT)
right: clock (CLK)

Connecting SW to the proper GPIO pin should enable the push switch.

Assume you`ll ask now: What are the proper GPIO pins? I´m not sure if there are standard pins ofr rotary encoder (like for IR remote control where the standard is GPIO 18 for receive and GPIO 17 for send). You can assign any GPIO pins (pls. refer to the script examples via the links), pls. don´t forget to set the pins to pull-up. The python script on github is an excellent starting point. There you can see also how to assign the rotary pins to certain GPIO pins.
https://github.com/conradstorz/KY040/blo...r/KY040.py

Cheers, AnnaBlume
Here's some info that might help :-)

https://www.mouser.com/ProductDetail/ALP...3GPQ%3D%3D
https://www.cui.com/blog/what-is-encoder...pr-and-lpr
https://www.linearmotiontips.com/how-to-...esolution/

moOde's rotary encoder driver and settings were designed around an ALPS 24 PPR encoder.

If you are trying to achieve 0 - 360 deg encoder rotation ~= 0 - 100 moOde volume knob then try adjusting the encoder params as below. When you change the params SET the encoder OFF then ON.

Heres the (i) help text from Audio Config screen.

- DELAY = Number of ms delay for each iteration of the volume update loop (default=100).
- ACCEL = Threshold (diff betw last/current enc pos) to determine whether to use 1 step or STEP steps (default=2).
- STEP = Number of steps to use when knob turns at fast rate (default=3).
- PIN-A/B = WiringPi pin numbers (default=pin 4,5 [GPIO 23,24]).

Heres the default

100 2 3 4 5

The DELAY determines how often the driver checks the value of two variables, currentPos and lastPos, that indicate which direction, clockwise or counter clockwise, the encoder has been rotated. The difference between these two values also indicates whether the encoder movement was fast or slow indicating greater or lesser rotation. A low DELAY setting will increase the likelihood that the difference between currentPos and lasPos will = 1 and thus not provide any information on how fast/far the encoder has been rotated.

The ACCEL threshold is compared against the difference between currentPos and lastPos to determine whether to adjust volume by 1 step or by STEP steps. This allows slow movements of the encoder to steadily adjust volume by 1 step while fast movements adjust the volume by STEP steps.

Ok, so at least with my ALPS encoder, heres how to get greater change in moOde volume knob for a given encoder movement.

1. Turn ACCEL threshold off by setting it to 1 and then increase the STEP value. This will result in the volume knob always going up or down by STEP. Whats lost is the ability to slowely go up/down by 1 step.

2. Leave ACCEL threshold set to 2 and increase the STEP value. This results in somewhat of a balance between slow = 1 step and fast = STEP steps.

3. Set DELAY = 10 (ms), turn ACCEL threashold off by setting it to 1, set STEP to 2 or higher. Having a lower delay can sometimes produce smoother knob movement.

Experiment!

-Tim
You could also replace contents of /var/www/command/rotvol.sh with the streamlined moOde 4.3 version below for slightly better performance.

Code:
#!/bin/bash
# moOde audio player (C) 2014 Tim Curtis, GPLv3, moOde 4.3
VOLKNOB=$(sqlite3 /var/local/www/db/moode-sqlite3.db "select value from cfg_system where id='32'")
if [[ $1 = "up" ]]; then LEVEL=$(($VOLKNOB + $2)); elif [[ $1 = "dn" ]]; then LEVEL=$(($VOLKNOB - $2)); fi
if (( $LEVEL < 0 )); then LEVEL=0; elif (( $LEVEL > 100 )); then LEVEL=100; fi
sqlite3 /var/local/www/db/moode-sqlite3.db "update cfg_system set value=$LEVEL where id='32'"
mpc volume $LEVEL >/dev/null
Hi Tim.. thanks for that explanation of the parameters.... I was a bit lost as to what the meaning of the terms were on the config page , what to adjust and what result to expect....
So I did experiment and settled on 100 2 9 4 5 as being a reasonable compromise....
Now I know more I will experiment further....Thanks for the 4.3 code !

Re the mute switch.... I thought I would try Remys guide for push-buttons and treat the rotenc push switch as one....?
http://moodeaudio.org/forum/showthread.php?tid=198

Or perhaps not use the rotenc for that but a separate button dedicated to a mute....yes that might be easier.
Hi Bob,

What PPR is your particular rotary encoder?

For sure, coding a driver for a quadrature rotary encoder is not trival and neither is the explain :-0

To do the mute switch in the moOde driver, some code would need to be added rotenc.c to handle a new PIN_C (the GPIO pin assigned to mute toggle).

Its doable but I would need a Pi with a working 4 pin encoder to do the coding and testing.

-Tim
Я использую
Code:
#!/usr/bin/env python3.5

# Key press detect code, uses gpio 27 and ground to a momentary switch. If pressed for more
# than 1sec but (less than 5) it will force a reboot.
# If pressed for more than 5 seconds it will force a shutdown
# Code taken from sample posted on the Foundation's forum
# by paulv >> Fri Jun 28, 2013 2:58 pm
# https://www.raspberrypi.org/forums/viewtopic.php?t=48455&p=379280
# Should be initiated in /etc/rc.local with following line:
# python /home/pi/tools/ButtonPress.py&


from time import sleep
import subprocess
import RPi.GPIO as GPIO

# GPIO channel 27 is on pin 13 of 40way connector
# with GND on pin14
CHANNEL = 15

GPIO.setmode(GPIO.BCM)
GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# setup the channel as input with a 50K Ohm pull up. A push button will ground the pin,
# creating a falling edge.


def system_action(CHANNEL):
   print('Button press = negative edge detected on channel %s'%CHANNEL)
   button_press_timer = 0
   while True:
           if (GPIO.input(CHANNEL) == False) : # while button is still pressed down
               button_press_timer += 1 # keep counting until button is released
           else: # button is released, figure out for how long
               if (button_press_timer > 5) : # pressed for > 5 seconds
                   print "long press > 5 : ", button_press_timer
                   # do what you need to do before halting
                   subprocess.call(['shutdown -h now "System halted by GPIO action" &'], shell=True)
               elif (button_press_timer > 1) : # press for > 1 < 5 seconds
                   print "short press > 1 < 5 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(['sudo reboot &'], shell=True)
        elif (button_press_timer > 0,1) : # press for > 0,1 < 1 seconds
                   print "short press > 0,1 < 1 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(["mpc", "toggle"], shell=False)
            break
               button_press_timer = 0
           sleep(1)

GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=system_action, bouncetime=200)
# setup the thread, detect a falling edge on gpio and debounce it with 200mSec

# assume this is the main code...
try:
   while True:
       # do whatever
       # while "waiting" for falling edge on gpio
       sleep (2)

except KeyboardInterrupt:
     GPIO.setwarnings(False)
     GPIO.cleanup()  # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit
(09-14-2018, 03:29 AM)fedormil Wrote: [ -> ]Я использую
Code:
#!/usr/bin/env python3.5

# Key press detect code, uses gpio 27 and ground to a momentary switch. If pressed for more
# than 1sec but (less than 5) it will force a reboot.
# If pressed for more than 5 seconds it will force a shutdown
# Code taken from sample posted on the Foundation's forum
# by paulv >> Fri Jun 28, 2013 2:58 pm
# https://www.raspberrypi.org/forums/viewtopic.php?t=48455&p=379280
# Should be initiated in /etc/rc.local with following line:
# python /home/pi/tools/ButtonPress.py&


from time import sleep
import subprocess
import RPi.GPIO as GPIO

# GPIO channel 27 is on pin 13 of 40way connector
# with GND on pin14
CHANNEL = 15

GPIO.setmode(GPIO.BCM)
GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# setup the channel as input with a 50K Ohm pull up. A push button will ground the pin,
# creating a falling edge.


def system_action(CHANNEL):
   print('Button press = negative edge detected on channel %s'%CHANNEL)
   button_press_timer = 0
   while True:
           if (GPIO.input(CHANNEL) == False) : # while button is still pressed down
               button_press_timer += 1 # keep counting until button is released
           else: # button is released, figure out for how long
               if (button_press_timer > 5) : # pressed for > 5 seconds
                   print "long press > 5 : ", button_press_timer
                   # do what you need to do before halting
                   subprocess.call(['shutdown -h now "System halted by GPIO action" &'], shell=True)
               elif (button_press_timer > 1) : # press for > 1 < 5 seconds
                   print "short press > 1 < 5 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(['sudo reboot &'], shell=True)
        elif (button_press_timer > 0,1) : # press for > 0,1 < 1 seconds
                   print "short press > 0,1 < 1 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(["mpc", "toggle"], shell=False)
            break
               button_press_timer = 0
           sleep(1)

GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=system_action, bouncetime=200)
# setup the thread, detect a falling edge on gpio and debounce it with 200mSec

# assume this is the main code...
try:
   while True:
       # do whatever
       # while "waiting" for falling edge on gpio
       sleep (2)

except KeyboardInterrupt:
     GPIO.setwarnings(False)
     GPIO.cleanup()  # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit

Hi @fedormil,

"Я использую"

Please post in English so we can all understand your posts, otherwise I'll need to moderate the posts.

-Tim
(09-14-2018, 04:35 PM)Тим Кертис Wrote: [ -> ]
(09-14-2018, 03:29 AM)fedormil Wrote: [ -> ]Я использую
Code:
#!/usr/bin/env python3.5

# Key press detect code, uses gpio 27 and ground to a momentary switch. If pressed for more
# than 1sec but (less than 5) it will force a reboot.
# If pressed for more than 5 seconds it will force a shutdown
# Code taken from sample posted on the Foundation's forum
# by paulv >> Fri Jun 28, 2013 2:58 pm
# https://www.raspberrypi.org/forums/viewtopic.php?t=48455&p=379280
# Should be initiated in /etc/rc.local with following line:
# python /home/pi/tools/ButtonPress.py&


from time import sleep
import subprocess
import RPi.GPIO as GPIO

# GPIO channel 27 is on pin 13 of 40way connector
# with GND on pin14
CHANNEL = 15

GPIO.setmode(GPIO.BCM)
GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# setup the channel as input with a 50K Ohm pull up. A push button will ground the pin,
# creating a falling edge.


def system_action(CHANNEL):
   print('Button press = negative edge detected on channel %s'%CHANNEL)
   button_press_timer = 0
   while True:
           if (GPIO.input(CHANNEL) == False) : # while button is still pressed down
               button_press_timer += 1 # keep counting until button is released
           else: # button is released, figure out for how long
               if (button_press_timer > 5) : # pressed for > 5 seconds
                   print "long press > 5 : ", button_press_timer
                   # do what you need to do before halting
                   subprocess.call(['shutdown -h now "System halted by GPIO action" &'], shell=True)
               elif (button_press_timer > 1) : # press for > 1 < 5 seconds
                   print "short press > 1 < 5 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(['sudo reboot &'], shell=True)
        elif (button_press_timer > 0,1) : # press for > 0,1 < 1 seconds
                   print "short press > 0,1 < 1 : ", button_press_timer
                   # do what you need to do before a reboot
                   subprocess.call(["mpc", "toggle"], shell=False)
            break
               button_press_timer = 0
           sleep(1)

GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=system_action, bouncetime=200)
# setup the thread, detect a falling edge on gpio and debounce it with 200mSec

# assume this is the main code...
try:
   while True:
       # do whatever
       # while "waiting" for falling edge on gpio
       sleep (2)

except KeyboardInterrupt:
     GPIO.setwarnings(False)
     GPIO.cleanup()  # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit
Sorry, Tim! I want to help with knob rotary encoder, and write script, which I use.
Pages: 1 2