[PLUGIN] RotaryEncoder II

Hi!, I’m triying to configurate some KY040 for my volumio, and want to use it to navigate into the menú and select betwen radio, folders, spotify, but can´t understand how to use de websocket messages. Can sombody help this newer in volumio?

Hi Mauricio,

sorry, the man page for the plugin is not very well showing the correct usage of the command. I plan to update it, but had other prios recently.
I am using it currently to call methods of another plugin.
Example:

Command CCW: callMethod
Data CCW: {"endpoint":"system_hardware/myplugin","method":"down","data":""}

Command CW: callMethod
DataCW: {"endpoint":"system_hardware/myplugin","method":"up","data":""}

So the “command” needs to be any of the commands described in the Websocket API description and the “Data” needs to be the respective payload (if needed).

Additional remark:
If your aim is, to control the UI on your mobile device or PC via the rotary controllers connected to Volumio, I am not aware of any websocket commands that would allow this. Your browser is communicating with the Volumio Webserver and the plugin is communicating with the Volumio Websocket interface - I would not know, how to combine both. But maybe somebody else is wiser than me - I have not explored any of the UI related stuff. If there is a simple method to do this, it might be worth adding to the plugin.

Thanks Tom for your answer: I juts trying to controller volumio with a 3,5 lcd and “now playing”.
If I undestand well, the way for access to the sources could be:
Command: getBrowseSources
ccw: down
Command: getBrowseSources
cw: up
data:?

data must be “select” o just " "

btw: please excuse my poor english, I don’t practice it too much

I’m still not 100% sure I understand:
You want to use a 3.5" LCD display - ok. But what is it displaying and what is controlling it? Is it displaying the Volumio User Interface (UI) or are you writing a plugin or software that is generating some content to display?
There are two problems with your current approach:

  1. You can configure the RotaryEncoder2-plugin to send the getBrowseSources command via Websocket API, but the API will not know what to do with the payload up or down because getBrowseSources does not take any attributes
  2. When getBrowseSources sends its response, the plugin has no function to handle this response (event). You need separate code (e.g. plugin) to handle the event

What I tried to show you with my example:
You can call functions inside another plugin and perform actions from there. What you would need to do e.g. is to write some plugin (myplugin in the example) which for example contains a function up and a function down.
Now when you initialize your plugin, you call getBrowseSources and store the list you receive in an array. Then you display it on your LCD. Additionally you store, which item is selected and mark that on the display (e.g. inverted). Now the functions up/down would increment/decrement the selected index and update the display. Additionally, you need a function (e.g. select) that moves down one level (e.g. into Artists) and then calls browseLibraryon the selected source to receive the items on the next lower level.
So you need to implement the navigation in your own plugin, that interacts with your display and you can use the rotary to call functions in your own plugin.
I do not want to provide this functionality in the rotary-encoder plugin, because it unnecessarily blows up the size and will break the idea of modularity. Also, there are many displays in the market which would all need a different code.
I am currently working on a plugin that works with an 1.6" LCD display (this is where I took the example), but it is not yet good enough for publishing and I currently have only little time to work on it (see Image 1 & 5 here).

I see… I was hoping it would be a bit simpler. While I study this programming, I will stick with simpler functions with the encoders. For now I will face the conflict with the rotary button that does not work. Thank you very much for taking your time to respond.

Sorry I do not have better news.
If you need help with the button, feel free to ask.
If you need assistance, please follow the instruction in the topmost post here. It will make it easier to respond.
BTW: v1.0.14 just got merged and should be available as stable now.

Hi,

I just installed the latest Volumio (3.324-2022-07-11), but the Rotary Encoder II plugin does not work at all, I configured the same GPIO’s which are working well using Volumio 2.

Live-Log does not show up anything.
Any hints where to look what’s wrong?

journalctl | grep -i encoder*
shows no errors.

volumio@volumio:~$ dtoverlay -l
Overlays (in load order):
0:  gpio-ir  gpio_pin=17 gpio_pull=up
1:  rotary-encoder  pin_a=4 pin_b=27 relative_axis=true steps-per-period=1
volumio@volumio:~$

Regards,
Phil

Hi!
I‘m currently traveling and cannot support right away.
Can you provide a bug-report as described at the bottom of post #1?

Raspberry Pi 3b+,
Hifiberry dac plus adc
Volumio 3.324
Rotary Encoder II Plugin 1.0.14
Rotary Encoder Hardware KY 40

Other Plugins installed:
Fusion DSP 1.0.18
IR Remote Controller 3.4.7

Logs.

plugin started:

Aug 04 15:33:29 volumio volumio[858]: info: Enabling plugin rotaryencoder2
Aug 04 15:33:29 volumio volumio[858]: info: Loading plugin "rotaryencoder2"...
Aug 04 15:33:29 volumio volumio[858]: info: PLUGIN START: rotaryencoder2
Aug 04 15:33:29 volumio volumio[858]: info: [ROTARYENCODER2] loadI18nStrings: /data/plugins/system_hardware/rotaryencoder2/i18n/strings_en.json
Aug 04 15:33:29 volumio volumio[858]: info: [ROTARYENCODER2] loadI18nStrings: loaded: {"ROTARYENCODER2":{"CONFIG":"Rotary Encoder II Plugin Configuration","SAVE":"Save","ENCODER0":"Rotary Encoder 1","D_ENCODER0":"Settings for the first rotary encoder.","ENCODER1":"Rotary Encoder 2","D_ENCODER1":"Settings for the second rotary encoder.","ENCODER2":"Rotary Encoder 3","D_ENCODER2":"Settings for the third rotary encoder.","ROTARYTYPE":"Periods per tick","D_ROTARYTYPE":"Periods per tick (Full: A and B full period, half: A and B half period, quarter: A or B half period","FULL":"Full-period mode","HALF":"Half-period mode","QUARTER":"Quarter-period mode","PINA":"Pin A GPIO","D_PINA":"GPIO pin that is connected to the first pin of the rotary.","PINB":"Pin B GPIO","D_PINB":"GPIO pin that is connected to the second pin of the rotary.","DIALACTION":"Dial Action","D_DIALACTION":"Action to be triggered by turning the rotary encocer. Option 'Emit Websocket Message' can be used to control other plugins using the Volumio Websock calls between Plugins. (see https://volumio.github.io/docs/API/WebSocket_APIs.html section 'CallMethod on Plugin' for details)","DOTS":"...","VOLUME":"Volume","SKIP":"Prev/Next title","SEEK":"Seek in title","SCROLL":"Scroll","EMIT":"Emit Websocket Message","SOCKCMDCCW":"Command CCW","SOCKDATACCW":"Data CCW","SOCKCMDCW":"Command CW","SOCKDATACW":"Data CW","SOCKCMD":"Command","SOCKDATA":"Data","D_SOCKCMD":"Command to send via Websocket","D_SOCKDATA":"Data to include with the Websocket Command","PINPUSH":"Pushbutton GPIO","D_PINPUSH":"GPIO pin that is connected to the pushbutton pin of the rotary. 0 or empty to disable.","PINPUSHDEBOUNCE":"Debounce-time (ms)","D_PINPUSHDEBOUNCE":"Debounce time for the button. If the button has hardware-debouncing, set to 0.","PUSHSTATE":"Button logic-level active low","D_PUSHSTATE":"Activate this, if pressing the button pulls the logic level on the GPIO low.","PINPUSHDELAY":"Delay for a long button press (ms)","D_PINPUSHDEDELAY":"Minimum duration of a button press, that will trigger the long push action in ms","PINDOUBLEPUSHDELAY":"Maximum interval for double press (ms)","D_PINDOUBLEPUSHDEDELAY":"Time interval in ms, within which a double press has to be detected.","PUSHACTION":"Short Press Action","D_PUSHACTION":"Action that gets triggered, when pushbutton is pressed briefly.","LONGPUSHACTION":"Long Press Action","D_LONGPUSHACTION":"Action that gets triggered, when pushbutton is pressed longer.","DOUBLEPUSHACTION":"Double Press Action","D_DOUBLEPUSHACTION":"Action that gets triggered, when pushbutton is pressed twice quickly.","SET_DEBUG":"Debug Settings","D_SET_DEBUG":"Settings for functional debugging.","PLAY":"Play","PAUSE":"Pause","PLAYPAUSE":"Play/Pause toggle","STOP":"Stop","REPEAT":"Repeat","RANDOM":"Random","CLEARQUEUE":"Clear Queue","MUTE":"Mute","UNMUTE":"Unmute","TOGGLEMUTE":"Toggle Mute","SHUTDOWN":"System Shutdown","REBOOT":"System Reboot","RESTARTAPP":"Restart Application","DUMPLOG":"Dump logfile","LOGGING":"Logging","D_LOGGING":"Switch the output of log messages on or off. Error messages are always logged.","TOAST_START_SUCCESS":"Plugin successfully started.","TOAST_STOP_SUCCESS":"Plugin successfully stopped.","TOAST_START_FAIL":"Plugin failed to start.","TOAST_STOP_FAIL":"Plugin failed to stop.","TOAST_GPIO_BLOCKED":"GPIO Pin unavailable","TOAST_MSG_OVERLAY_BLOCKING":"Blocked by another overlay.","TOAST_SAVE_SUCCESS":"Successfully saved","TOAST_MSG_SAVE":"Settings for Encoder ","TOAST_DEBUG_SAVE":"Debug Settings","TOAST_SAVE_FAIL":"Save failed","TOAST_WRONG_PARAMETER":"Error in parameters","TOAST_NEEDS_INTEGER":"GPIO Pins must be Integers.","TOAST_PINS_DIFFERENT":"GPIO Pins for A/B/Button must be different.","TOAST_PINS_BLOCKED":"Pins already used in another Encoder.","TOAST_NO_TYPE":"Please select 'Periods per tick'!"}}
Aug 04 15:33:29 volumio volumio[858]: info: [ROTARYENCODER2] onStart: Config loaded: {"syncSave":true,"autosave":true,"autosaveDelay":1000,"saved":true,"atomicSave":false,"data":{"enabled0":{"type":"boolean","value":true},"rotaryType0":{"type":"number","value":1},"pinA0":{"type":"string","value":"4"},"pinB0":{"type":"string","value":"27"},"dialAction0":{"type":"number","value":1},"socketCmdCW0":{"type":"string","value":""},"socketDataCW0":{"type":"string","value":""},"socketCmdCCW0":{"type":"string","value":""},"socketDataCCW0":{"type":"string","value":""},"pinPush0":{"type":"number","value":22},"pinPushDebounce0":{"type":"number","value":0},"pushState0":{"type":"boolean","value":false},"pushAction0":{"type":"number","value":3},"socketCmdPush0":{"type":"string","value":""},"socketDataPush0":{"type":"string","value":""},"longPushAction0":{"type":"number","value":4},"socketCmdLongPush0":{"type":"string","value":""},"socketDataLongPush0":{"type":"string","value":""},"delayLongPush0":{"type":"string","value":"1500"},"doublePushAction0":{"type":"number","value":12},"socketCmdDoublePush0":{"type":"string","value":""},"socketDataDoublePush0":{"type":"string","value":""},"delayDoublePush0":{"type":"string","value":"700"},"enabled1":{"type":"boolean","value":false},"rotaryType1":{"type":"number","value":0},"pinA1":{"type":"string","value":""},"pinB1":{"type":"string","value":""},"dialAction1":{"type":"number","value":0},"socketCmdCW1":{"type":"string","value":""},"socketDataCW1":{"type":"string","value":""},"socketCmdCCW1":{"type":"string","value":""},"socketDataCCW1":{"type":"string","value":""},"pinPush1":{"type":"number","value":0},"pinPushDebounce1":{"type":"number","value":0},"pushState1":{"type":"boolean","value":false},"pushAction1":{"type":"number","value":0},"socketCmdPush1":{"type":"string","value":""},"socketDataPush1":{"type":"string","value":""},"longPushAction1":{"type":"number","value":0},"socketCmdLongPush1":{"type":"string","value":""},"socketDataLongPush1":{"type":"string","value":""},"delayLongPush1":{"type":"string","value":"1500"},"doublePushAction1":{"type":"number","value":0},"socketCmdDoublePush1":{"type":"string","value":""},"socketDataDoublePush1":{"type":"string","value":""},"delayDoublePush1":{"type":"string","value":"700"},"enabled2":{"type":"boolean","value":false},"rotaryType2":{"type":"number","value":0},"pinA2":{"type":"string","value":""},"pinB2":{"type":"string","value":""},"dialAction2":{"type":"number","value":0},"socketCmdCW2":{"type":"string","value":""},"socketDataCW2":{"type":"string","value":""},"socketCmdCCW2":{"type":"string","value":""},"socketDataCCW2":{"type":"string","value":""},"pinPush2":{"type":"number","value":0},"pinPushDebounce2":{"type":"number","value":0},"pushState2":{"type":"boolean","value":false},"pushAction2":{"type":"number","value":0},"socketCmdPush2":{"type":"string","value":""},"socketDataPush2":{"type":"string","value":""},"longPushAction2":{"type":"number","value":0},"socketCmdLongPush2":{"type":"string","value":""},"socketDataLongPush2":{"type":"string","value":""},"delayLongPush2":{"type":"string","value":"1500"},"doublePushAction2":{"type":"number","value":0},"socketCmdDoublePush2":{"type":"string","value":""},"socketDataDoublePush2":{"type":"string","value":""},"delayDoublePush2":{"type":"string","value":"700"},"logging":{"type":"boolean","value":true}},"callbacks":{"_":{}},"filePath":"/data/configuration/system_hardware/rotaryencoder2/config.json"}
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] activateRotaries: 1,2,3
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] activateRotaries: 1,2
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] activateRotaries: 1
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] activateRotaries:
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] activateRotaries: end of recursion.
Aug 04 15:33:30 volumio volumio[858]: info: [ROTARYENCODER2] addOverlay: 4 27 1
Aug 04 15:33:30 volumio volumio[858]: verbose: New Socket.io Connection to localhost:3000 from 127.0.0.1 UA: node-XMLHttpRequest Total Clients: 6
Aug 04 15:33:30 volumio sudo[3059]:  volumio : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/dtoverlay rotary-encoder pin_a=4 pin_b=27 relative_axis=true steps-per-period=1
Aug 04 15:33:30 volumio sudo[3059]: pam_unix(sudo:session): session opened for user root by (uid=0)
Aug 04 15:33:30 volumio kernel: rotary-encoder rotary@4: gray
Aug 04 15:33:30 volumio kernel: input: rotary@4 as /devices/platform/rotary@4/input/input10
Aug 04 15:33:30 volumio volumio[858]: info: CoreCommandRouter::volumioGetState
Aug 04 15:33:30 volumio sudo[3059]: pam_unix(sudo:session): session closed for user root
Aug 04 15:33:30 volumio volumio[858]: info: CorePlayQueue::getTrack 14
Aug 04 15:33:30 volumio volumio[858]: info: /dev/input:
Aug 04 15:33:30 volumio volumio[858]: by-path
Aug 04 15:33:30 volumio volumio[858]: event0
Aug 04 15:33:30 volumio volumio[858]: event1
Aug 04 15:33:30 volumio volumio[858]: mice
Aug 04 15:33:30 volumio volumio[858]: /dev/input/by-path:
Aug 04 15:33:30 volumio volumio[858]: platform-ir-receiver@11-event
Aug 04 15:33:30 volumio systemd-udevd[3065]: Process '/usr/sbin/th-cmd --socket /var/run/thd.socket --passfd --udev' failed with exit code 1.
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] attachListener: /dev/input/by-path/platform-rotary@4-event
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] addEventHandle for rotary: 1
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons: 1,2,3
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons: 1,2
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons: 1
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons:
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons: end of recursion.
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] activateButtons: Now assign push button: 1
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] Push Button 1 now resolving.
Aug 04 15:33:31 volumio volumio[858]: info: [ROTARYENCODER2] onStart: Plugin successfully started.
Aug 04 15:33:31 volumio volumio[858]: info: Done.

plugin stopped:

Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] onStop: Stopping Plugin.
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries: 1,2,3
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries: 2,3
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries: 3
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries:
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries: end of recursion.
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] detachListener: [object Object]
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] detachListener: successfully killed handler process
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] checkOverlayExists: Checking for existing overlays for Rotary: 1
Aug 04 15:34:28 volumio sudo[3086]:  volumio : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/dtoverlay -l
Aug 04 15:34:28 volumio sudo[3086]: pam_unix(sudo:session): session opened for user root by (uid=0)
Aug 04 15:34:28 volumio sudo[3086]: pam_unix(sudo:session): session closed for user root
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] checkOverlayExists: check pinA=4pinB=27 in Overlays (in load order):
Aug 04 15:34:28 volumio volumio[858]: 0:  gpio-ir  gpio_pin=17 gpio_pull=up
Aug 04 15:34:28 volumio volumio[858]: 1:  rotary-encoder  pin_a=4 pin_b=27 relative_axis=true steps-per-period=1
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] checkOverlayExists: rotary 1uses overlay 1
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] removeOverlay: 1
Aug 04 15:34:28 volumio sudo[3089]:  volumio : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/dtoverlay -r 1
Aug 04 15:34:28 volumio sudo[3089]: pam_unix(sudo:session): session opened for user root by (uid=0)
Aug 04 15:34:28 volumio volumio[858]: info: [ROTARYENCODER2] addEventHandle: Stream from rotary encoder ended.
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] addEventHandle: child process exited with code null
Aug 04 15:34:29 volumio sudo[3089]: pam_unix(sudo:session): session closed for user root
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] removeOverlay: 1 returned:
Aug 04 15:34:29 volumio sudo[3099]:  volumio : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/dtoverlay -l
Aug 04 15:34:29 volumio sudo[3099]: pam_unix(sudo:session): session opened for user root by (uid=0)
Aug 04 15:34:29 volumio sudo[3099]: pam_unix(sudo:session): session closed for user root
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] removeOverlay: "overlay -l" returned: Overlays (in load order):
Aug 04 15:34:29 volumio volumio[858]: 0:  gpio-ir  gpio_pin=17 gpio_pull=up
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateRotaries: deactivated rotary1
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: 1,2,3
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: 2,3
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: 3
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons:
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: end of recursion.
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: button 3 is not configured.
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: button 2 is not configured.
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] deactivateButtons: deactivated button 1.([object Object])
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] getI18nString("TOAST_STOP_SUCCESS"):Plugin successfully stopped.
Aug 04 15:34:29 volumio volumio[858]: info: [ROTARYENCODER2] onStop: Plugin successfully stopped.
Aug 04 15:34:29 volumio volumio[858]: info: Disabling plugin rotaryencoder2
Aug 04 15:34:29 volumio volumio[858]: info: Done.


By turning or pushing the knob nothing is logged.

Thanks. At first sight everything looks normal. dtoverlays seem to be properly configured so they should be working.
there seems to be another dtoverlay in your system, but that should not cause issues. however, that is a deviation from my development system, so you could try to disable the IR-receiver just to see, if that is part of the problem.
Another thing I noticed is the debouncing setting of 0ms. Normally 50ms-100ms is the better choice, if you are not using hardware debouncing. But that’s unlikely the issue, because it should rather cause too many events, not none.
You could also try to use an older version of the plugin, e.g. 1.0.12 just to check.
Those are all hints I can give for now. Need to test the plugin with Volumio 3.342 when I am back home to see, if anything else changed (e.g. new kernel version).
When you say, your hardware was working with Volumio2, was that with Saiyato‘s plugin ‚RotaryEncoder’ or with my ‚RotaryEncoder II‘?

Thanks for your support, Thomas.
Unfortunately, deactivating the IR-plugin didn’t change anything, also setting a debounce value of 50ms.

On Volumio 2 I’m using Saiyato‘s plugin.
I’ve never installed plugins from shell, but I’ll try, shouldn’t be kinda rocket science.
Will report back when running 1.0.12.

I forgot to say that I’ve connected an I2S-RFID card reader, but there isn’t any software installed at this point, can’t say if this could interfere. However, as far as I know only the Hifiberry is using I2S for configuration thingies, but on Volumio 2 everything runs fine.

Regards,
Phil

@phil977 i use the rotary plugin (version 1.0.14) for two devices, hifiberry dac i2s output for a philips nos dac and generic i2s dac output for a audiophonics ess 9028 pro dac.
I also use infrared and audiophonics on/off plugin.
so i2s and infrared are probably not the problem then.

for the rest, the rotary plugin works well if only the push button responds sometimes slowly.

these are my settings for the KY 40 rotary.

Ok, it’s a debouncing issue.
I played around, finally configured 25ms, and it takes 3 to 5 360-degree turns of the knob to change the volume for one single tick.
So it simply needs patience, reducing 50% volume to zero takes about 3 minutes hard rotating work :smiley:

I also tried other values, 50ms, 100ms, 150ms, best result is 40ms, takes about 90 seconds from 50% to zero :slight_smile:

I remeber soldering resistors, but do not know the values anymore, about 1k I guess.
Since the encoders are mounted in a cabinett I can’t see it anymore without a serious 30-minutes-unmounting-hell.

However, pressing the Knob has no effect at all.

because to prevent I put several clicks in settings/playback options/mixer type volume steps.
saves a lot of effort turning the knob.

Hi Phil,
I’m back home and did some checks:

  • upgraded to 3.324
  • downloaded the latest “stable” plugin version (to check if I messed up anything, when I did some tiding up of my branch history on request of Balbuze, before it was merged)

But with both steps, the plugin still works stable and reliable on my test-system (also the push-buttons). So I assume, it probably really is a hardware issue on your side.
However, I do not think it is a debouncing issue, because bouncing should rather generate too many increments/decrements not too little.
If you generate the log again and this time do enough rotations to see log entries, you may get some hints from the log already (e.g. there should be a new log-entry with each tick of the rotary - if you share it and describe, what you did during generation, I may be able to offer some support).
Beside debouncing, there can be issues with wrong logic (active low/active high) and with too low or too high logic levels. For example, if you have a poor electronic connection somewhere, that can have a resistance and may generate a voltage drop across this poor connection. This will reduce the high level at your input and thus the input may actually never register a change of the signal from low to high (because the threshold of the GPIO’s internal Schmitt-Trigger is not reached). If you see an increase/decrease only on every other rotation, it might be that you have transient peaks (e.g. through fast switching and parasitic capacitances) which now and then are high enough to get over the threshold (causing a single increase now and then).

I did some research into the KY040 (I do not own one) and it basically is a 1/2 period/step rotary encoder + 2 pull-up resistors on the rotational switches. I use a similar setup in my test-system (Alps Rotary and two pull-ups) and it works like a charm. I see an increase of the volume with every click of the rotary (by 1, 5 or 10 steps, depending on what I set in Volume Options. If this does not work for you, you need to check the levels at your input. You may have a leakage somewhere (e.g. poor solder connection, small wire-bridge between two levels (e.g. dirt or residues from soldering).
If you really would like to improve, I recommend reading chapters Debouncing and Electronic schematic in the readme.md. Those may give some better insight on what to look for.

Hi Thomas,

thank you for your efforts, very appreciated.
Well, if I plug in my Volumio 2 SD-card, everything works flawlessly, every single tick is catched, every buttonclick is reliable, with two ky040 and saiyatos plugin, so it’s hard to believe it’s a hardware issue.

However, if you give me a Ferrari, and I destroy 12 cars with 500 horsepower in a parking situation, it might be okay for me to say it’s a piece of shit car, but I generally do not have to believe what I’m thinking : )

The next days I will have a little more spare time and will look deeper in generating logs, maybe something interesting pops up…

Ah - almost forgot… that is indeed strange. However, both Plugins work different, so there may be a difference in how they handle irregular signals. Also, if it is timing related, there may be differences because Volumio 2 and 3 are quite different. Differences between plugins:

  • Rotary Encoder original
    • Uses npm onoff_rotary under the hood, which itself basically uses two inputs configured via onoff to read out the rotary. Source can be found here
    • onoff itself uses /sys/class/gpio and epoll to monitor the inputs
  • Rotary Encoder II
    • Uses the Linux Kernel’s dtoverlay to load a built-in driver for monitoring of a rotary encoder connected to two GPIO’s
    • Source code of the driver can be found here

One of the differences is what the IRQ is triggering. In the onoff implementation, only the interrupt on one of the two inputs triggers an evaluation of both inputs (line 39). I suspect that caused the issue on my end with unreliable direction and missed ticks (probably due to the JS event loop being slower than the interrupt events).
The Kernel implementation seemed to be faster in my case, because it does not need JS to handle the state of the rotary and JS only receives the info, whether it needs to execute a CW or CCW action.

If you want to be sure, that the plugin (i.e. my code) is not the issue, you could use the method I explained to Darmur in a post in this thread. That should help to verify, if the Kernel Level driver operates as expected, or if you already have a problem there. Good luck and keep us posted how it goes.

Ok, did that shh test:

volumio@volumio:~$ dtoverlay -l
Overlays (in load order):
0:  rotary-encoder  pin_a=4 pin_b=27 relative_axis=true steps-per-period=1
volumio@volumio:~$ cat /dev/input/by-path/platform-rotary\@4-event
L▒b▒FL▒b▒F

That garbage characters appeared after 2 360-degree turns, then again after 15 turns.
Means it’s that kernel level driver issue, right?

Ok - that confirms my suspicion: the problem is not the plugin. Since the driver is in the Linux Kernel for several years already, I also do not think that is a Kernel level driver issue.
I updated the readme.md for the plugin yesterday and maybe you can additionally try to follow the updated instructions there. Instead of using cat I replaced it by od, which allows us to actually see the binary data sent by the Kernel driver in hex:
od -x -w32 /dev/input/by-path/platform-rotary\@4-event
After issuing this command, you should get one line of output for every “tick” of the encoder.

But I think the actual problem is somewhere in your hardware. Hardware is difficult to diagnose without a multimeter or even better an oscilloscope (since a multimeter is slow and will not show you transitions of states).
I do not own a KY-040, but from what I see on the web, it is basically sold on Maker-Webshops and is probably coming from some Chinese companies under different brands. I did not find out, what rotary encoder is actually used, so there may be different versions available. As I mention in the readme, the KY-040 is basically a standard rotary encoder with two pull-ups for the two rotary channels already included.
If you get output from cat only after 2 turns and then after 15 turns, that must have something to do with poor digital signal, broken rotary or a problem with the GPIO hardware. The rotary is a very simple device - it is basically just 3 switches (two rotation channels CLK/DT and one push-button). Depending on the type and the number of detents per rotation both rotational channel switches should open and close several times (10-30) within a single rotation. In your case this does not seem to be the case.

The difference between the two plugins is basically the speed of reaction on interrupts, as far as I can see and a better gray code logic in the Kernel driver. So I assume, that the Kernel driver is interpreting your signal as a problematic/bouncy input and not reacting on most of the events. The onoff_rotary does not have a lot of fancy gray code verification and may still operate with problematic signals. BTW: another difference is that you are running the old plugin on Volumio 2 (Jessy) and the new one on Volumio 3 (Buster). There may be subbtle differences due to the OS as well - I’ve seen weak Power-Supplies slightly drop voltage with different OS versions and a usual USB-Charger with 5.0V is actually already supplying too low voltage to the RPi which may decrease your 3.3V already (look for the brown-out warnings of the RPi).
Some questions:

  1. Do you have a multimeter or oscilloscope? Then you could measure the voltage at the Pins 4 and 27 and see if it changes when dialing.
  2. Do you know the following info for KY-040 (maybe @Mr100000Volt can help us here):
    2.1 Number of detents per rotation of KY-040?
    2.2 Correct steps-per-period setting? (see here for details)
    2.3 Value of the resistors in the KY-040 board (I found 200Ω online)? (According to online sources, GPIO 27 is internally pulled low by default and if that is true on your RPi and the external PU of the KY-040 is not matching, then it could be, that the voltage on the GPIO is below the required V_IH of 1.6V as in this example for external PD and internal PU). Maybe you could try to connect to GPIO 5 (internally pulled up) instead of 27? If the external pull-up is larger than the internal pull-down (>50kΩ), the voltage at the input with open rotary switch will be lower than 1.6V.
  3. Did you try to set steps-per-period=2 or 4 instead of 1? Here it looks like it is a SPP=2 rotary. If you use SPP=1 then you will already need 2 ticks for one step.

I think something with option 2 is most likely - it could explain, why you sometimes get an event (because the voltage may vary around 1.6V). It could also be caused by a cold solder joint or a too thin or squeezed cable - anything that increases the pull-up resistance significantly and thus reduce the voltage at the GPIO.

1 Like

“steps-per-period=2 or 4” triggers nothing by rotating in any direction.

as said, booting volumio2-sd-card, no problems at all.

I’m firing the rig with a 60 watts/19-volt power-supply through the hifiberry-amp-hat, so I don’t think power can be a source of this problem.

I do have a digital multimeter, but as stated before, the encoder is mounted, and I do not want to unmount it if not really, really necessary.

However, upcoming weekend I’ll get alps encoder for another project I’m in:
https://www.conrad.at/de/p/alps-stec12e08-encoder-5-v-dc-0-001-a-360-1-st-700708.html

Maybe these gizmos are what Volumio3/Buster likes a bit more, I’m curious.

If so, I will unmount and exchange the ky-040 and have a closer look at the resistor thingies onboard, plus the ones I soldered additionally.

Will post the results here.