#19 How to use a Rotary Encoder with an Interrupt routine on your Arduino

Поделиться
HTML-код
  • Опубликовано: 28 сен 2024
  • A rotary encoder is a useful type of switch but what exactly does it do and how do you implement it?
    And how do you use an Interrupt routine to reliably detect the pulses?
    Here I explain what it's all about and why it's such a useful (and cheap) building block for your Arduino project.
    It is amazingly easy to implement with just a few lines of code and will doubtless be of use in your next Arduino project!
    The final code used in this example can be found here: github.com/Ral...
    (Note this contains more sketches for another Rotary Encoder video - you need the sketch called "RotaryEncoderInterrrupts.ino")
    As always, Thanks For Watching.
    My channel and blog are here:
    ------------------------------------------------------------------
    / ralphbacon
    ralphbacon.blog
    ------------------------------------------------------------------

Комментарии • 370

  • @naboulsikhalid7763
    @naboulsikhalid7763 5 лет назад +2

    long time, I wanted to learn about the Encoder, didn't get the explanation that fit my knowledge in electronics and programming. So, this wonderful video makes much easy to understand and to apply it. I really thank you infinitely.

    • @RalphBacon
      @RalphBacon  5 лет назад

      Glad you liked it Naboulsi, thanks for letting me know, always good to get positive feedback!

  • @RonFinlay1
    @RonFinlay1 7 лет назад +11

    Best videos I've found. Very well done, multi screen, clear, well spoken and very kind of you to share your clearly vast experience.

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Thanks, Ron, glad you liked the video. I'm not so sure about the "vast experience" but kind of you to say so anyway! Thanks for the feedback, nice to hear from you.

  • @JerryEricsson
    @JerryEricsson 6 лет назад +1

    Thanks great explanation on these little gems. I recently had a 4 month nightmare because one of these did not function properly when installed in a mini oscilloscope. I was posting on forums everywhere I saw one of these built, and I guess I solved it myself, when I came upon one of my posts and read exactly what I posted. So to test my theory, I purchased a few of these, and replaced the one in the scope, and suddenly my nightmare was over, despite I had already purchased another model that was a bit larger and a lot more expensive. So now I have a pocket model and a desktop model and that is actually a good thing.

    • @RalphBacon
      @RalphBacon  6 лет назад +1

      Can you have too much of a good thing, Jerry? Not when it comes to electronics and Arduino stuff! As you know I have a "proper" bench scope, but my JYE mini scope (video #92) at 1/20th of the price often does the job, especially at the Arduino level we usually are dealing with. I'm glad you got yours sorted out, and as you say, big model + small model =win-win! Thanks for that anecdote Jerry, glad you liked the explanation of Rotary Encoders, and good to hear from you again.

  • @RalphBacon
    @RalphBacon  8 лет назад +2

    The final code used in this example can be found here: www.dropbox.com/sh/l7bzy5hj46ywa58/AABjo0yydmB5nzeAuK_nPI9da?dl=0
    Any problems with accessing that code (or understanding it) please DO let me know!

    • @sergioisaacpuentesto
      @sergioisaacpuentesto 8 лет назад

      One question please..If I want to make an encoder of 3 bits of resolution, how do I do it?

    • @RalphBacon
      @RalphBacon  8 лет назад

      +Sergio Puentes Torres
      Hi! A 3-bit resolution will give you only 7 positions - are you sure this is what you meant? This rotary encoder gives more resolution than that. Here's a link to how resolution is defined which may help you describe your requirements better:
      bit.ly/2cgLQHQ

    • @sergioisaacpuentesto
      @sergioisaacpuentesto 8 лет назад

      Yes, it is to better understand it. I want it simple, with only 7 positions. Please

    • @sergioisaacpuentesto
      @sergioisaacpuentesto 8 лет назад

      Like this video with photo sensors
      ruclips.net/video/XIUrnR8bLAI/видео.html
      My issue is the code using arduino

    • @RalphBacon
      @RalphBacon  8 лет назад +1

      +Sergio Puentes Torres
      Well, project guidance for your specific needs is best directed at the Arduino Forum: (forum.arduino.cc/index.php). I would suggest you post your question in the Project Guidance section as there are many excellent and knowledgeable people there who can help you. As you might imagine I just can't spare the time to develop specific solutions but thanks so much for your interest, others might also benefit from your query.

  • @TheRainHarvester
    @TheRainHarvester 7 лет назад +1

    Assuming you ARE actually getting contact bounce, it seems like you'd want to move the "lastInterruptTime" down a few lines (outside the if-clause).
    Otherwise, you'd still get contact bounce if the dial was not being moved except for vibrations/optical noise that causes the bounce.
    By moving it outside the if-clause, you remove all contact bounce that occurs within 5ms of the last contact bounce. The way you have it now, only the first bounce starts the timer to disregard an incoming 5ms stream of bounces. If a stream of bounces is 6ms, then you count the last bounce as a pulse.
    This may not matter depending on the optics/velocity of the encoder.
    Great video!

    • @RalphBacon
      @RalphBacon  7 лет назад

      An interesting proposed change to the logic, RainHarvester. Let's see. My logic is thus:
      1. Grab the current time.
      2. Compare time against previously stored time.
      3. Have I been here in the last 5 milliseconds since running the ISR logic? Yes - exit.
      4. Do the rotary value stuff.
      5. Update the stored time with the current time.
      This means that as long as 5ms has elapsed since last run it would indeed run the ISR logic (eg after 6ms). Your change forces the behaviour to change so that at least 5ms has to elapse since last CALLED (not just run). Now I like this but it MAY lead to unintended behaviour, for which I will use my car's radio as an example.
      My car's volume control is also a rotary encoder. If I spin it fast it refuses to acknowledge the pulses and just adjusts the volume slightly (as though only one or two pulses got through). So rapidly adjusting the volume to zero by turning the volume control knob rapidly anti-clockwise doesn't work. You have to turn it in a more gently manner for it to respond. This can be annoying as a user, as I know I've turned the volume control 10 clicks (very rapidly) but the volume has only changed from 20 to 18 in that time. This is the behaviour that may be the result of your logic change. Perhaps 5ms is a good value for your logic to work just fine and my car's design might use 20ms which is much slower (and thus less responsive).
      The long and short of it is that I'm intrigued whether your design would actually work better in Real Life or not. I shall add it to my list of things to investigate when I have a spare nanosecond or two. Thanks very much for posting, it certainly got me thinking long and hard about this, appreciated.

    • @rfresh1011
      @rfresh1011 6 лет назад

      Your suggested fix worked for me. I was getting number skipping when I turned the knob...52,54,56,etc. Per your suggestion, I moved that lastInterruptTime down outside of the loop and now I'm getting exact sequencing of the up and down numbers in the monitor window. I also have added 10k resistors to my pins 3 and 4. BTW I am using a Teensy 3.5 board.

  • @gman9275
    @gman9275 5 лет назад +3

    Hey mate, Great videos! I know this vid was from a while back, but I think I have improved on this code to make the turns 100% accurate and its super simple and easy to understand while still using interrupts. I have coded for the ESP8266 D1 mini (hence the ICACHE_RAM_ATTR in interrupt loop) but it makes for a super accurate way getting the right signal from the rotary encoder. All it takes, is some easy to understand nested while loops! They lock you into the sequence of the encoder and only kick you out of the loop if its an erroneous bounce signal. Let me know what you think.
    ...
    const int PinA = 12;
    const int PinB = 14;
    bool pinBVal;
    bool pinAVal;
    bool turn;
    int REPosition=0;
    void setup() {
    Serial.begin(9600);
    pinMode(PinA, INPUT_PULLUP);
    pinMode(PinB, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(PinA), interruptA, FALLING);
    attachInterrupt(digitalPinToInterrupt(PinB), interruptB, FALLING);
    }
    void loop() {
    delay(1000);
    Serial.print("Time on: ");
    Serial.println(millis()/1000);
    }
    ICACHE_RAM_ATTR void interruptA(){
    turn=0;
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA); //clockwise
    while((pinAVal==LOW)&&(pinBVal==HIGH)&&(turn==0)){ //step1
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    while((pinAVal==LOW)&&(pinBVal==LOW)&&(turn==0)){ //step2
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    while((pinAVal==HIGH)&&(pinBVal==LOW)&&(turn==0)){ //step3
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    if ((pinAVal==HIGH)&&(pinBVal==HIGH)&&(turn==0)){ //step4
    turn=1;
    REPosition=REPosition+1; //adding the position
    Serial.println(REPosition);
    }
    }
    }
    }
    }
    ICACHE_RAM_ATTR void interruptB(){
    turn=0;
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA); //counter-clockwise
    while((pinBVal==LOW)&&(pinAVal==HIGH)&&(turn==0)){ //step5
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    while((pinBVal==LOW)&&(pinAVal==LOW)&&(turn==0)){ //step6
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    while((pinBVal==HIGH)&&(pinAVal==LOW)&&(turn==0)){ //step7
    pinBVal=digitalRead(PinB);
    pinAVal=digitalRead(PinA);
    if ((pinBVal==HIGH)&&(pinAVal==HIGH)&&(turn==0)){ //step8
    turn=1;
    REPosition=REPosition-1; //subtracting the position
    Serial.println(REPosition);
    }
    }
    }
    }
    }

    • @RalphBacon
      @RalphBacon  5 лет назад +2

      That's certainly a unique way of determining rotational direction, Graham. I can't try it right now (I'm editing this week's video) but I'll bookmark it and come back to it later. You say it works until you get a bounce and then kicks you out of the while loop. Then what, start the whole thing again?

    • @gman9275
      @gman9275 5 лет назад +2

      @@RalphBacon sorry, I should have explained that better.
      When you turn the encoder one click, this is how the program handles it...
      It interrupts the program when PinA goes low. If its a bouncing signal from a terminal creating a connection within the encoder it will not enter any while loops as the next condition (pinB low) won't yet be true,and the interrupt will terminate and restart until a solid low is reached. once a stable ground is established inside the encoder the interrupt will wait until the next step is complete in the process. Once pinB goes low, the code latches into the new while loop. If there is bouncing on pinB the code will only revert back to the previous while loop until a solid pinB low is reached. The same latching while loop happens for the next step in the process which is pinA going back to high. If it bounces the program bounces back and forward between 'while' loops until a solid high is reached. As soon as pinB goes high as well (bouncing high or not), the program is complete and the code adds a +1 to the count variable. I know the code looks a bit inelegant in the RUclips comments but it's much nicer in the ide, and it works flawlessly.

  • @idvfpv
    @idvfpv 4 года назад

    I've tried multiple libraries and codes but none were stable! your code works great! and you provide very clear explanations! thank you so much!!

  • @dw1213
    @dw1213 5 лет назад +1

    Hi Ralph, this video was just what I needed - I am building a shed (my shed in sunny Reading) environment controller with one of the MEGA / ESP8266 boards and am using a rotary encode to scroll and select from a menu on a 3.2tft screen. There are various sensors all of which can be viewed/controlled either automatically or via WiFi (anywhere in the world. Not all the mega pins can be used for interrupts and the screen uses a few and so the pin allocations is a bit of a headache but I'll get there. Any way interesting video. Well done.

    • @RalphBacon
      @RalphBacon  5 лет назад

      Very glad you found this useful, DW, once you see how it works it all makes sense, doesn't it?

  • @steveshaw259
    @steveshaw259 7 лет назад +3

    Really nice and clear video, thanks Ralph. I've been wondering what to use my encoder for, you've now given me some ideas. One question i have is why did you attach the interrupt in the LOW rather then FALLING mode, as it would seem from the diagrams that FALLING was the way to do this ? Incidentally I tried it with FALLING, but it gave erratic readings, so clearly LOW is the better choice - would be interested in your thoughts as to why this is. Thanks

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Hey, Steve! I had problems getting FALLING working reliably, possibly because of switch bounce. LOW, however, worked reliably as you found out. And when you look at the square waveform LOW / HIGH is what we are really detecting and comparing against. FALLING and RISING (not that you can do the latter except on a few Arduino boards) is not bringing anything to this party. Great question, nice to hear from you.

  • @bobedge3149
    @bobedge3149 7 лет назад +1

    Great explanation. Must learn more about interrupts on arduino. There is a fantastic library called Rotary. I will try to find the link. works with all encoders, full or half step. Never misses a pulse also.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hello Arduinite! I'm currently on vacation 5,000 miles away from home so I'll have to be brief with these comments until my return, mid-July.
      Glad you like the video, Neville, and interrupts are a good topic to master. I've covered them from time to time during my videos. If you find those links please post here!

  • @joshlong93
    @joshlong93 Год назад +1

    Great and thorough video, by far the most useful interrupt video I've seen yet. Unfortunately/weirdly the code doesn't run on WOKWI which is where I'm currently practicing in anticipation of receiving components. The sketch seems to get caught up when you run attachInterrupt with a mode of LOW. I guess because it's simulating a rotary encoder it isn't sure what the pulse is when first initialised... or some other reason I haven't considered. I look forward to trying this out with actual hardware though. Thanks again.

    • @RalphBacon
      @RalphBacon  Год назад

      Try using FALLING instead of LOW, as the interrupt will continue to trigger if set to LOW, whereas FALLING fires once then stops.

  • @solimaneluahabi7579
    @solimaneluahabi7579 5 лет назад +1

    Hey Ralph I hope you are feeling better after the surgery.
    This is a great video as usual, very clear and well explained.
    I wanted for a while to control the position of DC motor by means of photo/optical switch. having looked at this video seems very similar concept using 90 degrees phase shift. I wonder whether you could share with us your expertise to control a motor using optical switch. your effort and time always appreciated.
    Regards
    Sol

    • @RalphBacon
      @RalphBacon  5 лет назад

      Hi Sol, I did some work using a mechanical switch to control a DC motor (a stepper motor) but you may get some ideas from these videos #38 and #39. Good luck and thanks for your good wishes.

  • @MrAllanwinks
    @MrAllanwinks 7 лет назад +1

    Ralph thank you so much for your efforts with this video, its the best explanation I have found on this subject.
    I hope to apply the knowledge you have shared to an Arduino based mechanised fishing system that I am working on. I need the encoder to set upper and lower fishing levels that the equipment can fish between.
    Thanks again.
    Allan

    • @RalphBacon
      @RalphBacon  7 лет назад

      Thanks for your kind words, Allan and welcome to my channel. If you're building an Arduino-based project then there are certainly other videos here that may interest you too! Thanks for posting, good to hear from you.

  • @SpeccyMan
    @SpeccyMan 7 лет назад +1

    There is a library for rotary encoders but it actually makes more sense to do it this way as you learn a lot more about the functionality of the devices you are attaching to your Arduino. My question is can you expand the interrupt routine to detect more than one rotary encoder as I am working on a project that needs two of them?

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      +Nick B
      And you have understood the purpose of my channel perfectly! Of course there are times when I use libraries as a building block of a bigger project but at least if you have gone through the hows and whys then you be a better developer.
      Regarding your question, NIck, remember the Arduino Uno / Nano has TWO interrupt pins (2,3) (Mega has SIX!) so why not attach each device to its own interrupt pin? That will ensure "separation of concerns" and each interrupt method has a "single responsibility" - easier to code, maintain and understand. Golden rule: an interrupt routine should be lean and mean, no fancy logic and absolutely no Serial.print statements (unless you are debugging, of course). Update a (volatile) variable and get out. Job done.
      Enjoy my channel and other videos, I just wish I had more time to do more!

    • @SpeccyMan
      @SpeccyMan 7 лет назад +1

      Thanks for your response. I was thinking along the pins 2 and 3 line myself. I rarely use Serial.print anyway as most of my Arduino code outputs to a display device of some kind, LCD, OLED etc. I enjoy coding so the challenge of coming up with code to drive other devices isn't really a challenge to me, it is more of a quest for more knowledge and the satisfaction when it works as you intended.

  • @pikor69
    @pikor69 4 года назад +2

    Hi, I know it's been 4 years but I just started :). Thank you for the videos, they are giving me great opportunities to learn something new. Do you know that millis() does not work inside ISR? This is indirectly the reason FALLING gives erratic readings. I believe switches inside the encoder are bouncing and with millis() not working you are getting multiple falling edges as you cannot ignore them.
    I'll keep watching your videos. Regards.

    • @RalphBacon
      @RalphBacon  4 года назад

      Indeed, millis() does not work (the value is never updated) within an ISR but micros() is OK-ish! I think the rotary encoder I used in this video is giving me multiple falling signals (poor quality or dirty contacts) thus it triggers erratically. LOW works because I ignore the same state. One day I will fix this for good! Great to hear from you, Pikor, you now have #190 videos to watch!

  • @kvamsidharvamsi5800
    @kvamsidharvamsi5800 3 года назад

    VERY VERY VERY VERY INTERESTING, GOOD TO SEE THIS AND WHEN I TESTED IT'S PERFECT without skipping steps ,simply 👌👍

    • @RalphBacon
      @RalphBacon  3 года назад +1

      Glad you liked it!

    • @kvamsidharvamsi5800
      @kvamsidharvamsi5800 3 года назад +2

      @@RalphBacon I loved, its very helpful in my project thank you very much 😊

  • @jamescullins2709
    @jamescullins2709 6 лет назад

    Thanks, I got it. I tested it as it is and it worked great, then tailored to my project. Great job Ralph.

    • @RalphBacon
      @RalphBacon  6 лет назад

      Thanks for letting me know, James, it is so annoying when Dropbox changes the location.

    • @jamescullins2709
      @jamescullins2709 6 лет назад +1

      yes, I know what you mean. Change is one thing that never changes .

  • @nietopalaciosluis8328
    @nietopalaciosluis8328 3 года назад +1

    Hello, excellent video, it is the most effective and accurate that I have seen, it works perfect for an encoder, I did it for 6 encoders, but when I moved them, it does not show me any value on the monitor, you know why this is, greetings .

    • @RalphBacon
      @RalphBacon  3 года назад

      Remember that each encoder requires a hardware interrupt pin - the Arduino UNO only has two, pins 2 and 3, could this be the problem?

  • @yepthatisme6201
    @yepthatisme6201 7 лет назад +1

    This is a great piece of code Ralph. Thanks for the instructions and describing the function of it all. I have a question about it in regards to the switch on the encoder. How would we use the switch if we wanted to set a specific input to a stepper motor function? ie; When we hook up 2 different stepper motors to our arduino and want to run a manual set up to perform at set parameters in the loop instead of having to code it each time. Like say we want to set motor A with a start point and an end point then save those setting by clicking in on the switch of the encoder. Then set motor B up with different start and end points with its own encoder(unless there is a way to do it with just one encoder). Afterward when we push a button to run the code it will move each motor to it's individual start and stop points until the user pushes stop.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hi there, er, Yep That Is Me! Stepper Motors are notoriously difficult to "set" unless you have some sort of end-stop as a reference point. This might be a mechanical switch like a microswitch, or a magnetic Hall Effect sensor, just to name a couple. That is why the question you're asking is difficult. The stepper motor has NO IDEA where it is currently positioned (unlike a servo) so "setting" it is just a matter of counting the individual pulses that you send to the motor to (hopefully) move it to the correct place. And then reverse that by sending a number of "reverse" pulses to move it back again. But it still does not know where it is set to. I recommend you read up the differences between servos and stepper motors and you will find lots of information. Good luck!

  • @ottokueng4236
    @ottokueng4236 3 года назад

    Thank for this Program. This works perfect. Other Programs do not because the bouncing makes troubles.

    • @RalphBacon
      @RalphBacon  3 года назад

      Quite so. I might do an update on this soon so keep tuned.

    • @ottokueng4236
      @ottokueng4236 3 года назад

      @@RalphBacon Thanks it works for about 99%. Sometime it loos one step, sometime it doubles the puls.
      Will wait for the update.

  • @faowff034faerf3490ur
    @faowff034faerf3490ur 5 лет назад +2

    Good tutorials and good codes.🐹💕🦀🐙💓
    Especially I was very impressed with the way to avoid bounce.
    I managed to understand how to use the rotary encoder.Thank you so much.🐹💕🦀🐙💓

    • @RalphBacon
      @RalphBacon  5 лет назад +1

      I'm very glad I helped you understand it, thanks for posting.

  • @CrimFerret
    @CrimFerret 4 года назад

    Thanks for the video. I couldn't figure out why you were interrupting on Clock going LOW instead of FALLING since your diagrams didn't make it clear that both pins stay HIGH when the encoder isn't moving. Once I checked (I just hooked it up and checked the pins with an LED), it made sense. No more using potentiometers for me.

    • @RalphBacon
      @RalphBacon  4 года назад

      You're welcome! You can try making it work on FALLING too, but I found it glitchy! Perhaps my rotary encoders are a bit "cheap".

    • @CrimFerret
      @CrimFerret 4 года назад

      @@RalphBacon It makes more sense to do the interrupt on LOW if the pin is high unless the shaft is turned. It's probably not the encoders. The clock speed on the Arduino isn't all that high. Thinking about it, the only time it would make sense to trigger on FALLING or RISING would be if the waveform never hit HIGH or LOW (I don't know the range for LOW or HIGH detection). Sine or triangle waves would probably work better, but there would still be some slop in the timing. That probably wouldn't matter for any application the Arduino was suited for.

  • @kieranj67
    @kieranj67 5 лет назад +1

    Thank You, perfect simple explanation

    • @RalphBacon
      @RalphBacon  5 лет назад

      Glad you liked it, Kieran, thanks for posting.

  • @janhellstrom4165
    @janhellstrom4165 2 года назад +1

    Hi Ralph, Great video as always!
    I'm working with a filament spooler for my 3d-printer and using PWM output for the servo motor. So far it works fine but when I try to use external interrupt, for another task, the servo motor acts strange. It starts moving to wrong positions.
    Is it so that the interrupt affect the PWM function?
    The Arduino I am using is MEGA 2560.
    Regards
    Jan

    • @RalphBacon
      @RalphBacon  2 года назад

      The interrupt will, as the name implies, interrupt anything running, although the actual PWM signal is generated by separate hardware so should not be affected.
      But if you are moving or adjusting the servo signal then that will be affected by an interrupt; keep them very short and simple and do all the processing in the main loop().
      Or use an ESP32 and put essential processing in a separate task (or several tasks) - I did a couple of videos on this.

  • @alanshroue7
    @alanshroue7 4 года назад

    this is a solid video that explains it really well

    • @RalphBacon
      @RalphBacon  4 года назад

      Thanks, Alan, glad you liked it.

  • @cpopte
    @cpopte 7 лет назад +2

    Thankyou. It was the best explanation. The only thing that I am searching now is HOW can I connect a rotary encoder to an arduino. No I don't refer to ebay, chinese or adafruit encoders already mounted on pcb's. I mean encoders bought from tme.eu or digikey, farnell, without any pasive components selected using datasheetd (5v, number of steps, durability, shaft lenghts...etc) because I want variety since I am using them in comercail products. Ok now, WHAT is the use of those passive components on those ebay encoders ? They are there to prevent false readings / skips ? How and why ? Why 2 capacitors are needed ? . Anyway, with your tutorial I am using an encoder Bourns type PEC-11R-4020K-SOO24 and tried also with Alps EC11B20242. Both work fine,
    . Basicaly you can use whaever encoder on the market if you read the datasheet ( voltage, current, pin configuration are important). I need to mention that YOUR VIDEO here finally helped me after one night wasted - to finaly make them work. Thankyou. I "like" its the least I can do, and it's not enough. You even did it without external libraries or aditional code junk that would use my precious Atmega memory. Thanks alot !

    • @RalphBacon
      @RalphBacon  7 лет назад

      Wow, rev3erse, your appreciation of my efforts is, er, appreciated! There's no reason that other rotary encoders would not work. I'm not sure the one I used had any additional components? Any capacitors *might* be for switch debouncing although you can do that in software too. Anyway, I'm very glad it is all working for you, thanks so much for posting, appreciated.

  • @legosteveb
    @legosteveb 7 лет назад +1

    Great video on encoders and it was really educational. I have an Arduino Mega 2560 that I plan on using eight encoders with. I would love to hear your strategy on how to accomplish this. My current strategy is to Mux the 8 A pins and 8 B pins into 2 separate Mux's, using the same 3 address lines for both. Setting the 3 address lines and reading the 2 input lines would happen in a timer interrupt routine. I thought I would use timer zero already running at 1 ms. Instead of looking for transitions I would map the 2 bit Gray code into 2 bit binary and check to see if the number was increasing or decreasing relative to the last read. This would give me the direction. And every time there was a change in value I would either increment or decrement the virtual position. What do you think?

    • @legosteveb
      @legosteveb 7 лет назад

      BTW The use case is knob twiddling on synthesizers. So the encoders are for human hands and most likely only two will be used at any given time.

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Glad you liked the video; but as for your encoder strategy it sounds dodgy! You have *six* interrupt pins available on a MEGA. Paralleling the encoders up like this is not something I would do. How does your interrupt routine know which rotary encoder has triggered the interrupt? Trying to multiplex various encoder signals onto a timer routine... I mean, what could possibly go wrong? (Spoiler alert: lots). If you really think this would work just try it with two onto a single interrupt routine - and let us know if you have got it to work (reliably)!

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Having thought about this overnight (is that sad?) is sounds like you're using Rotary Encoders in the same manner as a keypad matrix with columns/rows. Thus you poll for particular pins (A or B) and determine which Rotary Encoder is being used. Is this the approach you want to take? Unusual but stranger things happen at C. (pun intended).

  • @pashahassan720
    @pashahassan720 4 года назад

    elaborate,helpful & to the point. very nice

    • @RalphBacon
      @RalphBacon  4 года назад

      Thanks, Pasha, glad you enjoyed it!

  • @CalvinBacon
    @CalvinBacon 3 года назад +2

    Hi Ralph, thanks for the great video! I am currently working on a MIDI Controller for my music (I have the parts but am having trouble ACTUALLY building it🤣).
    This is the list of items I want to connect to my Arduino Uno:
    3x Rotary Encoders (with push-switch function)
    3x Linear potentiometers (audio faders)
    1x Ultrasonic Sensor.
    1x OLED Display (showing the selected MIDI channel and value of the potentiometers)
    First off - will I even be able to connect all of these parts to the standard Arduino Uno or will I need something with more pins, i.e. the Arduino mega?
    I got the single rotary encoder to work using your sketch but I am wondering how I would go about connecting the other two and then also including the additional fader potentiometers...
    Would appreciate it if you could point me in the right direction here, as I'm kind of lost at the moment! (This is my first electronics project so I'm still very new to this all as I'm sure you'll know!)
    FYI - this is my inspiration for the project (so you get an idea of what I am actually trying to make):
    nuancescontroller.fr/
    Cheers,
    Calvin

    • @RalphBacon
      @RalphBacon  3 года назад +1

      Hey Calvin, the Arduino only has two interrupts so max two rotary encoder. Arduino Mega had many more plus more general purpose up pins. But for a first project this is ambitious; can you create a (much) simpler proof of concept project that runs on a Uno just so you get some experience of what's required?

  • @KW-ei3pi
    @KW-ei3pi 5 месяцев назад

    Ralph, in this example, you have the encoder CLK pin connected to Arduino pin 3, and the DT pin connected to Arduino pin 4, so am I correct in assuming that ONLY the CLK pin needs an interrupt pin? But with the De-Bounce code in video #226, BOTH the CLK and the DT pins need and interrupt pin. Is that correct? Thanks!

    • @RalphBacon
      @RalphBacon  5 месяцев назад +1

      You need to detect when the Rotary Encoder is moved - so a single pin/interrupt is sufficient.
      In video #226 I believe the logic requires both pins to be detected to determine the correct state (or invalid state).
      These days I tend to use hardware debouncing (I did a video too) as it is 100% reliable and requires no software at all.

    • @KW-ei3pi
      @KW-ei3pi 5 месяцев назад

      @@RalphBacon Thanks Ralph! That clears it up for me. Regards!

  • @i2thewod91
    @i2thewod91 3 года назад

    Nice, found the information here, that i need.

  • @Autotrope
    @Autotrope Год назад

    I'm just wanting to know if these cheap ones are mechanical, or magnetic or optical. I'm guessing mechanical because it would be simpler? How often do the contacts wear out?

    • @RalphBacon
      @RalphBacon  Год назад +1

      Cheap rotary encoders are mechanical. The datasheet (if you can find one, Bourns do have one for their encoders) tell you what the MTBF is. Unless you are going mad with it, it's unlikely to wear out. Optical are, of course, better but cost considerably more.

  • @sanjaysharma05
    @sanjaysharma05 7 лет назад

    Nicely explained Ralph 😊

    • @RalphBacon
      @RalphBacon  7 лет назад

      Glad you enjoyed the video, Sanjay! Plenty more to learn here, which you will need if you intend to start building Arduino projects (as per your stated plan to me). Enjoy and thanks for posting!

  • @mpcostanzo
    @mpcostanzo 4 года назад

    Thank you, very helpful. I'm new to Arduino and I'm building a button box for my Racing Sim in which I use two encoders and one rotary Switch. I have used your code for one encoder but I don't know how to use it for two encoders. Would you be so kind to help me on this?

    • @RalphBacon
      @RalphBacon  4 года назад

      Yes, Maurizio, it's easy enough to do. If you have already built the demo circuit for one Rotary Controller you will have used ONE of the TWO interrupt pins available on the UNO. They are pins D2 and D3. So write an identical attachInterrupt statement but this time specify the other pin (so if you have used D2 this time, use D3 in the new statement, or vice versa) and specify (and write) another ISR for the new interrupt pin. Then everything else is pretty much the same. You will be duplicating some code but for a beginner that's easier than trying to be clever and getting bogged down. Have a go, let me know how you get on.

  • @maartensilvialuca
    @maartensilvialuca 6 лет назад

    Thank you very much! Thanks to you I got it to work

    • @RalphBacon
      @RalphBacon  6 лет назад

      Excellent news, Maarten, thanks for letting me know. Nice to hear from you.

  • @joesmith9330
    @joesmith9330 7 лет назад

    IN NOT SURE BUT I THINK TO GET IT TO WORK ON A SCHEMATIC WITH DIGITAL LOGIC LIKE A 7400 SERIES TYPE LOGIC IT HAVE A PULSE WIDTH LIKE A SAID BELOW BUT I COULD BE COMPLETLY WRONG HERE. LOOKING AT THE PROGRAMMING LIKE IN LISTENING TO AT THIS SECOND UR DESCRIPTION IS PERFECT AND EASILY UNDERSTOOD . THANKS FOR THE VID AGAIN AND IM GOING TO GET A ROTARY ENCODER FOR MY PROJECT.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Yes, do get a rotary encoder and if you have an oscilloscope it would be even better to see the waveforms. As I said below it is the rising edge that determines the direction not the width of the pulse. I'm sure you will find using the actual device will make it all much clearer. Thanks for posting (although we'd all appreciated your posts not being in UPPER CASE as it makes it seem as if you are shouting at me ).

  • @roberteliassen5020
    @roberteliassen5020 7 лет назад

    Excellent video, Ralph. Thanks! You are a source for inspiration.
    There is room for an interesting little C-question in your code, and that made me Google around a bit.
    We all know that changing a variable in an ISR is not as trivial as changing it elsewhere; it needs to be 'volatile', of course. That is to prevent the compiler optimising it away or put it in a register.
    In your isr() you have another variable, lastInterruptTime, that should be treated volatile, but you didn't. Instead you made it static. Perfectly fine of course.
    So, what is the difference between static and volatile? And... Can you use static instead of volatile? Or perhaps do both; "static volatile"? Frankly, I'm not sure. Well, not sure enough to try to make an explanation, that is. ;-)

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hei Robert, hvor er du?
      For others reading this post, let's think about what "volatile" is trying to do. Global variables (declared outside of any function) can be changed by the ISR. But the compiler is unaware of this and can retrieve the value from its registers without actually reading the data from memory again. Moreover, the compiler optimisation may "mistakenly" remove code if it thinks a condition is always true or false because the variable it is checking has not been marked as volatile (programming error, not an optimisation error). By marking it as volatile the compiler (and optimiser) is now aware the variable's value could suddenly (and unexpectedly) change and always retrieve its true value from memory.
      Variables used within *and only within* the ISR itself are safe because the compiler knows that's where they are used! Volatile is not needed as they are not accessed elsewhere.
      As it happens, during the execution of an ISR, millis() is not incremented so that piece of code that tracks the millis() will have the same value at the start of the function as at the end of it. But it seems more logical to update the "lastInterruptTime" at the end of a function to me!
      So declaring a variable used within an ISR as both static and volatile is not required because the scope of that *static* variable is local (only for the ISR in the first place, ie not global) and is not *volatile* as it's not being used globally.
      Tricky subject you've raised here Robert! Probably requires more background reading but in broad terms that is my understanding (and my code works so I guess it is not being optimised away or corrupted).
      Wow! I wonder if anyone else would care to comment on your post?

    • @roberteliassen5020
      @roberteliassen5020 7 лет назад

      Google translate did a terrible job there... You asked where I am. I might as well answer that. :) I'm in the middle part of Norway, north of Trondheim. :) The rather rhetorical English question "how are you?", does not exist in the Norwegian language. Typing in "How are you doing" in Google Translate gives a better translation by the way. Enough linguistic digression... ;-)
      You're absolutely right about volatile and static variables of course. I just felt a bit unconfortable when I saw the variable lastInterruptTime in the ISR and thought "this variable is lost". I didn't notice it was static.
      A static variable "survives" outside the scope, but is not accessable outside the scope. If if were non-static it would have been lost, and the code would behave strange.
      I would have made lastInterruptTime global (and volatile of course), but now I realise it's better (and more elegant) to do it your way.
      Being a C-developer for more than 30 years doesn't mean you've stoped learning. Just ask me! :-)

    • @RalphBacon
      @RalphBacon  7 лет назад

      Robert, hvordan går det? Better? Ha ha! Thank goodness you're fluent in English!
      Regarding your post, I don't think we ever stop learning, whether that's in C++ or in life in general! It's when we *stop* learning that the rot sets in. I'm sure some beginners find the whole concept of scope, static, volatile and so on quite confusing. I try and not gloss over such things in my demos but I will henceforth take *extra* pains to try and explain such esoteric language concepts for the benefit of one and all. Once understood, the general reaction should be "Is that all it is?".

    • @roberteliassen5020
      @roberteliassen5020 7 лет назад

      Better indeed. :) When it comes to computers and development, I think my English is ok. But if you like to discuss knitting, I think I'll pass. "Weft and warp", I have no idea what that means, at least not in a knitting context. :)

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      That's a shame, my next video was going to be about the weft and warp process for knitting. Knit one, purl one. Oh well, I had better stick to Arduino-related videos then :)

  • @xelionizer
    @xelionizer 7 лет назад

    Thanks for posting. However, I'm quite surprised to see that you did not explain the connections from encoder to the Arduino? The tutorial being that elaborate and all? Just a suggestion maid;)

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Well now, noilex, the demo sketch used in the demo also contains the pin connection details: PinA (from the encoder) goes to pin 2, PinB goes to pin 4 and pinSW goes to pin 8. We use Pin 2 because the Arduino has interrupt capability on that pin, so we can reliably detect rotary encoder movement. Hope that helps.

    • @xelionizer
      @xelionizer 7 лет назад +1

      Thank you for clarifying ;)

  • @beicel
    @beicel 7 лет назад

    @Ralph S Bacon Your video helped me a lot! Thanks!

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Glad you like it, beicel, once you have understood how it works it all becomes very simple, does it not?

    • @beicel
      @beicel 7 лет назад

      Yeah, but not that simple! ;) Anyway, I needed to change pin 3 and 4 (revert), but I have the same rotary encoder like you!

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hmm, interesting that you changed the pins but I'm delighted you got it working! "Simple" is a relative term, what I meant was that once the concept is understood then it becomes much easier to actually implement! Great, thanks for the update.

  • @shuaaibrehmman926
    @shuaaibrehmman926 6 лет назад

    Hello Ralph, This video is pretty neat explanation of rotary encoder and your code is efficient and light but I have question regarding your 5ms time check in isr routine. Surely you didn't use delay() function because it doesn't work in ISR vector, however in your code you declared the time variables inside ISR function. This will cause them to initialize with 0 every single time isr is called and you would always end up having interrupttime - lastinterrupttime > 5 condition as true.
    I might not be seeing the point here but if you could explain this 5ms time check for debounce in ISR.
    Cheers

    • @RalphBacon
      @RalphBacon  6 лет назад

      Many Arduinites get tripped up over this bit of code, Shuaaib, so let me see if I can explain it.
      The *lastInterruptTime* variable has been declared as *static* which means it is a sort of global variable but _only_ to this function. It doesn't get reset every time. The initialisation occurs just once, the first time.
      Would it work if this variable were a _true_ global variable? Yes. Is that the _right way_ to do it? No.
      But hey, life's short. Whatever works for you, works, right? I'm just writing the code to demonstrate Best Practice! I hope this helps your understanding of this code, thanks for posting that question.

    • @shuaaibrehmman926
      @shuaaibrehmman926 6 лет назад

      Oh, Yes you are right. Totally tripped on that one. Didn't realize, variable was declared static. Normally in embedded systems people are looking for volatile keyword for variables that are used inside ISR. :)
      Thanks for clarification.
      Cheers

    • @RalphBacon
      @RalphBacon  6 лет назад

      You are most welcome Shuaaib, I'm glad it clarified things for you. Nice to hear from you.

  • @RonFinlay1
    @RonFinlay1 7 лет назад

    hi Ralph Got it working, sort of. I isolated an unrelated push button to update my OLED counter. Works great. Uncomment the encoder ISR, and it works. but the pushbutton doesn't update at all, or takes forever !!! Screen updates very slowly. Seems I may not be exiting the loop. So where should the ISR code code related for initialization, setup() and loop() sections? Thanks.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Ron, you said previously the switch button is pulled HIGH (to Vcc) when pressed? If so (you must be sure!) you need to change the sketch as I'm assuming the opposite in my sketch, line 56. That switch pin needs to be tied to ground via a 10K resistor and the code line changed to a simple INPUT (not INPUT_PULLUP). Then lines 71 to 73 need amending to look for a HIGH value on that pin, so line 71 and 73 need the "NOT" (exclamation mark) removing because you are looking for a HIGH and not a NOT HIGH (confusing sentence if ever I read one).
      Regarding "positioning" of routines, it makes no difference. The compiler will find them wherever they are declared. From a Best Practices point of view, all routines (those written by you) should come first, then SETUP then LOOP. But I think you need to get the sketch working first! Have a go with the above and *let me know* (hit REPLY to this message).
      If you can post your modified sketch to a central cloud storage place (Dropbox, Google, Amazon etc) where I can get hold of it I can see whether what you have done. But please don't post it here! If you have nowhere suitable I'll send you a folder link where you can copy it into.

  • @sledgehammer7998
    @sledgehammer7998 5 лет назад

    Hi Ralph, awesome video. Do you have anything with a rotary and a 7 segment display?

    • @RalphBacon
      @RalphBacon  5 лет назад

      Not together, but there are plenty of videos on this channel that cover both topics. I'll leave you to browse!

  • @christerjohansson2863
    @christerjohansson2863 7 лет назад

    Hi Ralph and thanks for the video. I am not that skilled in C but I am trying... How come that the varible that is static in the interrupt routine doesn't lose its value when the subrutine ends?

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Hello Christer, good to hear from you. The whole point of a *static variable* is that although it is declared within a function (subroutine) the compiler pulls it out so that its scope is not constrained to that function's scope - it survives even when the function ends, in much the same way that a global variable survives, except that it can *only* be used by the function that declared it. I think it's better than a global variable as its scope is still constrained (you can't amend or read its value anywhere except in the function it was declared in) but other viewers (no names mentioned but Robert might read this) think that global variables are easier to use - which might be true but are also easier to abuse and introduce bugs! Is this clear? If not, reply to this message and I'll have another go!

    • @christerjohansson2863
      @christerjohansson2863 7 лет назад +1

      Thanks Ralph, crystal clear! I think I need to pull out my old C/C++ books from the dusty shelf ;-) Thanks again!

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      How did I get your name wrong in my reply! Doh! I've changed it now, Christer, and I'm glad my response was clear enough. Keep coding, your C++ will only improve.

  • @danielclever5626
    @danielclever5626 6 лет назад

    Hi, excellent video. I am looking forward to using a rotary encoder to build a volume control knob. My question is, what happens when the power is turned off or cut off for some reason? How do i store the last value from the rotary encoder form the Arduino board in order to maintain the last value of the knob? Should i use a SD card?
    Thank you in advance.
    I apologize for my english, not my native language.

    • @RalphBacon
      @RalphBacon  6 лет назад

      No need for an SD card here, Daniel. Just use the Arduino's built-in EEPROM. Very easy to do, see videos #26 & #27 to see an example (stores a light level) and video #65 on how to use the EEPROM, *very* easy. Any good?

    • @danielclever5626
      @danielclever5626 6 лет назад +1

      Hi Ralph, thank you very much for such a quick reply. I will look into the videos you have mentioned. Thanks again for the great help and great tutorials!

  • @techisgod
    @techisgod 6 лет назад

    My homemade Six Digit, 20MHz, CD74HC192 Up-Down counter circuit counts Quadrature Encoder pulses at 20Mhz speeds. And seems to be many times faster than using my PIC16F887 microcontrollers.
    Can you tell me why?

    • @RalphBacon
      @RalphBacon  6 лет назад

      I suspect it is because your CD74HC192 is a hardware-based solution and your PIC controller relies on software. Hardware implemented solutions will always trump software, even when the software is written very well (no delays, for example). Of course, a very fast µcontroller could match a hardware implementation but that's just compensating for the slower execution.
      So that's my take on this question, good one that it is, Techis God, thanks for posting.

  • @jerryohhh
    @jerryohhh 3 года назад

    i have encoder non stoppers my only concern is how to convert into input mapping for gaming.?
    encoder used 600ppr
    board used Arduino Leonardo

    • @RalphBacon
      @RalphBacon  3 года назад

      In principle it works the same way, although I found non-stepped/non-indented more difficult to work with.
      You still compute which way the rotary encoder is being turned, and how quickly and then have to decide what to do with that information for mapping or gaming.
      As you are using a Leonardo you could build a virtual keyboard and use the rotary encoder to either issue "Left Key" or "Right Key" signals depending on which way you were rotating the spindle.

    • @jerryohhh
      @jerryohhh 3 года назад +1

      @@RalphBacon here my short video. the only problems ks Rotary Encoder while i spin disc is to hard to select song or using as dj scratch
      ruclips.net/video/fT3u12VrX4Y/видео.html

    • @RalphBacon
      @RalphBacon  3 года назад +1

      That looks like you might be overloading the processor with interrupts.

    • @jerryohhh
      @jerryohhh 3 года назад

      @@RalphBacon hmmm.. 🤔
      what else can be done that way.?

  • @RonFinlay1
    @RonFinlay1 7 лет назад

    Hi Ralph. Tried your code. Not working. I only get ST and later ART as in START. Same delay with RE... SET
    I get the LED to come on sold when I push the encoder switch. Turning it does nothing to the LED and only periodic updates to the screen as to the value. You made it look easy. Any ideas?

    • @RalphBacon
      @RalphBacon  7 лет назад

      Mmm, tricky to diagnose at a distance Ron, but let's have a go.
      Firstly I can't work out what you mean by the sentence " I only get ST and later ART as in START. Same delay with RE... SET", can you explain that please?
      Secondly, if the LED comes on but does not fade (you have to turn it counter-clockwise quite a few times to get it fade all the way down) then I suspect that your A/B wiring is not correct. Recheck that. You can verify whether the rotary encoder is doing anything at all by monitoring the output on the Serial Monitor - it will print "Up" or "Down" with a value depending on which way you are turning the knob.
      Finally, ensure you using the EXACT sketch (no modifications or pin changes or anything) that I supplied otherwise we could be talking at cross purposes!

  • @najeharashid9391
    @najeharashid9391 6 лет назад

    Hello Sir, How to operate multiple servo motors using interrupts simultaneously with servo.h library?

    • @RalphBacon
      @RalphBacon  6 лет назад

      You only have two interrupt pins on the Uno and related boards, Najeha, so that's how many servos you will be limited to if you are using interrupts to control them. Is this really what you asked?

  • @kierandetheridge4177
    @kierandetheridge4177 6 лет назад

    Hi, I'm trying to make a rotary encoder work to increment a seven segment display. I have the display part working fine, but every way that I have tried to program the rotary encoder, with or without interrupts, the counter goes from max to min as soon as the encoder is moved. Any help? Thanks.

    • @kierandetheridge4177
      @kierandetheridge4177 6 лет назад

      Never mind, I just had to us the pullup resistors for both outputs A and B of the encoder.
      I'll leave this here in case anyone else has the same problem.
      Great video. :)

    • @RalphBacon
      @RalphBacon  6 лет назад

      If you define the input pins as INPUT_PULLUP you should not need actual pull up resistors. Check the code to verify this and try it out!

    • @kierandetheridge4177
      @kierandetheridge4177 6 лет назад +1

      ​@@RalphBacon That works too. Thanks!

  • @edwardclarke1608
    @edwardclarke1608 8 лет назад

    Hi Ralph, having issues with the serial monitor, lots of random ASCII character garbage is being spat out when turning encoder... any ideas? Great tutorial too, thanks!

    • @RalphBacon
      @RalphBacon  8 лет назад

      +Edward Clarke
      Welcome to my channel!
      I suspect that your baud rate is not correct. Check that the Serial WIndow (bottom right hand corner) is set to the same value (eg 9600) as what is in the Serial.begin(9600) statement.
      You can test this just by sending a standard "Hello World" statement and ensuring that is received correct to begin with.
      Finally, close and re-open the Arduino IDE as sometimes it gets confused.

    • @edwardclarke1608
      @edwardclarke1608 8 лет назад

      I've tried all that with no luck :( thanks anyway!

    • @RalphBacon
      @RalphBacon  8 лет назад

      Hmm, sorry to hear it's still not working. You are not using digital pins 0 and/or 1 (D0 / D1) on the Arduino board are you, as they are used for the serial communication - if you use those pins for something else then garbage may appear on the serial monitor (or your uploads will fail!).
      Does the standard "Hello World" appear correctly on the serial monitor? And garbage characters appear only when you turn the encoder?

    • @edwardclarke1608
      @edwardclarke1608 8 лет назад

      Actually just fixed it, no idea how... yes I was using the digital pins correctly.
      I did also try to use a sketch just with some print commands in a loop but that wasn't working at all. Either way, it's all good now.
      Am quite new to this as you can probably tell!
      Thanks for all your help, really appreciated :)

    • @RalphBacon
      @RalphBacon  8 лет назад

      Great to hear it's now working! Enjoy the video(s) and keep learning as you go!

  • @3dprintwiz378
    @3dprintwiz378 7 лет назад

    Nice instructional vid. Just a question though, so if I am planning to control 8 motors separately and have rotary encoders to report its position, do I need 8 interrupt pins for it, can I use any pins in arduino to use as interrupt? Thanks in advance.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hey 3D Printwiz! I wish I had a 3D printer, quite frankly.
      Anyway, with regards to your question the short answer is "No", you cannot use just any old pin for an interrupt. On the Uno/Nano only pins 2 and 3 can be used as "external" interrupts (like you get from a rotary encoder). On the Arduino MEGA you have more: pin 2 (interrupt 0), 3 (interrupt 1), 18 (interrupt 5), 19 (interrupt 4), 20 (interrupt 3), and 21 (interrupt 2). If you need several interrupts a MEGA can cost very little when cloned from the Far East (I bought mine for less than $10).
      Additional reading: you might want to read up on the difference between "pin change interrupts" and "external interrupts" as we've been dealing with the latter but the former *may* be of use to you!
      Thanks for posting this interesting question, I'm sure others will think it useful too.

    • @3dprintwiz378
      @3dprintwiz378 7 лет назад +1

      Thank you so much for your answer, it helps a lot since I am building a desktop robot with a precision of an industrial one, hehe, it feels impossible as I go through the process. As for 3d Printers, I have a Flashforge, but there are a lot of 3d Printers now that are twice as large, and as better, plus cheaper. Get one I, believe me it is worth it.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Getting one is the easy bit. Paying for it is the first challenge. Secondly where do I put it? I have zero space left in my workshop. Build another workshop! Could be an expensive 3D printer! I'd also like a 50W laser cutter so I could cut acrylic for project boxes and the like. Another dream. ;)

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Robot Arm looks great just don't let it be seen in Germany (I Am Arm means I Am Poor there). And that soundtrack reminded me of a couple of 1990s raves that were better forgotten. But it's an interesting, working construction and I wish I had a man cave (well, my workshop aka shoe cupboard is my man cave) but all space has been used up. Sigh. One day, one day...

    • @roberteliassen5020
      @roberteliassen5020 7 лет назад

      Hi Ralph. A few words from the nit-picking Norwegian here. :)
      The ATMega328P can indeed do interrupts on almost all its pins. The datasheet says: "The External Interrupts are triggered by the INT pins or any of the PCINT pins". If we take a look at the pinout we see that all of the Arduinos pins (0-13 and the analog pins as well) has a PCINTx label.
      That's the theory... I'm not sure if you can use the Arduino IDE though.
      Edit: And you said that in your comment of course... I wasn't paying attention. :)

  • @manoftheday1
    @manoftheday1 8 лет назад

    Thanks for this greet videos. please and please can you do a video on how to create LCD menu on common 1602 LCD thank you.

    • @RalphBacon
      @RalphBacon  8 лет назад

      +manoftheday1
      I'm intrigued as what you mean by 'menu' - and has it got anything to do with the Rotary Encoder? Explain further as I'm always after ideas for videos that could help beginners.

  • @radhakrishnak5687
    @radhakrishnak5687 8 лет назад +1

    Hi sir,
    How do we write the code to calculate the rpm of a wheel connected to the encoder?

    • @RalphBacon
      @RalphBacon  8 лет назад +1

      +Radha Krishna Korlam
      Hello! Firstly thanks for posting that question. I'm sure others have wondered the same. I'm not sure that a rotary encoder of this design is really suitable for attaching to a wheel (ideally you want an optical sensor) but let's proceed as though it were OK.
      You simple need to count the pulses received (via the interrupt) during a 1 /10 /60 second interval (depends on how fast the wheel is going round). You can accurately detect the time interval by comparing the current millis() value with the previously stored millis() value from the last loop. When the time exceeds your interval (1 /10 /60 or whatever timeframe you have chosen) then you can calculate (extrapolate) the rpm.
      Personally I would not use a rotary encoder. I would use a Hall Effect transistor to count pulses from a small magnet attached (very securely!) to a wheel. I have such a video already in an advanced state of preparation but not yet published, but it won't be too long. I'll use this as an example of how a Hall Effect device can be used, so thanks for the suggestion and good luck with your project (or home) work!

    • @radhakrishnak5687
      @radhakrishnak5687 8 лет назад +1

      Ralph S Bacon
      Thank you so much for your help sir. I am sure you are one of the best youtubers. And your content too is very helpful too.
      If I have any doubts with arduino based projects, may I contact you via mail or something else?

    • @RalphBacon
      @RalphBacon  8 лет назад

      +Radha Krishna Korlam
      Thanks so much for your supporting comments. As regards help with your projects I can recommend the Arduino forum (forum.arduino.cc/) where there are many, many experts just waiting to help. You may even spot me lurking in a corner there too! This is definitely the best approach as I just don't have the time to give specific, bespoke help which I'm sure you understand.That way, I can develop more videos whilst the experts at the forum help newcomers with their projects.

    • @radhakrishnak5687
      @radhakrishnak5687 8 лет назад +2

      Ralph S Bacon
      Yup sir, I understand. Thank you. :-)

  • @НиколаИлић-у2я
    @НиколаИлић-у2я 3 года назад

    Great video!

  • @RaadYacu
    @RaadYacu 7 лет назад

    Nice little gadget. I'll have to try it. But is it so hard to be counter clockwise ? Really ? Kidding aside - really enjoyed it.

    • @RalphBacon
      @RalphBacon  7 лет назад +1

      Hey Raad, yes try it! Once you have one of these and just 'do it' your understanding will be permanent. It's not magic or fairy dust, just simple physics. Clever physics, I wish I had invented the concept. :)
      I didn't know if the term anti-clockwise was used in the US so I also used 'counterclockwise', even though that's something that no UK resident (including me) would ever say. I remember when singer Joss Stone returned to the UK after a long stint in the US and started speaking in an (allegedly affected) US accent she was panned by the press. Shock! Horror!
      So, if I ever do a video on replacing the taps on my basin I will refuse to call them 'faucets' (huh? wassat?) heh, heh!
      Thanks for posting Raad, glad you like the video, it was great to hear from you.

  • @sury5710
    @sury5710 6 лет назад

    Sir, actually I want to connect a servo motor with it
    So,I wanted to know the exact connections of the servo motor,encoder and Arduino Uno board
    Can you please help me out?

    • @RalphBacon
      @RalphBacon  6 лет назад +1

      You must learn to walk before you start to run, Suryansh! Do the Rotary Encoder project. Then you will know how they work and what they really do. Then connect up a servo and play with that (unfortunately I don't have a video for that but you're bound to find a good example somewhere, perhaps on the Arduino site). By that time I suspect you will figure out how to connect the two together. As they say, you can teach experience - that's something you must acquire all by yourself. It's a fairly simple requirement you have so should be straightforward to do - good luck.

  • @PlaceholderforBjorn
    @PlaceholderforBjorn 7 лет назад

    Hi!
    First of I want to thank you for this video. Helped me a lot with the code for my project. But I have not had the possibility to test it because:
    When I try to compile it I get an error "'digitalPinToInterrupt' was not declared in this scope".
    I try to compile your code aswell but get the same error.
    I'm a n00b at programming and does not know where to look first for a solution.
    I have IDE 1.8.5 and the forum post I have found suggests a newer IDE (because of a updated arduino.h).
    Sincerely

    • @PlaceholderforBjorn
      @PlaceholderforBjorn 7 лет назад

      Ok. I have now realised that it has to do with the board I want to use. I have to manually fix so it can use the interrupts... I will have to dig a bit deeper before I can give a better answer. Btw the board I want to use is a Digispark ATTiny 85.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hi Björn and thanks for the support! I'm not even sure the ATTiny85 has hardware interrupt pins the same way as the Uno but you can program it for pin change interrupts. Here's a Stack Exchange article I found that may help you: arduino.stackexchange.com/questions/3929/attiny85-interrupt-id-vs-pin-when-programming-with-arduino but read the comment (correction) by guru Nick Gammon below the answer. And note that the interrupt is triggered on both rising and falling edges.

    • @PlaceholderforBjorn
      @PlaceholderforBjorn 6 лет назад

      I have now giving up the idea of using a ATTiny 85. And I have now tried to make it for the UNO. But step into problems again... The
      attachInterrupt(digitalPinToInterrupt(PinA, isr, LOW);
      line gives me a error:
      macro "digitalPinToInterrupt" passed 3 arguments, but takes just 1
      And I'm not sure where to find a answer for my problem. Tried google and gives me only results on C++ problems with the macro Min and Max. I'm a real n00b att programming and would just love some pointers that direct me where to look for a solution...
      I will read up on the link you gave me in later time, when I have understood this code first so I can convert it to a ATTiny 85.
      Sincerely
      EDIT: Now I found the problem after even more googleing... It was the format of the line...
      Missed a ) after PinA... Feels dumb now...

    • @RalphBacon
      @RalphBacon  6 лет назад

      Never feel dumb about making mistakes. It's actually the best way to learn. When you have to write that line again you will remember the syntax (or at least check your brackets!). On that basis I learn a huge amount every day!!! You can guess how many mistakes I make! Anyway, I think you'll find it much easier using an UNO first, at least, before moving over to the Tiny85. Thanks for the update.

    • @PlaceholderforBjorn
      @PlaceholderforBjorn 6 лет назад

      I wanted to say that I have managed to get the code working on a UNO now. Works great! But needed some time to figure out how to turn it ON and OFF with the switch.
      I must thank you again for a very good explaining video. Think I could not managed if it was not for you video.
      Sincerely

  • @paulroyan8430
    @paulroyan8430 5 лет назад

    Can we count from 0.1decimal places

    • @RalphBacon
      @RalphBacon  5 лет назад

      I'm not completely sure what you mean, Paul, can you just explain a bit further, please?

  • @crash_often
    @crash_often 8 лет назад +1

    thanks!

    • @RalphBacon
      @RalphBacon  8 лет назад

      You're most welcome, I'm glad you found it interesting and/or useful. Plenty more projects in the pipeline...

  • @omaoda4462
    @omaoda4462 6 лет назад

    as said in a coment: use "falling" instead of "low"for the interrut

    • @RalphBacon
      @RalphBacon  6 лет назад +1

      What's your reasoning behind that Oma? Have you tried it? Does it work better than "LOW"?

    • @omaoda4462
      @omaoda4462 6 лет назад

      Ralph S BaconHello Ralph, rising or falling or change just detect the edges and fires only once the interrup. This is what I used for buttons and rotary switches. Where low or high will fire the interrupt as long as the level is detected. It still might work well with some encoder but did not wored out for me. After my last comment I saw your newer video an the newer codes. Anyways thank you for your great videos and well feedback. Cheers
      PS: would love to see something by you about Can Bus e.g. mcp2515 or low power usage (idel, sleep, reduce clock) or running code non-blocking (no delay), using SD card for storring data ...all one need for a stand alone battery powerd data logger :) ...just some hints

    • @RalphBacon
      @RalphBacon  6 лет назад

      Thanks for the suggestions, Oma, I'll certainly see which ones I can add to my list of future videos.
      Regarding the ISR being triggered on "LOW" for as long as the low level is detected, this is not true! What I expect you experienced was switch bounce (the switch literally bounced for a few milliseconds from LOW to HIGH and back again) and triggered the ISR multiple times. This has been a topic of some recent videos - if you haven't already watched it, see video #98 for exactly how switch bounce can cause problems in your code. Thanks for responding, Oma, and keep tuned!

  • @joesmith9330
    @joesmith9330 7 лет назад

    NICE VID

    • @RalphBacon
      @RalphBacon  7 лет назад

      Really glad you liked it Joe.

  • @bobedge3149
    @bobedge3149 7 лет назад

    github.com/brianlow/Rotary The link to the rotary library.

    • @RalphBacon
      @RalphBacon  7 лет назад

      A nice way of abstracting a rotary encoder's workings, Neville. That said, I think an understanding of how a Rotary Encoder works is always useful and it's not *that* complicated to understand and even write your own code (as my demo shows). But sometimes people just want to 'get on' and this library fits that bill perfectly. Thanks for posting.

    • @bobedge3149
      @bobedge3149 7 лет назад +1

      I agree totally. Your video taught me a thing or two, and I'm a professional electronic engineer.

  • @RonFinlay1
    @RonFinlay1 7 лет назад

    OK, its the encoder. It's from Creatron Inc in Toronto. They have an EC11 on a PCB with 5 pins. Seemed great, but there's a IC chip on the back. No idea and not in their poor documentation. Cost me $8.25 and four days of code searching !!!! and it won't work with the switch pin connected. I can't recommend this supplier, so your viewers should be forewarned. So sad. Could have paid half the price for a raw encoder and avoided all this.
    Pins are VCC, L, R, Z, And. So L is your A, R is your B, VCC connects to Z when switch is depressed. No idea what the IC does (8 pins, "472" on it).
    The switch applies 5V to Pin Z when pressed. I'm afraid to connect this Z to pin the arduino "switch pin". I'd be applying 5 V to the arduino. Do I need a resistor to limit current? What value?
    How would you change your code? My LED is going dim, off at "0" then full bright, then all of a sudden bright with repeated "down" turns. Labelled differently. Totally works. I wish all parts had the same labeling as to AB, or 1,2 or LR.... really. Great code, thanks. Off to the races now except for the switch.

    • @RalphBacon
      @RalphBacon  7 лет назад

      Hi Ron, I've looked at the (bilingual) datasheet for this device and it looks like a standard rotary switch with the exception that it has limiting 10K resistors built in. But it apparently has Terminals A, B, and C(gnd). There's no mention of the push switch on the data sheet so if it has one you will have to use a multimeter to determine which two pins are used for that. It also has some 0.01µF capacitors on the outputs A & B to help deal with switch bounce. They may be marked 103 on the board. No idea about anything marked 472 although it could be a capacitor 0.0047µF but it's not on the datasheet. You must also connect the VCC to +5v.
      Actually, I see from your post that you have indeed already correctly identified the pins for A (left), B (right) and Z (gnd) and the push switch Z which goes HIGH when pushed. Even spookier, in part 5-1 of the datasheet they have that waveform drawing I used in my video!
      Finally, in part 5-3 (Switching Characteristics) it seems to indicate that the A and B voltages are HIGH when OFF and LOW when ON. Best check that against my demo to ensure this is the right way round for the demo sketch. I assume that the interrupt will be triggered when the rotary switch PIN A goes low (to gnd) but here it may be the other way around (that is, it goes HIGH). Tricky for me to test but you can by changing this line:
      // Attach the routine to service the interrupts
      attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);
      so that is is looking for a HIGH value (not a LOW) one. Have a go, and let me (and everyone else fascinated by your (rather expensive) Rotary Encoder issues) know!

  • @swarajpalsingh
    @swarajpalsingh 8 лет назад +1

    how to use rotary encoder without ardiuno

    • @RalphBacon
      @RalphBacon  8 лет назад

      +swaraj pal singh
      Why would you want to? A Nano can be had for a couple of pounds (or dollars) when sourced from the Far East (or here in the UK) and effectively provides 'black box' functionality for a rotary encoder. Now, yes, you COULD design some discrete component circuitry to replace the Arduino but I have not done this and certainly would not waste time trying to do so when you can achieve it all with a Nano! So can't help you there I'm afraid but I *would* be interested in knowing why you asked the question?

  • @beicel
    @beicel 6 лет назад

    Dear @Ralph S Bacon can you please do the same on ESP8266 platform too?!

    • @RalphBacon
      @RalphBacon  6 лет назад

      This will work exactly the same way on an ESP8266 as it does on the Arduino, beicel. Just make sure that Pin A is connected to an interrupt pin on that device. Luckily, interrupts may be attached to any of the GPIOs of the ESP8266, except for the GPIO16.

    • @beicel
      @beicel 6 лет назад

      Dear Ralph, did you tried it? Because I was, and it's not working on ESP8266 (hooked up correctly), can you please elaborate your sketch/code again?!

    • @RalphBacon
      @RalphBacon  6 лет назад

      I've certainly tried it in the past but have no demo for it. But this page walks you through it, step-by-step:
      techtutorialsx.com/2016/12/11/esp8266-external-interrupts/
      I suggest you try the example there with just a simple momentary push button switch to prove it all works before connecting the Rotary Encoder. I hope this helps.

    • @beicel
      @beicel 6 лет назад

      I triead almost all of them and they are not working (duplicate or skipping results), but your example can't work on ESP platform because there is no LOW in attachInterrupt() on it, it's not supported.

    • @RalphBacon
      @RalphBacon  6 лет назад

      In that case use FALLING, which I found worked on the Arduino but not as well as LOW. If you use a switch (as I suggested above) you should be able to prove it works fine. If it skips or duplicates pulses then you have a switch bounce problem which I deal with in my example but you may need to extend the delay from 5mS to 10mS (for example) in the ISR.

  • @youpattube1
    @youpattube1 3 года назад

    Very confusing. Not explained very well.
    To begin with, you go on about it goes high then low. But your turning the switch while explaining seems to contradict yourself. If you just turn 1 click cw, does the pulse go high, then low again ? Or do you have to turn it to the next click to have it go low ?
    Secondly, your visual aid is confusing. Is it supposed to be voltage level plotted against time?
    That works for cw pulses, but how can you plot voltage against time going to the left ?

    • @RalphBacon
      @RalphBacon  3 года назад +2

      Oh dear. It was not meant to be confusing. With a Rotary Encoder, one "click" or indent of the device means coming back to the starting voltage levels; that is, _initially_ pin A will be HIGH and pin B will be LOW (your device might be the other way round).
      When you rotate the knob CW that one "click", pin A will go LOW for short time and pin B will go HIGH for a short time during that tiny rotation. Then they return to where they started from.
      Yes, the graph is voltage against time (I think you knew that) and for anti-clockwise rotation just read the graph going the other way. I think this is pretty clear from my video. Still not make sense?

  • @sudesh.s5240
    @sudesh.s5240 Год назад

    Hi gramps are you still alive

    • @RalphBacon
      @RalphBacon  Год назад

      Nope. This is my Arduinite spirit talking right now 👻

    • @sudesh.s5240
      @sudesh.s5240 Год назад

      @@RalphBacon at least gramps I talk your arduinite to scary ,but its like fun

    • @sudesh.s5240
      @sudesh.s5240 Год назад

      @@RalphBacon gramps can I ask question bldc motor can adjustable speed control and weight control for agv

  • @zhuk462
    @zhuk462 4 года назад

    You have to use both interrupts to make it work properly. In real life it works not as perfectly as in this video.

    • @RalphBacon
      @RalphBacon  4 года назад

      Absolutely not, shekaus! All the interrupt should be doing is checking for pin A. Once triggered you should just READ the value of pin B to determine the direction of rotation. Thousands of makers use this every day with a single interrupt, so why not download my sketch and try it my way?

    • @zhuk462
      @zhuk462 4 года назад

      ​@@RalphBacon I tried your sketch, actually. And I see strange behavior in half-step: Serial output stops till the next full step. I looked very carefully into your sketch and couldn't explain this.
      That why chosen another script which works fine.
      github.com/RalphBacon/RotaryEncoderUpdate/blob/master/RotaryEncoderInterrrupts.ino

    • @zhuk462
      @zhuk462 4 года назад

      I found the reason. You should change the logic to CHANGE event. using LOW leads to this problem.

    • @RalphBacon
      @RalphBacon  4 года назад

      Or FALLING as that is really what we are checking for on Pin A. Glad you found the issue for you. I suspect it was the half-step Rotary Encoder, mine was full step. I did another video on quarter-step RE it was *video #96* (the original was this video #19).

  • @joesmith9330
    @joesmith9330 7 лет назад

    I THINK THERE IS SOMTHING MISSING ON THAT DIAGRAM

    • @RalphBacon
      @RalphBacon  7 лет назад

      Ooh, a quiz, Joe, I like them! Would it be a cat? Benny didn't make an appearance on this video. Perhaps a title is missing? A copyright message (not that anyone needs to copy that diagram)? No I give up, I'll have to have a clue. What's missing?

  • @loucostello3111
    @loucostello3111 6 лет назад

    "Easy peasy".

    • @RalphBacon
      @RalphBacon  6 лет назад

      Thanks for your post, Lou Costello, good to hear from you.

  • @arduinomaquinas
    @arduinomaquinas Год назад +1

    Hi teacher, thank for explanation, 👏👏👏👏👏👏 @arduinomaquinas subscribed, your vídeo is very better 🇧🇷😉👍 great !

    • @RalphBacon
      @RalphBacon  Год назад +1

      Glad you like it. Saludos!

  • @oncledan282
    @oncledan282 4 года назад +2

    Good day, Ralph.
    GREAT video and mostly, excellent explanation on just how this rotary encoder works.
    This is exactly what I was needing to set the temperature on my brother in law's future med cooler. I'll write in private for more details.
    Meanwhile, have a great day and take care. God bless !!

    • @RalphBacon
      @RalphBacon  4 года назад

      Oh dear. "Mostly excellent". Damned by faint praise. A case of the curate's egg, I feel. "Good in parts". I await your email with some nervousness, Daniel!

  • @JerryEricsson
    @JerryEricsson 4 года назад +2

    Nice, I always enjoy these classes. I always thought that if a man learns one new thing per day, it will keep his brain active and perhaps, slow the aging process. So thanks for the added time for me on earth, and I assure you I do use most of what you teach in one way or another. Now that money is short, travel is restricted and it takes MONTHS to receive anything from China now, I must work with what I have. Thankfully I have stocked up over the years by using the policy, if I need one item, I order 5. When you get your crap from China it is useful since a lot of it arrives dead or dying. Again, thank you for the wonderful videos it is almost like a visit from a good friend and now that we are locked down in our homes, thanks to our friends in China, such visits are always so very welcome.

    • @RalphBacon
      @RalphBacon  4 года назад

      Yes, agreed, it is taking forever to get stuff from China now. And no free shipping (to the UK at least). I always buy "a few" of the components, at that price it is worth having backups.

  • @JustPlainRob
    @JustPlainRob 4 года назад +2

    THANK YOU! I was having so much trouble with the Encoder library causing bad reads and trying to convert an 'absolute count' into just direction (all I needed was forward and back). This simple explanation of how to use interrupts to do this allowed me to build a bulletproof direction-only encoder read with less than 20 lines of code.

    • @RalphBacon
      @RalphBacon  4 года назад

      Glad I could help you, Rob, and thanks for posting here, nice to hear from you.

  • @9brian99
    @9brian99 4 года назад +1

    Thanks for a great video. I wanted to learn how a rotary encoder worked, watched some other videos but they didn’t really explain what was going on and how the code actually worked. Great stuff as I think having watched yours I’ve got a handle on it now. It’s a bit of a change from writing ABAP4 for big SAP systems but very interesting to get down in the weeds.
    Malcolm

    • @RalphBacon
      @RalphBacon  4 года назад

      Challenges are what makes the success even sweeter, Malcolm! Try a simple sketch to prove you understand Rotary Encoders eg light an LED on the left or right depending on which way you turn the RE. Or, have a strip of Neopixels and wind them up and down using the RE, now that is a challenge (and no peeking at a video that I did to show this). Good luck. Hang on, did you say SAP? Spawn of the devil, you mean. No offense. I'm more of a dot Net person.

    • @9brian99
      @9brian99 4 года назад

      That’s exactly where I’m heading. Thought I’d try a pot first as haven’t played with analog stuff yet. Spawn of the devil it may be but I could move seamlessly from client to client and work on/implement systems with 100s - 1000s of users.

  • @jerryohhh
    @jerryohhh 3 года назад

    i need you help how to return into empty file into androuino leonardo as fresh from the pack

    • @RalphBacon
      @RalphBacon  3 года назад

      I'm sorry Jerry, I don't quite understand what you mean. Possibly to clear down the sketch in an Arduino Leonardo? Have you uploaded a keyboard emulator and now can't stop it splatting all over your PC?

  • @justatravellerpassingby3931
    @justatravellerpassingby3931 2 года назад

    Very nice demonstration, I think I might borrow some parts of your code for my project. Huge thanks. However I'm confused by the usage of millis() inside the ISR, as from what i remember it can't be used inside the ISR. Pls explain this.

    • @RalphBacon
      @RalphBacon  2 года назад

      You can _use_ millis inside an interrupt function; they just won't get _updated_ there. As all I'm doing is taking a snapshot, that's fine.

  • @andrewtitcombe8378
    @andrewtitcombe8378 Год назад

    The image description at the beginning is wrong or at best miss leading. As you can use interrupt RISING and test the direction being high or low . Or interrupt on FALLING is the reverse of direction being high or low. But well done , it helped me understand the method.

    • @RalphBacon
      @RalphBacon  Год назад

      Glad it helped and sorry for any confusion!

  • @jrs0007
    @jrs0007 4 года назад

    I love your videos from a technical viewpoint, but as a beginner, know absolutely nothing about coding. I get lost when you talk about the sketches. I've studied the Arduino code reference pages, but they're of little help. It's easy to build a project and copy someone else's sketch to make it function, but I'd like to learn how to do a project from idea to hardware to sketch. Any ideas on how to learn coding without someone "giving the answer first" and assuming we understand the code? Every tutorial I've found on the internet works this way, even the so-called "learn to program Arduino" courses. Thanks for providing so many interesting projects!

    • @RalphBacon
      @RalphBacon  4 года назад

      Hmm. You've got me thinking. Perhaps as part of my BB (Bacon Bytes) series I can include simple (and I mean _simple_ ) coding examples that assume nothing.

  • @stevenq4859
    @stevenq4859 3 года назад +1

    Best video on the topic out of dozens i've looked through.

    • @RalphBacon
      @RalphBacon  3 года назад

      I'm very glad it was helpful, Steve!

  • @jonasaskenobis
    @jonasaskenobis 4 года назад

    Is there really such a problem as "bouncing"? because i think your encoder is skipping steps because of that 5ms read delay, not because it reads too slowly

    • @RalphBacon
      @RalphBacon  4 года назад +1

      Switch bounce exists for just about every switch in existence. My 5mS delay is good enough most of the time to ignore those bounces. It doesn't seem to skip any steps unless you turn the RE _really_ fast (like the volume control in my car).

  • @genghisbunny
    @genghisbunny 2 года назад

    Thank you. Planning out a MAME spinner, and I think this will suit.

    • @RalphBacon
      @RalphBacon  2 года назад

      Yes, it should work out nicely 👍🏻

  • @lukaszM46
    @lukaszM46 6 лет назад +2

    instead of triggering the ISR when the pin is LOW you could trigger it with the FALLING condition and get rid of that 'less than 5ms' if statement?

    • @RalphBacon
      @RalphBacon  6 лет назад

      Nope, won't work dudekidPL. You could use FALLING as a trigger (I found it less reliable than LOW but your mileage may vary) but you can't escape switch bounce so you would *still* have to check for that to avoid false pulses. There's a more in-depth video on switch bounce in videos #96 & #98 (#96 talks about Rotary Encoders some more, #98 shows you how you CAN remove the 5ms statement if you're willing to add in a bit more hardware). Have a gander and let me know what you think!

    • @lukaszM46
      @lukaszM46 6 лет назад

      Thanks for the quick reply! I will have a look at #96 for more encoder info. I am currently trying to implement a row of encoders into a key matrix. It should work as long as I can get a single encoder to work correctly and then put that interrupt function inside the key matrix. Unfortunately I cant get a stable encoder output so far. I have 5V at the common pin because my key matrix cycles 5v between the columns. I use pull down resistors for the A and B pins. A is connected to an interrupt pin and state of B is then checked inside the ISR to acquire the direction of the square waves. In my head it sounds right but i get crazy outputs.

    • @lukaszM46
      @lukaszM46 6 лет назад

      I got it to work quite well with your code and by connecting the common pin to GND and using the software pull-ups for pins A and B . Is there a way to get similar performance but connecting the common pin to 5V and using physical pull down resistors on pins A and B? my circuit requires this configuration unfortunately

    • @RalphBacon
      @RalphBacon  6 лет назад

      Yes, you can, with a bit of fiddling about (easy). Connect the common to 5v. This means you the pins A & B will be made HIGH as you turn the shaft. The Arduino Uno doesn't have a trigger on HIGH (Arduino Due only), only on RISING so use that in your attachInterrupt statement. Also, you will need to connect 10K resistors from the pins A & B to ground so they are not left floating. The debounce routine is still required in the ISR (using the check for millis() so no change there). Should then work. Let me know if you have problems.

    • @lukaszM46
      @lukaszM46 6 лет назад

      Thanks once again for the quick reply, you're a gentleman!
      I followed your instructions but used 7.8K pull down resistors instead. I didn't have 10k but that shouldn't have much difference. The debouncing function based on time since last interrupt definitely helps but in this configuration the encoder is still acting crazy. Changing the debouncing period from 5ms to 50ms helped somewhat but I still get many stray signals, not to mention the significant delay introduced. Any suggestions? Could it be down to the encoder itself? maybe the one i am using is designed to have the common pin grounded and that's it?

  • @fjonesjones2
    @fjonesjones2 6 лет назад +1

    Great video mate, just what I needed for my next project :-)

    • @RalphBacon
      @RalphBacon  6 лет назад

      Good luck with your project, Fred Jones and thanks for posting.

  • @Ishanchawla61
    @Ishanchawla61 3 года назад

    I have 5 rotary encoders that require 10 interrupt pins. But Arduino Mega has only 6 interrupt pins. What should I do?

    • @RalphBacon
      @RalphBacon  3 года назад

      You may need a processor that can handle more interrupts - but if you have 5 rotary encoders you only need 5 interrupts as only ONE pin one each rotary encoder will need to trigger an interrupt.

    • @Ishanchawla61
      @Ishanchawla61 3 года назад

      @@RalphBacon it is a quadrature encoder so it requires two pins. Which microprocessor will be okay? Rasberry Pi 3 >

    • @RalphBacon
      @RalphBacon  3 года назад

      I don't know about the RasPi when it comes to interrupts; the ESP32 can have any pin as an interrupt but it doesn't have a huge number of pins either; but it might be OK.

  • @albandaumer3441
    @albandaumer3441 3 года назад

    Thank you for this tutorial,
    It'll help me with my music project.
    As my project has a lot of timed interruptions I also had to add some cli(); and sei(); to block and restore the handling of the interruptions, inside the equivalent of your "if (virtualPosition != lastCount)" in the main loop() function. It may also fix your problem if your "isr" function is not called when intended.
    But some strange behavior happen: when I add those cli(); and sei(); inside the "isr" function itself the arduino resets everytime it's called.
    Does anybody know why ?

    • @albandaumer3441
      @albandaumer3441 3 года назад

      I'm still investigating.
      Summary for my investigations:
      context:
      - Arduino MEGA 2560
      - I don't have the Dupont wire shield, only a plain encoder (the type you see on the pcb but without the pcb), I only use the turn detection pin, not the button for now
      - I 'm using the INPUT_PULLUP mode on the pins for my arduino to handle power to the encoder, way simpler, less cables
      - I use tone so my Arduino is constantly using time interrupts in addition to the rotary encoder handling
      what happens
      - if interrupt on pinA is in LOW mode -> it works without cli() and sei(), if I add cli and sei inside the interrupt routine it crashes
      - if interrupt on pinA is in FALLING mode -> i can add cli() and sei(), it doesn't crash, but when turning right I get sometimes "turn left" detection
      some leads:
      - maybe the breadboard connection is loose and we detect too much falling on pinA because it's trembling when I turn
      - maybe the interrupts stack in LOW mode, because of the cli(), too rapidly and that's the reason why it crashes.
      my workaround :
      - I'm in LOW mode, I don't use cli and sei, and it works, but I don't understand why, is there a protection for an interrupt function not to interrupt when it's executing itself ?

    • @RalphBacon
      @RalphBacon  3 года назад +1

      Ideally, you want to detect FALLING, as LOW will constantly retrigger whilst it is LOW (and requires logic to ignore that).
      Using sei and cli will not crash the program. Are you using these commands to prevent further retriggering of the interrupt routine you are in or to prevent the other timer interrupts?
      Are you sure your wiring is not shorting something out?
      Getting a LEFT signal when turning RIGHT indicates that you are getting switch bounce or turning it too fast - have you allowed for switch bounce as per my demo code? 5mS should be enough.

    • @albandaumer3441
      @albandaumer3441 3 года назад

      ​@@RalphBacon
      Yes I'm using the rebound protection. The decrease looks parasitic, but I secured the pin and I still got those, when I'm turning to increase it happen like once every 4-5 increase ....
      When I'm using LOW without sei and cli it's ok, no parasitic decrease.
      Here is the interrupt routine
      pastebin.com/NdmyJh4X
      Here is the consume code for which I detect "-1" on the counter when I switch to FALLING with cli and sei:
      pastebin.com/r1Cu7PAR
      If you are curious, full code is available here (may change, I'm currently updating this project on this branch)
      github.com/DelTa-B/hook-matching/blob/release/demo3/HookMatching/HookMatching.ino
      What I think is that the arduino MEGA compiler tells to block interrupts when processing a LOW trigger and that a cli in this state crashes.
      Also my connection is CHA to the left pin, Ground to the middle, CHB to the right pin. CHA is an interrupt pin, CHB is not (but I tested with an interrupt pin and got same result)
      CHA and CHB are in INPUT_PULLUP mode.

    • @RalphBacon
      @RalphBacon  3 года назад +1

      Check out Nick Gammon's website about interrupts - you may find the answer there: www.gammon.com.au/forum/?id=10945

  • @RonFinlay1
    @RonFinlay1 7 лет назад

    Hi Ralph. Tried again, and got this
    Start
    Reset
    Up :77
    and no other writes despite turning. It's as if it leaves the loop and never returns. I switched the encoder pins, as mine are label VCC, L R, Z Gnd, so I assume VCC goes to 5 V, and goes to ground, Z is also marked as the switch on the PCB where the 2 pins are, and L & R are then assumed to be the A and B encoder pins. Still no luck. I noticed the Tx LED only blinks once, which matches with the single "77" value, but certainly not the set of values you get from 50 to 77 which is what I expected. This is baffling. In using a genuine Uno board. My Led goes on (LED anode to pin 11) but doesn't dim or brighten. I assume with each turn, there's an RX/TX flicker to update my computer screen. No such luck.

    • @RalphBacon
      @RalphBacon  7 лет назад

      I've replied to your later response Ron, hope it helps. And it would help me too if you would just hit 'Reply' under the original post (rather than posting a brand new 'thread') so I can find all related responses to the original question, thanks!

  • @theUsesOFnot
    @theUsesOFnot 4 года назад

    Great explanation. My only suggestion is to minimise the isr code to just a flag and process the change in the main loop.
    bool is_changed = false;
    int pos = 0;
    void isr()
    {
    static unsigned long last_int_time = 0;
    if (millis() - last_int_time > 10)
    {
    is_changed = true;
    last_int_time = millis();
    }
    }
    then in the loop...
    if (is_changed)
    {
    is_changed = false;
    if (digitalRead(pin_b) == LOW)
    {
    pos--;
    Serial.print(F("Down: "));
    Serial.println(pos);
    }
    else
    {
    pos++;
    Serial.print(F("Up: "));
    Serial.println(pos);
    }
    }

    • @RalphBacon
      @RalphBacon  4 года назад

      Yes, that would certainly optimise the ISR and make it shorter, which is what ISRs should be, of course.

  • @gregwmanning
    @gregwmanning 5 лет назад

    Hello RalphGoing through all your videos again.I am confused with a couple of lines of code in the isr of the original sketch.void isr () {
    20 static unsigned long lastInterruptTime = 0;
    21 unsigned long interruptTime = millis();
    .
    39 lastInterruptTime = interruptTime;
    }In line 20 why the "static", what does it do; but mostly, the last thing we do in the isr() is set "lastInterruptTime" on line 39 ready for next interrupt, but next time the interrupt runs the first thing we do is reset "lastInterruptTime" to 0, why don't these statements conflict?Thanks for your time againGreg

    • @RalphBacon
      @RalphBacon  5 лет назад

      A _static_ variable is set to its initial value (if it has one, this one does) and is then _removed_ from the function_ , making it behave almost like a global variable except it can only be accessed by that function. Keeps things much tidier. Thus, line 39 does indeed update the variable with the current millis, but on re-entry to this function line 20 is *not* actioned; that statement was only ever actioned once, the very first time the function was invoked.
      Does this make sense?

  • @LIGHTSSOUT759
    @LIGHTSSOUT759 8 лет назад +1

    Great explanation.
    Thanks so much for uploading :)

    • @RalphBacon
      @RalphBacon  8 лет назад +1

      +Max Foster
      I'm glad you found it useful. And once you know, it seem so straightforward, doesn't it? Thanks for posting your comment and keep watching!

  • @mohamedatef3526
    @mohamedatef3526 3 года назад

    Brilliant !

    • @RalphBacon
      @RalphBacon  3 года назад

      You are very kind! Thank you.

  • @LuisSanchez-sy4rp
    @LuisSanchez-sy4rp 5 лет назад

    Hi Ralph.Ver y good vídeo your my LIKE.Im wondering ir you can share a link vídeo if your already have Or any idea about hoe to do the conect and enconder that doesnt have the PCB .I have seen some vídeos with and with out resistor and with and with out capacitor.I am getting confused.I am trying to make a cockpit forma muy flightsim.Hope u can help.Luis from argentina

    • @RalphBacon
      @RalphBacon  5 лет назад

      Hola Luis, que tal? Here's a picture of the connections required to a bare Rotary Encoder (no PCB): community.axoloti.com/uploads/default/original/2X/f/f656716442794f064bec964b8258ea771cd40360.jpg
      You can use the NEW method or the OLD method - the NEW method is probably more reliable.

  • @leighbucksey5263
    @leighbucksey5263 8 лет назад

    Hi Ralph,
    I have a project where I am using two encoders. I have utilised your code to run the encoders but I have one small problem. Is it possible to contact you via email or some other form so I can explain what is happening? From up north in Doncaster . Cheers Leigh

    • @RalphBacon
      @RalphBacon  8 лет назад +1

      @Leigh Bucksey
      Firstly, let me say how great it is that my video has helped you. Makes it all so worthwhile.
      Now to the issue of 'support'. The BEST place for support is the Arduino forum (forum.arduino.cc/index.php) where there are many experts cleverer than me who can lend a hand, providing you can explain succinctly the issue and what you have done so far in trying to resolve it. And follow the house rules for posting code and the like.
      As you can imagine, if I tried to do this single-handedly I'd do nothing but answer queries. That said, I'm prepared on this occasion to let you PM me on that forum after you have posted your query so that I am alerted. I should then be able to read your original post within 24 hours, during which time others may already have posted suggestions.
      I'll do my best then to help, how does that sound?
      And BTW don't apologise for being up north in Doncaster, someone's go to live there (heh heh)!

  • @vbandke
    @vbandke 6 лет назад

    Very nice, and professionally presented. Unfortunately, though, the link to the code points into data-Nirvana, in other words, a 404 (page not found) at Dropbox. Could you be so kind and update the link?
    With best regards

    • @RalphBacon
      @RalphBacon  6 лет назад

      Thanks for letting me know, Volker, I've updated the link in all places, video description and comments. If you experience further problems please do let me know. Thanks for your kinds words too, glad you like the video.

  • @jonihermawanto9896
    @jonihermawanto9896 5 лет назад

    Hello, I have seen your tutorial and I have tried it and works very well, but I got confused how to send that data to blynk so I can monitor the movement? Would you help me to solve my problem please?

    • @RalphBacon
      @RalphBacon  5 лет назад

      Many people misunderstand what the Rotary Encoder is actually doing: all it does is tell you which way the spindle or knob is turning, Joni. There are no values. That is for your sketch to decide that each "step" represents 1 or 50 or 500000. If you use my test sketch and work out what is happening all will become clear - note that I add or subtract a value depending on the rotation direction; no value is being given to the sketch.

  • @PeteTum
    @PeteTum 4 года назад

    Thanks for your help. Finally my project works as it should. Thanks again!

    • @RalphBacon
      @RalphBacon  4 года назад

      I'm delighted to have been of help, Pete. Thanks for posting.

  • @valerioguagnelliscanzani643
    @valerioguagnelliscanzani643 5 лет назад +1

    Great! I 've also learned "easy-peasy" :-)

    • @RalphBacon
      @RalphBacon  5 лет назад +2

      Added value all round then, Valerio! Normally I charge extra for language lessons but this one is included! Thanks for posting.

  • @naps1saps
    @naps1saps 7 лет назад

    Can you make another example with an interrupt timer? My setup requires the interrupt pins for other tasks like safety sensors.

    • @RalphBacon
      @RalphBacon  7 лет назад

      +naps1saps
      Do you mean an example WITHOUT an interrupt? This would only work in a sketch that has been carefully written to have no Serial.print statements, no delays and in a way so that each function (method) is only given a small time slice to do its work - otherwise you could so easily miss that rotary encoder pulse - hence the use of interrupts. If you have run out of interrupts I would seriously suggest you move onto an Arduino Mega which has many more interrupt pins (six, I believe) which would solve your problem. If you are in a part of the world that can buy from the Far East (via eBay, for example) then you can pick up a Mega clone for about $10 or so, very good value.

  • @bhartitak4084
    @bhartitak4084 6 лет назад

    Can we use rotary encoder for sensing the projection's xy coordinates?
    As we can use Lidar for the same.

    • @RalphBacon
      @RalphBacon  6 лет назад

      Not sure about this, Bharti. If you mean that you want to hang a pendulum on the Rotary Encoder so it turns the shaft as you move the object around it could work (especially if you used a stepless version) but really you should be using the device described in vide #76, an MPU6050 3-Axis Accelerometer Gyro which would work a lot better. Have a look at that video and let me know whether it's a good fit for your project.

  • @zawaralikhan7870
    @zawaralikhan7870 4 года назад

    sir,how to conect encoder+RELAY+display.

    • @RalphBacon
      @RalphBacon  4 года назад

      Learn how to do each item separately. Then think about how you would connect all three methods together. There are no short cuts to doing it properly and learning along the way.