#96 Rotary Encoder Update - Stepless & Software Debounced

แชร์
ฝัง
  • เผยแพร่เมื่อ 13 ต.ค. 2017
  • A couple of recent comments on a previous video #19 (Rotary Encoders) made me think and ponder. So here's an update that looks at both the original sketch and stepped Rotary Encoder and also at a newer detentless (stepless) one, with the problems it potentially presents.
    We also consider how best to debounce the signal in software and what happens if you change the way I originally did it with a Real World example of my car radio - yes, really!
    I've included a link to a GitHub repository with the simple test sketches I used just so you can grab them and play about with them yourself, along with links to the stepless Rotary Encoder (rather more than I'd want to pay but it was supplied by a local supplier rather than a Far Eastern warehouse so would be more, of course).
    --------------------------------
    LINKS LINKS LINKS!
    --------------------------------
    github.com/RalphBacon/RotaryE...
    Bourns Pro Audio Rotary Encoder Spec Sheet (generic)
    www.bourns.com/docs/Product-Da...
    Example eBay item for stepless rotary encoder
    www.ebay.co.uk/itm/INCREMENTAL...
    NOTE: The PEC-016 part number convention is that the second digit determines whether it is stepped or not.
    Eg: PEC16-4020F-N0024 - it's the 4020F that is important - the second digit here (0) means STEPLESS
    The next part, N0024 determine whether a SWITCH pin is included (N=NO, S=YES) and the 24 shows how many steps per revolution
    Nick Gammon's web page on Interrupts:
    www.gammon.com.au/forum/bbsho...
    The sketches used in the demo are in the repository. Just download as a zip file and unzip on your local machine.
    If you like this video please give it a thumbs up, share it and if you're not already subscribed please do so :)
    My channel is here:
    ------------------------------------------------------------------
    / ralphbacon
    ------------------------------------------------------------------
    How can I remember this? Memory tip: "See" Ralph Bacon, geddit?
    [You can also use this link: / ralphbacon ]
  • วิทยาศาสตร์และเทคโนโลยี

ความคิดเห็น • 178

  • @rolandberendonck3900
    @rolandberendonck3900 3 ปีที่แล้ว +1

    Hi Ralph, I am still blown away about your original code, the simplicity, the use of that static variable and the speed and the responsiveness of the encoder in action. I have tried a few sketches and debouncing circuits, but your solution is absolutely the best! And these little boys are so very great to incorporate into our projects. So thanks very much :)

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว +1

      You're very welcome, Roland! Coincidentally I've been looking closely at an alternative way of reading a Rotary Encoder from a suggestion by viewer Marko Pinteric. I've understood his code but have yet to try it out. In the meantime my code will have to suffice!

    • @rolandberendonck3900
      @rolandberendonck3900 3 ปีที่แล้ว

      @@RalphBacon I am looking forward to that Ralph, but he has to come up with something really really clever to beat your code!!

  • @bikefarmtaiwan1800
    @bikefarmtaiwan1800 6 ปีที่แล้ว +2

    Hi again Ralf- thanks for another interesting and useful video. You have managed to fill an empty spot for all those that want to improve their knowledge with respect to what you teach and share. This is a great resource and I wanted to let you know it is much appreciated.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Spread the word indeed, Bikefarm Taiwan; the more people that get to know about Arduinos and their cousins the better the world will be as we implement solutions to problems we never even imagined could be solved by such a small device. You are most welcome, thank you very much for posting.

  • @leonardohomem
    @leonardohomem 3 ปีที่แล้ว +2

    @Ralph thanks for this whole lesson and experiments. I have consulted several sources on how to debounce and make these cheap encoders more accurate... None of them reduced the lack of accuracy without slowing down the readings... I used the CLK falling ISR + a HW debounce with the 1nF / 100k RC filter and now it works like a consumer product. Thanks again!

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว +1

      You're most welcome, Leonardo, I'm glad it worked for you.

  • @solmanJapan
    @solmanJapan 3 ปีที่แล้ว

    I purchased a rotary encoder and it's doing the same thing. Seeing this video really helped me to understand what's going on. Thank you!

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว

      Glad it helped, Solman!

  • @RandallStephens397
    @RandallStephens397 2 ปีที่แล้ว +4

    @7:48 that screwdriver scraping on the scope screen makes my teeth hurt X_X

    • @RalphBacon
      @RalphBacon  2 ปีที่แล้ว +1

      OMG 😲 it was indeed the screwdriver scraping over the screen. No damage done though, it was super light pressure - but I should have used a plastic indicator!

  • @hoggif
    @hoggif 5 ปีที่แล้ว +2

    I had problems with a clicky rotary switch when I used them first. I learned you really need to debounce them or measure every edge change. If you handle all edge changes, you need usually no debounce, because then bouncing up signal is counted like up-down-up-down-up-down-up (which is same result as a single "up" because the up-down pairs are cancelled). If detents give you more than one count, just divide it with a suitable value. I found quickly too that with very fast turning you probably start missing pulses.
    I think with every switch it is always very important to assume bouncing edges even if you have them or not. In future code may be pain to debug if you use different switch or you may get a buggy appliance by just replacing a broken rotary with another model that has debouncing you did not have before.
    BTW, my favourite method of debouncing often was using a timer interrupt and tracking if you have enough similar readings in a row. If you read 101010101111111, you may detect switch is probably stable 1 after several similar values. (and likewise 010101010100000000000 must surely mean stable 0 for now). If you need a "push" event, just keep track of the stable value and as stable value changes (happens only once), register a push. (or like every n events if you want a repeating button effect).

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว +1

      There speaks the voice of experience, hoggif! Yes, switch bounce should definitely be carefully considered and catered for. I've even come across commercial products that do NOT do this well and it results in a piece of equipment that becomes a pain to use (I have a DAB radio that does this). Thanks for posting your experience of switch bounce, I hope others reading this take due note!

  • @loftos1
    @loftos1 6 ปีที่แล้ว +3

    Hi Ralph, I had this problem when I was designing a rope counter for measuring rope off a reel, I overcame the bounce issue by using a Schmitt trigger, but as you said you can only rotate a mechanical encoder so fast so I used an optical one in the end for my application. The use of a schmitt trigger gives you a lovely clean output signal though on a mechanical encoder.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      I'm thinking that you and another viewer who has commented here (#I Suck at Gaming) are singing from the same hymn sheet - hardware debouncing is obviously a solution. That said, an optical encoder obviously circumvents all the bounce issues but a Schmitt trigger is also a (much cheaper) solution too. Perhaps I need to fully investigate this...

    • @icarossavvides2641
      @icarossavvides2641 2 ปีที่แล้ว

      Can't check it at the moment but most microcontrollers have some Schmitt inputs, I would expect the atmel family does too. As Mentioned elsewhere, it cannot be stressed too much that reading the datasheet of the microcontroller you're using is a must.

  • @spock2884
    @spock2884 4 ปีที่แล้ว +2

    Hello Ralph, thanks for sharing. I personally tries to do a strict separation between input, calculation and output. The shown method for decoding the rotary decoder volatile this. What i don't like is that the isr calculates a value. I think it's to limited and it throws away halve of the input information(the speed). I have made a decoding method that doesn't change a number but returns a value that give the direction and the time since the last puls. The calculation of the value that has to be changed is calculated in the sketch. That way i'm more flexible. This way i can add dynamics to the behavior. If the time is short the increment can be bigger.

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      And yours is definitely a better way of doing it, Spock, but I know that jumping around in the code during a demo just confuses people! So my way is not ideal but does show the principle. In Real Life your way is the way to go. Thanks for posting and Live Long and Prosper.

  • @andymouse
    @andymouse 4 ปีที่แล้ว

    Hi Ralph, having watched Greatscott use a motor from a hard drive as an encoder I thought I would have a go myself, and I had great results with it, I did it a little differently but it was quite good fun and was hoping "Killer X Treme" reads this !!!

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      That's great news, Andy, success can be so sweet!

  • @pekkagronfors7304
    @pekkagronfors7304 6 ปีที่แล้ว +1

    Great video. Very interesting about rotary encoders.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Glad you liked it Pekka, as you can see it generated a lot of conversation regarding debounce methods!

    • @pekkagronfors7304
      @pekkagronfors7304 6 ปีที่แล้ว +1

      Yes, many suggestions and ideas. I look forward to yet another rotary encoder video :-)

  • @peoplethesedaysberetarded
    @peoplethesedaysberetarded 6 ปีที่แล้ว

    Another slight aside regarding the sidebars into dual rotary encoders and hardware debouncing: thanks, Ralph, for seeing these inquiries for what they are: fans wanting to know more and hash out details. Thanks for not feeling threatened or thinking that to bring this question up is to devalue what you've done here.
    I like the channel. I am interested in your videos. I am quite curious to see where you go next, especially as I don't have a scope myself (sad-face) and therefore cannot easily visualize switch/encoder bounce (aside from a counter).
    One suggestion, in light of what seems to be coming: you may want to change this video's title to "... & Software Debounced." ;) Be well!

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Thank you for your continued support! I love it when viewers suggest things (see my comment against your last post regarding the debounce circuit I mentioned) as it gets my creative thoughts started. Pity you don't have any kind of oscilloscope; my recent video review of the Banggood cheapie (single channel) version should be good enough for this, I'll try and include that in any future video about debouncing. And thanks for the title suggestion, I will mull it over.

    • @peoplethesedaysberetarded
      @peoplethesedaysberetarded 6 ปีที่แล้ว

      Actually, I (embarrassingly) have that kit! I'm not sure that it will have good enough resolution, though. I eagerly-await the day when I can justify a Rigol scope.
      I've been out of soldering for a long time and was waiting on some new tips to come in. The solder just didn't seem to be flowing properly with the tip included with the soldering station. As I've said in the other comment, I look forward to your video! :)

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      And in the meantime watch #92 JYE Oscilloscope Kit Review & Build and ensure you have lead-free solder! Or a better soldering iron / tip combination. Seriously, this should be good enough to show rotary encoder pulses, but we shall see.

  • @jimbooth2010
    @jimbooth2010 2 ปีที่แล้ว

    Nice info, thanks. I am currently working on a rotary encoder project.

    • @RalphBacon
      @RalphBacon  2 ปีที่แล้ว

      Sounds great! Good luck with your project, Jim.

  • @ismzaxxon
    @ismzaxxon 6 ปีที่แล้ว +2

    I have known Nick for 10 years plus(via forums) Nick and I were using Atmel chips for that time. Arduino is an Atmel micro. Nick knows arduino as all we had years ago was machine code for these devices. As a side note, memory was so small, that we had to use machine code rather than wastefull C. C even uses RAM for contants and string that don't change etc.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      If I tell you Terry (and don't spread it around) that I used to have to program in assembler for the 6502 chip with just 4K memory, you will appreciate that I understand totally where you're coming from! These days, memory constraints are the last thing on developers' minds until you try and use the same techniques you use in commercial .NET-style programming on an Arduino. Hah! Then you suddenly realise that you really must write efficient code, and not have constant 'strings' in your code memory, which requires a bit of a paradigm shift in programming thinking. Nice to have someone on board with this appreciation!

    • @Roy_Tellason
      @Roy_Tellason 4 ปีที่แล้ว

      There are a few of us out there, I used to do z80 assembler back when...

  • @chrisw1462
    @chrisw1462 3 ปีที่แล้ว

    Rising and Falling for iterrupts are fairly well defined. The logic in the microcontroller has a set point where a low becomes a high and vice versa. When the signal crosses that value, the 'rising' or 'falling' interrupt would be triggered. The 'change' interrupt is triggered no matter which way it goes. If your input were a slowly moving ramp signal, you could get some wacky readings, since the rising point will be different from the falling point, voltage-wise. But with an on/off signal like the encoder, we don't have to worry about that.
    The code for using all four different states of a rotary encoder like this is fairly common. You need to read both pins on the change, and you need to know which one caused the interrupt. If pin A causes the Change interrupt and it's now High, it was rising. If pin B causes the interrupt and it's now low, it was falling. In the two separate ISR's, you have four states each: For the A interrupt: Pin A rising while B is low, or A rising while B is high. A falling / B high. A falling / B low. The B change interrupt would have similar states. If you study the timing diagram, you'll see that of these 8 states, four can only occur during clockwise rotation, and the other four can only occur during counterclockwise rotation. So you know immediately on getting the interrupt which way the encoder is turning, even if it skips due to being turned too fast. To halve the resolution, you could use Rising and Falling for A only, for example, and just ignore the other states. You'd only need to read B instead of both, since the interrupt already tells you A is Rising or Falling. This would be close to the code in the video, except you definitely know which way the encoder is turning. Taking it further, you could interrupt on one state - for example, A Rising. The ISR would only check B. If B is low, it's turning one way. High, it's the other.
    It's important to note that the debounce time is effectively doubled if you check all states, since the interrupt will be called two times more than the original code. If you use only Rising or only Falling, it would be simply 5 ms, or half the original code. This is important because it will affect how fast you can turn the knob. If you check all states, you get really high resolution, but the ISR is busy ignoring you for 120 ms for every full rotation. It won't take much speed to miss a few ticks, especially if you get a noisy encoder and have to increase the time above 5 ms.
    Most mechanical rotary encoders use wipers on a rotary disk with conductive fingers. It isn't a sprung contact pushed out of the way like a switch or relay - the wiper only has to move the thickness of the finger plating. The crossing does cause noise on the signal which will look like bounce, but it's much smaller than a sprung contact bounce. A 5 ms dead time wouldn't be long enough to debounce a sprung switch, but it works fine here, and even lower might be possible with a new encoder. Older ones get dirty and worn, of course, and will need more debounce time.

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว

      Good explanation! And I've discovered there are good Rotary Encoders and bad ones, in terms of switch bounce. The one used in my car, for example, is undoubtedly a much higher quality than the one I used in this video. Ironically, I bet General Motors paid about the same as they bought a few million of them!

  • @andreweastland9634
    @andreweastland9634 6 ปีที่แล้ว +1

    Interesting video, thanks. You need to add another layer to your code that looks at the last state of the pins. Although there are only 4 possible states, not all states are valid depending on what the previous state was. This way you can filter a lot of the spurious noise. E.g. if the last state was a=on, b=on then the only valid state to follow this is a=on,b=off or a=off,b=on, neither of the other two states are valid and so should be ignored. If you add this logic to your code you will improve the accuracy dramatically.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +2

      That is an excellent suggestion, Andrew. Hmm, I might try this out quickly as the hardware is still strewn over my desk! Thanks for the suggestion.

  • @shalbsb
    @shalbsb 2 ปีที่แล้ว

    thank you for exist. This video is so cool!

    • @RalphBacon
      @RalphBacon  2 ปีที่แล้ว

      Glad you liked it!

  • @Roy_Tellason
    @Roy_Tellason 4 ปีที่แล้ว

    I have one of those rotary encoders which came as one item of many in that batch of stuff I bought from banggood a while back, and hadn't gotten around to playing with it yet. I had no idea that contact bounce was going to be so much of an issue with it! My thinking while viewing this video was that optical was probably the way to go, and then you commented a bit after that about how expensive they were. I wonder if that's changed any since then? Perhaps salvage from a mouse might be the ticket...

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      Contact bounce can be dealt with very successfully within software (as I showed). Hardware debounce is better (video #98) but not essential. Optical is ideal but then you are talking more money. Salvage from a mouse is a great idea if you can get a mouse with a ball these days.

  • @arsenic1987
    @arsenic1987 6 หลายเดือนก่อน

    Hmmm.. Old video, but hey, I couldn't help but notice that the change in code of lastInterruptTime changes to a "minimum time between pulses".. But contact-bounce _was_ taken care of by just "waiting around" for a TOTAL of 5ms.. A single contact bounce of 5 milliseconds sounds like a VERY long bounce to me. Usually the bounces are in the microseconds range. But there might be 10-20 bounces, thus a total wait of 5ms is "probably good".
    But after moving it outside the if-clause, you could definitely reduce the time to make it more responsive, since every teeny bounce would reset the time.

    • @RalphBacon
      @RalphBacon  6 หลายเดือนก่อน

      Well, I reckon that 5mS is probably a reasonable time to wait for a switch bounce; some really bad switches can bounce for 20mS according to switch-bounce guru Jack Ganssle.
      I think I put the pdf of his work in my GitHub, definitely worth a read. I've just created a tiny switch bounce PCB with SMD components for a project I'm working on. Works like a dream and it's based on Jack's circuit.
      In that case, of course, hardware does the debouncing and no delays of any kind are required, the nirvana of software developers.

  • @fredriksjoblom5161
    @fredriksjoblom5161 6 ปีที่แล้ว

    Have you tried going over specs on your capacitor values? I saw a guy with similar problems, and he solved it by simply changing the 1nF caps to 100nF ones to give the microcontroller a longer time to cach these events.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      That's certainly one way to try and address the problem of switch bounce, Frederik. The main issue is that it may work for one switch but not another (so if you were a manufacturer you want repeatability of behaviour and that may not be the case here). I like the hardware solution but it involves further hardware and connections; the software solution can be made to work for almost any device but can introduce longer delays before a change is acknowledged. It's a minefield, don't you think?

  • @ipadize
    @ipadize ปีที่แล้ว

    i have never had good experience with these encoders. Then i found out about the Bourns ACE128 absolute encoder and also there is a library for the arduino available, which works perfectly. Yeah it doesnt have a clicky button and maybe has too much resolution (128ppr) but you can just divide the raw number by some amount which feels appropriate.

    • @RalphBacon
      @RalphBacon  ปีที่แล้ว +1

      That's a lot of non clicks for a single turn of the knob, for sure. But as you say, using a subset (eg 5 clicks) to equal one step would be fine. I'll check out that encoder, thanks for the info.

    • @ipadize
      @ipadize ปีที่แล้ว

      @@RalphBacon fyj, you can connect the encoder either via 8 pins + ground or connect the encoder to a i2c module

  • @andrewferg8737
    @andrewferg8737 3 ปีที่แล้ว

    Had the same issue with reversing errors on a 3 pin no-detent encoder. This debounce function cleared it up:
    bool debounce(int Button) // generalized function for active LOW button debounce
    {
    byte count = 0;
    for(byte i = 0; i < 5; i++)
    {
    if (digitalRead(Button) == 0)
    count++;
    delay(10);
    }
    if(count > 2) return 1;
    else return 0;
    }

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว

      That's quite a thorough test you've done there for debouncing, Andrew. I've found most switches do not bounce for longer than 5ms and even "bad" ones are done by 20ms (which probably means I should choose a better switch). Anyway, if that debounce routine works for you keep using it and thanks for sharing it here.

  • @Ray-ej3jb
    @Ray-ej3jb 5 ปีที่แล้ว +2

    You mention that the Uno's and Nano 's don't like/do Interrupts on High - Is this also true for the Mega? Does this apply to the main INT pins or to all all the interrupts associated with the pins eg Int On Change.

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว +1

      It's also true for the Mega, Ray. If you code HIGH it actually gets compiled as a CHANGE.
      On the Mega you can choose the following pins for a hardware interrupt: 2, 3, 18, 19, 20, 21.
      Only on Due, Zero and MKR1000 boards can you code a proper HIGH detection.
      Pin change detection is similarly limited to RISING or FALLING and you have to do all the detective work as to why you are suddenly in the ISR. It won't tell you the pin that got triggered nor the value!
      More info on pin change stuff here: playground.arduino.cc/Code/Interrupts

  • @willofirony
    @willofirony 6 ปีที่แล้ว +5

    With all due respect, I suspect that KillerExtreme has missed the point regarding rotary encoders. They are not physically confined (like, say, a potentiometer) to one full rotation or less. So, the resolution is decided by firmware. If his application needs finer control, he simply changes the mapping of the encoder's input to his output so that more degrees of turn are required to affect the output. Infact, having more steps per degree of turn, reduces the resolution of the control loop.
    Bounce: I agree with you, regarding lack of response in volume controls, etc. I do suspect one can become more sensitive to this phenomenon, the more familiar one is with the functionality of UIs. Those "plebs" who are blissfully ignorant of how these things work, respond to such inconvenience with "Oh, it is OK, It always does that". Is knowledge such a valuable thing?

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      You are correct, Michael, in stating that detecting each pulse edge *reduces* resolution - my video clearly showed that having it that sensitive made it awkward to use. If #KillerExtreme wanted to use his rotary encoder for precisely tuning a radio then fewer pulses for a given amount of travel work better. On the subject of...
      On the subject of Bounce, you are once again IMHO correct. Ignorance is indeed bliss. Whenever my car radio's volume control does not respond as I expect it to I think 'missed pulse detection again' instead of 'must turn it slower'!!! Too much knowledge is indeed a dangerous thing.

    • @ismzaxxon
      @ismzaxxon 6 ปีที่แล้ว +1

      Commercially, You dont do so many pulses. As encoders age, they get worse. Also, when you have an inbuilt push button, fast changes causes last minute changes...hence complaints from customers.

    • @willofirony
      @willofirony 6 ปีที่แล้ว

      At least I was correct in assuming you deserved respect :-)

  • @maxximumb
    @maxximumb 6 ปีที่แล้ว

    Great video. I wondered how rotary encoders knew which direction they were moving. I've never used one so never needed to find out. But now I know.
    You mentioned that optical rotary encoders were expensive, what are the rotary components in mouse wheels? They have a slotted wheel between and LED and what I'm guessing is a photodiode of some type. Is this an optical rotary encoder, or a different type all together?

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      A (non-laser) mouse is a very good example of an optical rotary encoder - but they are not something you could easily wire up and include in your latest Arduino project! I don't know why standard optical rotary encoders are so expensive (£20 - £50). Perhaps they are designed to be connected to a motor that you are trying to measure the speed of. Or the Chinese manufacturers haven't overproduced them yet so they are not readily available on eBay at low cost. Whatever, they are currently beyond my price range so we'll have to wait until they drop in price... Nice to hear from you again Maxx.

    • @maxximumb
      @maxximumb 6 ปีที่แล้ว

      Ah, I've just been looking through my parts bin and found that most mice have just a 3 pin rotary encoder. The optical one must have been from a more expensive mouse that I salvaged. But I did find more optical encoders in printers that I've taken apart for parts. That might be a source for optical rotary encoders if you needed one on the cheap.
      I ask all my friends and family for their old electronics, good supply of motors, encoders, MOSFETS, and other components. It's harder to salvage SMD parts, but I've yet to find an electronic cast off without some useful parts. Even if it's just wires and cables.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Too true, salvaged parts can often realise good finds, even if only for experimentation. Optical rotary encoders are used in many places as you mention - except in the Arduino hobbyist world it seems. Oh well... non-optical still do the trick for 99% of the uses we need them for!

    • @maxximumb
      @maxximumb 6 ปีที่แล้ว

      I'm slowly collecting stepper motors and rods etc, to make myself a CNC. This isn't going to be a fast project, but I thought to use printer optical rotary encoders to give the Adruino feedback as to the cutting head's location on the x/y axis.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      I don't see why that would not work. Perhaps you could read up how 3D printers know where the printing head is, if it works for a 3D printer it will work for a CNC machine too?

  • @tubical71
    @tubical71 6 ปีที่แล้ว

    Using a little bit of added hardware will help a lot regarding de-bouncing and encoder detection speed/tracking.
    Here to see: th-cam.com/video/xw1HIFOe_Ik/w-d-xo.html
    I added some schmitt-triggers at both encoder switch pins, basically a 7414 which has four of them inside and simply daisy-chained two of them on one encoder pin. The first one also has an RC filter 15kOhms in series with an 0.33muF cap to ground to eleminate spikes. This setup works up to hundrets of RPMs...

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      Now that's interesting as I designed a simple debounce circuit using a quad nand gate CD4013B with the intention of using two per pin (in series) to ensure the signal was not inverted. Sounds like my logic is good, given your experiences. I also am including an RC filter as suggested by the makers of a dual rotary encoder, but I might adjust the values to your ones as you have had success. Thanks for this #TubiCal, appreciated.

  • @AnalogDude_
    @AnalogDude_ ปีที่แล้ว

    i believe there also ones that have leds inside and also "friction-less".
    Would like to try these.

    • @RalphBacon
      @RalphBacon  ปีที่แล้ว

      The ones with LEDs inside are called _optical_ rotary encoders and can turn at ridiculous rates, with zero bounce. The frictionless ones are called _stepless_ rotary encoders but require a bit more coding to use without getting confused exactly which state it's in.

    • @AnalogDude_
      @AnalogDude_ ปีที่แล้ว

      @@RalphBacon i have one standard alpha, it's soldered on a board, but would you try again?, using a 200Hz timer, hardcore direct access to the port not using the "Arduino language" and via bit masking to isolate the needed pins, sampling the pins is what i did.
      the timer interrupt takes the port value and the mainloop handles it.

  • @williammiller7543
    @williammiller7543 6 ปีที่แล้ว

    Ralph,
    Thanks for the update. Would you consider doing this with an ESP32? I'm using a ESP32 to control a Sous Vide cooker/PID loop. and would like to use the encoder to control a menu for time and temp changes and I'm not sure how to use an interrupt with the ESP32. I don't want to be sitting there checking the state of the encoder constantly. The program could be away from the PID loop for a second or two but it cannot be gone for any extended time or the temp will be way off.
    I've switched most of my project MC work over to an ESP-8266 and now a ESP32 because of its additional features

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      The ESP32 is certainly the flavour of the month! And you're in luck as the ESP32 has two cores, with 32 interrupts each. Exactly how to use them is best understood by reading this: esp-idf.readthedocs.io/en/latest/api-reference/system/intr_alloc.html from the makers, Espressiff. This is a good document (v3) to read anyway.
      In due course, and as my understanding of the ESP32 increases, I will no doubt be doing something with it that requires interrupts. For the ESP8266 it's even easier as you can use any of the GPIO pins (except GPIO16). Wow, spoilt for choice. Thinking about it, my original sketch for Rotary Encoders should run unmodified on an ESP8266 board (eg ESPDuino), but I haven't tried it (yet). You might want to though (and let us know whether it works as expected).
      I'll add the task to my ever-growing list, William, so if you don't do this before me keep your eyes peeled for a video on interrupts on the ESP32 in due course.

    • @williammiller7543
      @williammiller7543 6 ปีที่แล้ว +2

      Thanks for your quick responce. I'll give yor suggestion about trying the original rotary sketch on a ESP-8266. I have the parts needed and I'll let you know.

  • @icarossavvides2641
    @icarossavvides2641 2 ปีที่แล้ว

    Not sure exactly what killer-x-treme's problem is but I'm assuming he (?) wants a high resolution so he can tune the VCO in small steps? Well he's got a built in switch so I would have thought an obvious and reliable solution might be to have multiple step weightings selectable by pressing the switch? Course = 10MHz steps, press, 1MHz steps, press 100KHz steps etc. On heritage analogue instrumentation we used to have two knobs, course and fine.

    • @RalphBacon
      @RalphBacon  2 ปีที่แล้ว

      Sounds like a plan worth exploring. Let's hope he reads your comment.

  • @jeffschroeder4805
    @jeffschroeder4805 11 หลายเดือนก่อน

    If you were using a micro-controller with more interrupt pins, could you use 2 to determine direction and count detents and another 2 to count pulses in between detents? That might allow you to simplify the code and reduce the likelihood of losing track of the direction.

    • @RalphBacon
      @RalphBacon  11 หลายเดือนก่อน

      Quite possibly, although it would not be usual to use two interrupt pins for one rotary encoder. Most manufacturers just ensure you turn the knob slowly enough for the underlying code to keep up (my radio does this and just ignores me if I try and spin it too fast).
      However, that said, perhaps your approach could work - if you ever get the time (and inclination) do try it out and report back!

  • @terryschabert7929
    @terryschabert7929 ปีที่แล้ว

    How much overhead does the serial.write affect the sensitivity of the resolver, or the perceived errors in the count? The interrupt may take too long or the serial.write may act as an additional interrupt when it is buffered.

    • @RalphBacon
      @RalphBacon  ปีที่แล้ว +1

      Serial.print (or write) takes a relatively _huge_ amount of time which is why they must never be included in any interrupt routines (other than when debugging, and even then keep the output to as short as possible).

  • @erikisberg3886
    @erikisberg3886 4 ปีที่แล้ว

    Thank You for an excellent review of the troubles with rotary encoders!
    I am an EE and have seen many variants of these missbehaviours over the years. I concur that analog filtering, schmidt triggers and proper software in a tasteful mix is the way to go to achieve good performance.
    It is usually a good idea to start with the oscilloscope first and figure out the timeconstants of the noise and the desired signals. I have also noticed the behaviour You showed as in the car stero and found it very annoying.

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      Thank you very much! Without a doubt, Schmitt triggers are a foolproof way to go but you need more components. Thanks for posting.

  • @dinodubroja7433
    @dinodubroja7433 3 ปีที่แล้ว

    Low is not zero, it's around 0.3 volts, so you could use RAISING bridge as a trigger for the counter same as you use FALLING, no worries.

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว +1

      Hmm, interesting suggestion. I'll add it to my list of things to investigate.

  • @eastern815
    @eastern815 6 ปีที่แล้ว +1

    Good video and watch your video still learn a lot. Could you make a tutorial about OV7670 with FIFO?
    There are some tutorial about ov7670 but no fifo and the resolution is no good.
    So I bought a fifo one. But I can not figure out it how to work.
    So if you make a tutorial video about ov7670 with fifo.
    I will appreciate you. Thanks!

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      The Jtron OV7670 comes in multiple flavours, Zhang yixin, one VGA, one 300K pixels, and some with the AL422 frame buffer chip (thus making them FIFO). I don't think I have the FIFO module (I acquired one a while ago) which means the Arduino will be too slow to capture a frame, but I will check. It's a useful, cheap camera for making simple snapshots to an SD card - the Arduino can easily do this. Stay tuned, this would be a good video for Arduinites (even if you might have to use a Mega rather than an Uno).

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Would you believe it but my camera *does* have the AL422 chip on it so I will now have to do a video on how to capture photos onto an SD card using an Arduino (MEGA, probably). Woo hoo!

    • @eastern815
      @eastern815 6 ปีที่แล้ว +1

      That's a good news ha ha. Looking forward to your tutorial video Master Ralph.

  • @jeffbluejets2626
    @jeffbluejets2626 5 ปีที่แล้ว

    One can get a 600 ppr optical rotary encoder from Ebay these days for as little as Aus$13.00 - $14.00 . I am about to look at using them in fact (as a counter) or rather as a dual counter for sync on a spindle to leadscrew and that is what brought me here.
    This brings up another query you may be able to help me with, using 2 of these optical rotary encoders, one on the spindle and one on the leadscrew, if I am to use both interrupt pins , would any problem arise from missing pulses ? As I understand it only one interrupt can happen at a time.
    Possible it is explained somewhere, ( need to look further) just thought I'd ask while I'm here.

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว

      Well, Jeff, an interrupt can't be interrupted, so if your code was dealing with a pulse from one Rotary Encoder and the other one then triggered an interrupt, that interrupt would be queued to run once the first one was completed. So no missed pulses but if your ISR is too long you could have too many queued up.

  • @ismzaxxon
    @ismzaxxon 6 ปีที่แล้ว

    Slow increments is normal, use pushbutton function to have counter add more than one. Push button again to return to normal increment of 1.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Ah yes, that would work. Perhaps we (OK, me) try too hard to solve problems 100% when the good old 80/20 rules applies (if it's good enough...).

    • @MC_AU
      @MC_AU 6 ปีที่แล้ว

      a common solution to that is keeping track of the interval between pulses...
      Then you can make the ‘speed’ proportional to the rate of rotation.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      @MC That works if we accept each pulse as being a proper pulse without rejecting it, designating it a 'bounce'. However. I've just completed a small debounce circuit which means we must be able to trust each pulse as being a true pulse (no more debounce timings) so your method would then work really well.

  • @KW-ei3pi
    @KW-ei3pi 8 หลายเดือนก่อน

    Hey Ralph. At about 6 minutes, you mentioned that the detent encoder has built-in pull up resistors. Would that be true of all detent encoders? That would explain why my works without needing to call a pull up in code. Thanks

    • @RalphBacon
      @RalphBacon  8 หลายเดือนก่อน

      If you buy a "module" where the rotary encoder is already mounted on a tiny PCB, then undoubtedly the manufacturer has added pull-up resistors (but never guaranteed, of course). They do this so it works "out of the box" and they don't get lots of negative feedback from noobs who are unaware of the need of pullups (or INPUT_PULLUP in your sketch).

  • @jeffbluejets2626
    @jeffbluejets2626 4 ปีที่แล้ว

    Hi Ralph, could you explain line 34 a bit more as it appears max and min are reversed. I did a search of that particular line to see if I could understand it but nothing really came up.

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      The "min" function takes the lower of the two values. So, if we do min(100, 54) we will get 54. If we have min(100, 244) we get 100. We could write it with the values either way round.
      I suspect the max() in the middle of it has confused you.
      Arduino state: "Perhaps counter-intuitively, max() is often used to constrain the lower end of a variable’s range, while min() is used to constrain the upper end of the range."
      Basically, that line restricts the maximum to 100 regardless of what the value is. Write a small sketch (it will take 5 minutes) and use the Serial input to enter two numbers to see how it works. That way, Jeff, you will truly understand it.

  • @joelsmart9485
    @joelsmart9485 4 ปีที่แล้ว

    Wow Ralph and Julian Lett would have to be mates I think they share the same work mat

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      He stole his from me. Mine's newer. And bigger.

  • @KJW648
    @KJW648 6 ปีที่แล้ว +2

    Optic rotary encoder ! could you make one, with a cheap or old mouse wheel ?!? :)

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      That's a really kind offer, Kuk, but I really want to use 'standard' components that others can then source too. I don't know why optical encoders are so expensive, when as you say, they were used in old mice that you could buy for £3 - but an optical rotary encoder is nearly 10 times that cost. Thanks again for the offer, stay tuned for more on encoders and interrupts!

    • @crayzeape2230
      @crayzeape2230 6 ปีที่แล้ว +2

      Ralph, did you read Kuk Willson's post as "I could make you one" perhaps?
      Kuk Willson, yes, you could use the optical encoder from a mouse.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      Yup. Thank goodness I declined his "offer"!!! Well, I came to my PC this morning and had a zillion messages from last night's video. Obviously I didn't read this one correctly although I feel Kuk probably would have built me one if I had asked! Right Kuk? Er, Kuk? Obviously, he's just popped out for a minute...

    • @paulpvhl1930
      @paulpvhl1930 4 ปีที่แล้ว

      @@RalphBacon This is old, but … I read it as you did Ralph until I looked again. I find this type of cognition error fascinating. Looks like we both read the separated exclamation as a capital I, possibly because the following c was lowercase. I love it!

  • @ipadize
    @ipadize ปีที่แล้ว

    28:58 i have some with 512ppr for my servo motors and i could spin them at 6000 rpm without a problem (i was using Mesa hardware though, really good stuff)

    • @RalphBacon
      @RalphBacon  ปีที่แล้ว

      I'm guessing that those RE were optical then? A mechanical one would never survive (nor work at) those speeds!

    • @ipadize
      @ipadize ปีที่แล้ว +1

      @@RalphBacon yes optical, also shaft mounted. HEDS 5540-i14

  • @johnnymotorboat8824
    @johnnymotorboat8824 6 ปีที่แล้ว

    In case anyone missed it. When one pulse goes high, the other goes low. Well off to take my counter-depressant and counter psychotic medication.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      It's not as simple as that, David. The pulses are out of phase by 90 degrees, so turning the encoder in one direction gives you a particular value on the pins whilst turning it in the opposite direction gives you a different value - that's how we can determine direction.

  • @janhellstrom4165
    @janhellstrom4165 6 ปีที่แล้ว

    Hello Ralph,
    I have tried your Rotary Encoder code and it seems to work fine. I intend to use it in my attempt to make a speed controller for my CNC spindle, but I have some questions about your isr routine.
    In Arduino's homepage:
    www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
    you can read "Generally, an ISR should be as short and fast as possible"
    and also "millis() relies on interrupts to count, so it will never increment inside an ISR"
    Your isr routine is quite long and you are using the millis function.
    Could that give me any problem if I add more code for PID-regulation and so on?
    I like your videos with clear and good explanations!
    Regards Jan

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      Hey, Jan! Let's try and clear up any confusion over ISRs!
      I have often stated that an ISR should do the least amount of work possible - but I'm doing demos in my videos which necessitate putting Serial.print and other long-winded stuff in there, just to show the point I'm making - BUT which should NEVER be put there in a real sketch. If you can get away with just incrementing (or decrementing) a counter that's the best possible scenario.
      Using millis() in the Rotary Encoder sketch is absolutely fine and is an accepted way of stopping switch bounce (where the mechanical switch actually bounces a few times in an extremely short period of time, almost always less than 5ms, but which is an eternity to even a humble Arduino Uno, so it counts EACH of those bounces). The millis() value will NOT increase whilst inside the ISR but that's fine - we can safely use a 'snapshot' value for that aforementioned debounce feature.
      What you don't want to be doing is putting logic inside there. Let the main loop() function do all that by checking the count (or whatever) you're updating inside the ISR. That includes PID calculations! Remember that whilst the ISR is running, the main loop() is BLOCKED, not a good situation. Further requests to the ISR just get queued, making the situation worse!
      I hope this helps in your sketch design, but do come back with more questions as you develop your code. I'm really happy you like my videos and thanks for posting an interesting question.

  • @Krishnavisweswaran
    @Krishnavisweswaran 5 ปีที่แล้ว

    Could you try the following code and see if it works better for responsiveness and bounce detection?
    It should work for both types of encoders (as long as you use either INPUT or INPUT_PULLUP appropriately.)
    // Clock signal
    const unsigned int pinA = 2;
    // Data signal. We are not going to use an interrupt on this.
    // So can be some other pin to save the HW interrupt pin.
    const unsigned int pinB = 3;
    volatile int count = 0;
    void isr() {
    static int lastClk = -1; // Initialize to an invalid state.
    int clk = digitalRead(pinA);
    if(clk == lastClk) return; // Bounce!
    lastClk = clk;
    int data = digitalRead(pinB);
    if(clk == data) { // anti-clockwise
    // remove the 'count > 0 check if you want to allow -ve values
    if(count > 0) count--;
    } else { // clockwise
    count++;
    }
    }
    void setup() {
    Serial.begin(115200);
    pinMode(pinA, INPUT); // use INPUT_PULLUP if required.
    pinMode(pinB, INPUT);
    attachInterrupt(digitalPinToInterrupt(pinA), isr, CHANGE);
    Serial.println("start");
    }
    void loop() {
    static int oldCount = -1;
    if(oldCount != count) {
    Serial.print(oldCount < count ? "UP" : "DOWN");
    Serial.println(count);
    oldCount = count;
    }
    delay(200);
    }

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว

      I have a better idea, Krishna. You get a Rotary Encoder, an Arduino Uno and _you_ try it out. That way you get experience and learn the answer to your own question. How about it?

  • @boldford
    @boldford 6 ปีที่แล้ว

    Hi Ralph. There's not much wrong with Rainharvester's suggestion. By using it you tend to encourage people to treat rotary encoders with a little more respect. Were you to spin my car's radio volume control like you did your own for demo I wouldn't be overly happy. Consumer products aren't meant to be "squaddie proof"!

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +2

      Agreed, Brian, I was definitely abusing that volume control but purely in the interests of science! If nothing else, the fact that is *doesn't* respond when turned quickly makes me turn it very slowly indeed in day-to-day use. It has trained me!
      But given this is not some cheap Far Eastern component built down to a price but is a commercial, robust item in a GM/Vauxhall/Opel car I felt it would survive a couple of quick spins! Did you not find it interesting though that it also went "backwards" in relation to the direction of spin on a couple of occasions? So we are not alone in the Arduino world in getting either the logic or hardware to behave correctly.
      Loved the "squaddie proof" comparison (with no offense to any squaddies on my channel!), personally I think it might just survive :)

    • @boldford
      @boldford 6 ปีที่แล้ว

      Great channel. I waiting for some REs to arrive so I can simulate multi-multi-turn pots to set CV & CC on a lab PSU. I have learned, although it has a magnitude reduced ripple, the Arduino derived 3.3v isn't too hot as a reference as it's anything but stable over a range of temperatures.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      Sounds like you need a temperature compensated voltage source, Brian. Maybe a MAXIM MAX6143, or TI MC34063AP. I'm guessing there must be dozens out there, that you can run from the 9v/12v that you have available and get it rock solid. Have you noticed that some chips are now only available as surface mounts? Makes the soldering a bit trickier!

    • @boldford
      @boldford 6 ปีที่แล้ว

      SMD = An excuse to practice real use of the recently obtained microscope/camera.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      You've just given me justification for getting one. Thanks!!!

  • @jonshygye5005
    @jonshygye5005 6 ปีที่แล้ว

    Using a "noisy" signal to trigger interrupts just seems a poor choice. Those spurious interrupts can cause a performance hit and the incorrect readings. Just cleaning up the interrupt signal should suffice.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      That does seem to be the consensus, Jon. So I've built a simple Schmitt trigger buffer to clean up those pulses which appears to work nicely but I need to inject a rubbish signal to prove it can work to you guys in extreme cases. Hmm, a simple triangle-wave signal injector, now there's a topic for a future video maybe... Thanks for posting and adding your voice to the "use a hardware debouncer!" clamour, I am now persuaded this is the way to go!

  • @markopinteric
    @markopinteric 3 ปีที่แล้ว

    There is no need for "dead time" (5ms) because, unlike common switches, the rotary encoder has to go through four different stages to create one event. I wrote software that checks this, has no dead time, and works perfectly whether you turn the encoder fast or slow. I would be happy if you could try it out and see if it solves your problems. The code and explanation can be found on the website www.pinteric.com/rotary.html.

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว

      I'm intrigued in how you resolved the switch bounce issue if you don't ignore signal for a specific length of time after the first such signal.
      I've looked (very briefly) at your webpage and I intend to read in more detail when I have a few spare moments. I especially like the "impossible movement" signal which can be ignored, I'm guessing.
      I'd love to try your code out but my (new) workshop is in disarray (typical British understatement) so it will be a while before I can do that.
      Thanks for the info, appreciated.

    • @markopinteric
      @markopinteric 3 ปีที่แล้ว

      @@RalphBacon Very simply, in order to confirm one move left/right encoder must go through successive four states. Bouncing between two neighboring states is ignored, which is why I don't need dead time. Impossible movements (when one state is skipped) lead to movement to be ignored. I already got feedback from one person that (after looking for several years for this) confirmed my algorithm solved his problem.

  • @peoplethesedaysberetarded
    @peoplethesedaysberetarded 6 ปีที่แล้ว +1

    Ralph:
    Why, why, why, why are people so terrified of hardware debounce? Hardware debounce (a) filters bounce from your encoders and switches; (b) can be used natively with ISR calls--as most people use delay() to do software-debouncing, and as delay() cannot be used with ISR calls, the naive "back off for n ms then re-read the input pin value" manner in which many people implement software debounce is incompatible with ISRs.
    I was hoping to see hardware debounce in your video today. Sadly, no. But you must have a very good reason for this and know something that I do not. I'm after this missing bit of information.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      I feel your sadness in the same way you feel my terror at the thought of hardware debouncing! Seriously though, (and see the comment by #loftos1 here) I'm now thinking I should be seriously looking at a simple Schmitt trigger or similar. The reason I tried to do it without extra hardware is because I was certain we can manage without that extra layer of hardware - the video clearly demonstrates that my hypothesis was flawed. Stay tuned, I Suck At Gaming, the debouncing story is not yet complete... and thanks for posting.

    • @ismzaxxon
      @ismzaxxon 6 ปีที่แล้ว +1

      Noone uses hardware debounce in industry. Costs footprint on pcb.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      In fact, (and spooky timing) another viewer has asked about a dual rotary encoder. That aside, the data sheet for said encoder includes a simple circuit for hardware debouncing with a capacitor, resistor and simple 74HC14 Schmitt trigger. I may have found the simple hardware debounce circuit for which I feel no fear whatsoever :) (link: www.leobodnar.com/products/BU0836X/ELMA-E37.pdf ). what do you think #ISuckAtGaming, is this what we all need and then we can forget about skipping pulses, delays, re-reading input pins and the like?

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      I wonder how industry addresses the problem of debouncing then? Like my car radio, just accept s-l-o-w pulses and say that's the way it is designed (which is quite OK, as they are producing the product)? This was my assumption which is why I *really* tried to do this without extra hardware but... see my response here about a simple Schmitt trigger.

    • @peoplethesedaysberetarded
      @peoplethesedaysberetarded 6 ปีที่แล้ว

      Hmm. I can appreciate this argument Terry--one 7414 per six inputs, one R/C per input adds up. In industry, then, do they just rely on really fast sampling (running at speeds much greater than 16KHz of the Atmel lines)?
      In my own project, I'm electing for hardware debounce because (a) it's a niche product and I'll eat the quarter per board in extra costs, and slight size increase of the board; (b) I'm a software person and want to reliably believe my underlying hardware signals are accurate and stable--when a logical 1 is reported, I want this to be a post-bounce 1.

  • @ArjanvanVught
    @ArjanvanVught 5 ปีที่แล้ว

    I really would like to see the same code on a STM32

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว

      Hmm, I'm not really familiar with the STM32 (didn't I do a video on it once?) but as long as it has a hardware interrupt pin it should work pretty much the same, I would have thought...

  • @Taki7o7
    @Taki7o7 ปีที่แล้ว

    You do not count the steps in between. Basically, you have to make 2 little ticks with that.
    I solved it like so:
    void doEncoderA()
    {
    if ( rotating ) delay (1);
    if ( digitalRead(encoderPinA) != A_set )
    {
    A_set = !A_set;
    if ( (A_set && !B_set) || (!A_set && B_set) ) {
    encoderPos += 0.1;
    Consumer.write(MEDIA_VOLUME_UP);
    }
    rotating = false;
    }
    }
    void doEncoderB()
    {
    if ( rotating ) delay (1);
    if ( digitalRead(encoderPinB) != B_set )
    {
    B_set = !B_set;
    if ( (B_set && !A_set) || (!B_set && A_set) ) {
    encoderPos -= 0.1;
    Consumer.write(MEDIA_VOLUME_DOWN);
    }
    rotating = false;
    }
    }
    And making the counter variables floats instead of ints

    • @RalphBacon
      @RalphBacon  ปีที่แล้ว

      Thanks for sharing! I'm not sure about making the counter a float (why?) but if this all works for you, then it works! 👍

  • @konturgestalter
    @konturgestalter 6 ปีที่แล้ว

    Hi! Can you please make a video about how to code for a dual rotary encoder?

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      I'm not sure I really know what a DUAL rotary encoder is - have you got a link that I can use, or a part number?

    • @konturgestalter
      @konturgestalter 6 ปีที่แล้ว

      It would be fantastic.. building a homecockpit... and these are used tons... www.leobodnar.com/shop/index.php?main_page=product_info&products_id=196

    • @peoplethesedaysberetarded
      @peoplethesedaysberetarded 6 ปีที่แล้ว +1

      A dual rotary encoder is the same as a single, except with more pins.
      Look up "dual concentric rotary encoder" or Elma E75 (sorry, E37). There's an inner and outer ring, both of which can be turned. These lead to more pins on the back and you can monitor these just as you would two regular encoders (except they have a common ground and common body).
      But: dual rotary encoders are EXPENSIVE. I can order a bag of 10 rotary encoders for a couple dollars, delivered. But one dual rotary encoder comes to around $14 delivered.

    • @konturgestalter
      @konturgestalter 6 ปีที่แล้ว

      You are right... ELMA are by the way the official supplier for Boeing cockpits and have the best quality. It would be great to learn more about them though.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      I've had a look at this, #konturgestaltung, and as #ISuckAtGaming has mentioned these are effectively two rotary encoders in a single body.
      The outer sleeve on the shaft controls one A/B set, the inner shaft controls another. They are not joined internally (other than the ground). To use these you would simply treat them electronically as two entirely separate encoders, but remember than an Arduino only has two interrupts so if you use my original sketch from video#19 with an extra interrupt for the second encoder's A/B pair it would work exactly as expected. Does any of this make sense to you?

  • @josepheccles9341
    @josepheccles9341 3 ปีที่แล้ว

    If someone needs to have a fast encoder, they should use an optical encoder.

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว

      Not just fast but no switch bounce either! Win win.

  • @hm-yt7lv
    @hm-yt7lv 6 ปีที่แล้ว +1

    please Ralph you are talking quickly some time i can't understanding some world .i like your channel.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว +1

      I'm sorry about that Hafedh, try switching on the (auto) subtitles, that may help you (depending on whether Google can correctly understand me). In the future I will bear in mind that many of my viewers do not have English as their mother tongue and I will slow down. But I am glad you still like my channel.

    • @TheKetsa
      @TheKetsa 6 ปีที่แล้ว

      I'm not a native english speaker and I can understand you no problem.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      For which I'm profoundly relieved, #TheKetsa. But sometimes I do notice I either mumble a word or don't speak that clearly - something that competent English speakers will still understand but which viewers with a poorer grasp of English would struggle with. Even my cat, Benny, doesn't always understand me. Or pretends not to. Hmmm.... Thanks for confirming that on the whole my English is OK!

    • @scottmitten2248
      @scottmitten2248 6 ปีที่แล้ว

      If you click on the settings icon (Little Gear) in the bottom right of the TH-cam window, you can adjust the speed. 0.75 might be easier to understand without sounding weird. (I often watch videos at higher speed in my native language if I'm looking for an overview, or general interest, but slow it down if I'm really trying to grasp a concept. Can be pretty handy.

    • @RalphBacon
      @RalphBacon  6 ปีที่แล้ว

      Couldn't agree more Scott! I often listen to courses at x1.5 in English but slow it right down when I need to follow instructions and so forth. This should really help non-native English speakers (other than me not gabbling, mumbling or anything else that doesn't sound like BBC English!).

  • @lohikarhu734
    @lohikarhu734 4 ปีที่แล้ว

    a 'detented' encoder is far, far from 'standard... more typical are continuous encoders, with far more steps per revolution, like 1024 per rev...

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      Hmm, the one in my car (volume, tuning) is detented. Makes it a more positive action, I feel. Not to say it's not standard, I suppose. Depends on its use, I would imagine.

  • @lsfornells
    @lsfornells 5 ปีที่แล้ว

    One problem with using external interrupts on these mechanical encoders is that there’s no way to reliably filter contact bounces. A better approach is reading the encoder inputs inside a fast timer interrupt and only accept steady changes of the input pins. This also has the advantage that you can use any regular input pins for the encoder. This approach works extremely well at any encoder rotation speed, from very slow to significantly fast. In case you want to have a look, this is is demonstrated here: github.com/John-Lluch/Encoder

    • @RalphBacon
      @RalphBacon  5 ปีที่แล้ว

      I don't usually disagree with my viewers, on the basis they know more than me, but on this occasion, I think my hardware solution is the best I found, Isfornells. 100% reliable too, at least in my testing! And...
      If you watch my video #19 (the original Rotary Encoder video) the software solution worked pretty well too, at the speeds I was using it anyway. The trouble with "accepting steady states" is that it involves multiple reads, which are time-consuming and not best suited to an interrupt routine, IMHO. Debouncing has got to occur somewhere, after all. Using "any pin" for an interrupt might work well for some but my video was targetted at using the built-in interrupt pins precisely because they can be relied on.
      Each to their own! If you have a solution that works well for you it might work well for others too so thanks for sharing the link, you never know who might read this in the future. Thanks for posting, appreciated.

  • @alanesq1
    @alanesq1 3 ปีที่แล้ว

    I have been struggling recently to reliably use a cheap rotary encoder on a menu and finally found a method which works very reliably for me, so thought I would share it here in case it is of use to anyone else.
    see: alanesq.eu5.net/temp/rotary-encoder.txt
    It stores the last received pin states and the debouncing mostly happens simply by ignoring any repeats of the same pin states then just through a series of if statements it looks for a valid change in the pins (e.g. when turning one direction the pin states just alternate between 0,1 and 1,0).
    btw - you can see the menu I have used this on here: github.com/alanesq/BasicOLEDMenu

    • @RalphBacon
      @RalphBacon  3 ปีที่แล้ว +1

      That is great, Alan, nice and reliable is exactly what we need with these cheaper rotary encoders, thanks for sharing.

  • @mwngt12
    @mwngt12 4 ปีที่แล้ว

    Hi Ralph,
    Many thanks for your video. Please I have a query as I came across a particular situation in my project:
    I’m using MEGA2560 R3 and want to read 4 pulses per step from my encoder. It’s a step-less BOURNS encoder with 36 PPR (eu.mouser.com/datasheet/2/54/CW1J-777413.pdf), so my aim is to read 144 pulses per turn. After online research and testing, I managed to write a simple code that debounces the encoder through software -see below- (this includes two CHANGE ISRs, each for the encoder pins A & B, and a variable to count the pulses in either direction.) After completing the circuitry and the coding for one encoder, I’m getting one of the strangest things: even though my board always detects 144 pulses per one turn in total (whether I turn the knob slowly or really fast), at certain points it seems to mistaken the input signal from one pin as though it came from the other, thus messing with the Counter’s final value due to flipping the increment's sign at those particular instances.
    Looking deeper into it, I simplified the code further to only print out on the screen either “A” or “B” at the end of either ISR, indicating which pin has been triggered on the encoder, followed by 1 or 0 to state whether that pin had come to a low or high state. So in a normal turn of the knob, I get a nice toggle like this:
    A0 B0 A1 B1 A0 B0 A1 B1 A0 B0 A1 B1 …
    But then I also get something like this:
    A0 B0 A1 A0 A1 B1 B0 A0 B1 A1 B0 B1 B0 B1 B0 A0 …
    I don’t know if you’ve ever come across such an issue, as I’ve not yet succeeded to find an explanation on how this could happen, that is, if it were not due to the code itself, but rather maybe a hardware issue. But if it's from the code, could it be that the interrupts are queuing up because I'm turning the knob too fast? or another reason? Any input or assistance on this matter would be much appreciated.
    Many thanks for your help in advance, and for reference, here’s the code that I wrote so far:
    const int encPinA = 2; //interrupt pin
    const int encPinB = 3; //interrupt pin
    volatile int p = 0; // counter
    volatile uint8_t a;
    volatile uint8_t b;
    volatile uint8_t a0;
    volatile uint8_t b0;
    void setup() {
    pinMode(encPinA, INPUT_PULLUP);
    pinMode(encPinB, INPUT_PULLUP);
    a0 = digitalRead(encPinA);
    b0 = digitalRead(encPinB);
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(encPinA), ISREncPinA, CHANGE);
    attachInterrupt(digitalPinToInterrupt(encPinB), ISREncPinB, CHANGE);
    }
    void ISREncPinA() {
    b = digitalRead(encPinB);
    if (b0 != b) {
    b0 = b;
    (b0 == a0 ? p++ : p--);
    Serial.println(p);
    }
    }
    void ISREncPinB() {
    a = digitalRead(encPinA);
    if (a0 != a) {
    a0 = a;
    (a0 != b0 ? p++ : p--);
    Serial.println(p);
    }
    }
    void loop() {
    }

    • @RalphBacon
      @RalphBacon  4 ปีที่แล้ว

      The problem you're describing I have also experienced with these stepless rotary encoders. I believe it's switch bounce that is confusing the µC. Some work better than others. Stepless always work poorly compared to stepped devices too. There's no easy solution. By the time you have catered for switch bounce you might miss one or more positions. I would clean up the Rotary Encoder pins with a hardware switch debouncer as I described in video #96. At least that way you can take out any software coding for bounce.

    • @mwngt12
      @mwngt12 4 ปีที่แล้ว

      @@RalphBacon Thank you soo much for getting back to my inquiry. Truth is, I'm mounting the encoder on the output shaft of a DC motor (perhaps not the most ideal way to read a motor position/RPM though I saw it implemented successfully online, plus the motor is slow enough for the encoder to work.) As my project had become a bit more complex, I eventually decided to abandon the software debounce solution and go to good 'ol hardware, since I'll have several motors to read from, and to eliminate the false positives the Arduino has to filter out from all the encoders, and give it more space to do more important stuff.
      Kindly I have another question that came to mind yesterday regarding declaring and running an ISR from inside a Class. What things should I pay attention to, or new concepts to learn and comprehend, to implement this successfully with little hassle, as perhaps otherwise it might better to leave the ISRs in the main sketch instead. What do you think?
      Once more, very great videos. unlike in other channels, this one has very little video editing effects (music, intros, visuals ...etc) that would somewhat otherwise distract the viewer, and should make them feel comfortable and focused learning new materials. Many thanks again Ralph