3 ms·
I made something like this pretty recently, though it was with an ESP32, and it was bluetooth, and I used a mouse driver. It was cool, though I did kind of grow
by tombert 3y ago
I made something like this pretty recently, though it was with an ESP32, and it was bluetooth, and I used a mouse driver. It was cool, though I did kind of grow a hatred for the Arduino "poll the pins in the loop" way of doing things. It would kind of work, but the problem would be that if you spun the knob too quickly, it would actually end up going backwards because you're effectively spinning faster than it can sync.
I ended up having to learn how to use the FreeRTOS interrupts. It was a bit harder but it was a much better play experience.
- mikeInAlaska 3y agoWhat is causing the interrupts? Any change to encoder A or B?
- tombert 3y agoYou can set a gpio pin mode to PULLUP, and there’s a function built in to the freertos/arduino stuff for the ESP32 to convert that gpio pin signal to an interrupt. From there you can pass in a function pointer to run upon receiving the interrupt. The rotary encoder I bought simply applies pulses to one pin when spinning clockwise, and another pin when spinning counter clockwise, so I just attached the interrupts to two separate gpio pins, and sent the updates to the mouse stuff directly in the interrupt handler. I simply moved the mouse N units to the right or left if going clockwise or counterclockwise. I’m sure it’s not ideal but it worked to play breakout. I’m still a little new to the world of microcontrollers so it’s possible that I did something dumb.
- dekhn 3y agoThere is also a very simple and straightforward chip that will convert quadrature to pulses. Ls7183n. It's kind of unnecessary if you can write your own interrupt handlers but it's useful if you're just working with discrete electronics
- HeyLaughingBoy 3y agoThe LSI-Logic encoder interface chips are nice if your encoders are running at thousands of RPM. You also have to jump though a few more hoops than just an online order (I use an LSI device in a machine tool reconditioning product), so it's not particularly hobbyist-friendly. I'd be hard pressed to imagine anyone using them if they didn't absolutely have to. That said, they work very well.
- dekhn 3y agoHuh... I'm a hobbyist and I got them at digikey for about $5/chip. It ships in a couple weeks directly from LSI. My personal goal was to eliminate one microcontroller from my project. I would probably not use one in the future as long as my project had even a basic microcontroller.
- HeyLaughingBoy 3y agoWell, that's a surprise! I just checked and the LSI7366R (the version I use) is now available through Digi-Key. They have really expanded their Marketplace program. I used to have to buy them directly from LSI: it wasn't a big deal to setup an account with them, but it's nice to know that next time I can just piggyback it onto my Digikey order. Although if the delay is a couple weeks I'd have to plan ahead. They typically get them to me in a couple of days.
- dekhn 3y agoSo that combines both the quad decoder and the counter? That would have saved me a chip :) as my project was basically an encoder-driven 8-bit binary counter.
- HeyLaughingBoy 3y agoYes, I wish it also had differential inputs. My original design was based on an Arduino Nano with an AtMega328. Originally it was designed to read 0-10-0V position signals. This is from really old machine tools :-) Processing encoder inputs was a much later change. With the rate of interrupts coming in from a high-resolution encoder turning at 3,000 RPM, there was no way it would keep up and still do all the processing needed. The product volume wasn't high enough to make it worthwhile moving to a processor that had the timer/counter resources to handle it in hardware, so the simplest solution was adding a $6 chip (and a $2 differential interface chip to handle the differential encoder output channels).
- tomek_ycomb 3y agoIt's a fun exercise in which I think you'll find polling to be fine for many Arduino cases. Not as much for raspi and higher level in my limited experience for various hardware reasons and overhead. And quickly when you do other stuff, especially blocking high level communication, polling does suffer. But interrupts exist and are a reasonable level 2 for people to learn. https://www.mikrocontroller.net/articles/Drehgeber https://www.mikrocontroller.net/articles/Drehgeber is an excellent article (in German, Google translate is fine afaik. Check the interrupt section
- brokenmachine 3y ago>poll the pins in the loop You should be using interrupts for encoders. The standard Encoder library uses interrupts. https://www.arduino.cc/reference/en/libraries/encoder/ https://www.arduino.cc/reference/en/libraries/encoder/ In my experience on an ESP8266, it can do over 300kHz. Probably faster on an ESP32. For ESP8266, just remember to set ICACHE_RAM_ATTR for the ISR. Not sure if ESP32 is the same, but it probably is. So you'd need to be turning those encoders pretty damn fast for the interrupt speed to become a problem.
- phkahler 3y ago>> if you spun the knob too quickly, it would actually end up going backwards The spinner on arcade Tempest can do the same. IIRC the quadrature signals feed the clock and direction pins on a 4 bit up-down counter on the board, and software probably polls the counter. If you spin it fast enough (I used Teflon spray on mine) you could wrap the counter around and get it to move backwards. Something like that, it's been a few years...
- CrLf 3y agoThis project does use interrupts for the encoder. It uses the "Encoder" library mentioned in another comment. https://www.pjrc.com/teensy/td_libs_Encoder.html https://www.pjrc.com/teensy/td_libs_Encoder.html
- bombela 3y agoI might be missing something but I think the author of this library missed a very simple implementation. This library is hundreds of lines of assembly for implementing some jump table for all possible input combinaisons. I propose instead to shift left the two inputs into a 8 bits accumulator. And then there are only 3 states to match. Inc, Dec, Invalid (happens if you jiggle the encoder in place, effectively doing halfinc/halfdec). Something like that: sw = A << 1 | B if (state & 3 != sw) state = (state << 2) | sw state == 0b00101101 for increment state == 0b01111000 for decrement Any other state is ignored. If this code runs on interrupts, the conditional can be skipped if spurious interrupts are not possible. Any switch bounce can be filtered either in hardware (capacitor + resistor), or in software by averaging over time.