I was wrong about millis: how to write non blocking code: (Arduino Uno Programming for Beginners)

Поделиться
HTML-код
  • Опубликовано: 24 ноя 2024

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

  • @playduino
    @playduino  9 месяцев назад +1

    you can find the code on git:
    github.com/playduino/arduino-uno-programming

  • @Volker-Dirr
    @Volker-Dirr 9 месяцев назад +9

    Very nice video. Also not just rerecording and only showing the correct code, but also talking about why the old code is wrong is a perfect solution. Guys can learn much more by such a code review. Maybe as a task for every viewer: rethink why the old problems do not appear anymore. Think exactly about the 2 situations that lead to the old bugs. The first one is easy to explain. The second one is more difficult to explain.

    • @playduino
      @playduino  9 месяцев назад

      Thank you :) I agree, I really tried but it is very hard to explain and I had a hard time understanding the issue in the first place.

    • @Volker-Dirr
      @Volker-Dirr 9 месяцев назад

      @@playduino Well, rethinking about bug 1 and 2 again in fact the first code was even faster buggy than I thought. Since if the if statement is executed in less than 1ms, this means that the storeTimeStamp is (at the end) always set to millis() (because of bug 2). So it will be set to the max value also and that mean bug 1 will occur 100%. Luckily you fixed it now.

    • @playduino
      @playduino  9 месяцев назад +1

      OMG true, so the code would stop after 50days for sure

  • @yoyohuba
    @yoyohuba 9 месяцев назад +4

    This is one of the best videos on youtube! Congrats!

  • @NormanNodDunbar
    @NormanNodDunbar 9 месяцев назад +5

    Your new code will work just fine! However, if you don't fancy waiting almost 50 days for a rollover, do this In setup to adjust the millis counter.
    extern unsigned long timer0_millis;
    unsigned long untilOverflow = 1500;
    noInterrupts();
    timer0_millis = 0xffffffff - untilOverflow;
    Interrupts();
    Now wait 1500 milliseconds and the millis count will overflow.
    Cheers,
    Norm.
    (Author of Arduino Software Internals and Arduino Interrupts)

    • @playduino
      @playduino  9 месяцев назад +2

      Awesome, this is very useful, I will give it a try! Thank you very much!

    • @evanbarnes9984
      @evanbarnes9984 8 месяцев назад +2

      Nice! I'm going to check your book out. I'm in the interesting position of being what I would consider an intermediate programmer writing code for Arduino that will go into production in toys, so I'm doing as hard a crash course in C, C++, and Arduino/AVR programming as I can manage. Your book looks great!

    • @victormikecharlie1596
      @victormikecharlie1596 7 месяцев назад

      There aren't any need for checking overflow when you use milis

    • @NormanNodDunbar
      @NormanNodDunbar 7 месяцев назад

      @@victormikecharlie1596 There is! But it depends on how the test was written. The result of millis() doesn't go negative, obviously, but it does overflow from 0xffffffff to zero. That's the problem for some calculations. As described in the video.
      Cheers,
      Norm.

    • @NormanNodDunbar
      @NormanNodDunbar 7 месяцев назад

      ​@@victormikecharlie1596 this is why overflow is a problem
      Arduino millis function, plus rollover.
      Don't do this:
      if (millis() - lastTime > 1000)
      doSomething();
      Because roll over leaves millis() less than lastTime. Do this:
      if (millis() < (lastTime + 1000))
      doSomething();
      That always works.
      Cheers,
      Norm.

  • @mrasrrcom111
    @mrasrrcom111 8 месяцев назад

    Its very good to know how the nuts and bolts of this stuff works so you know how to properly use it and know it's advantages. Now I'll shamelessly plug the NoDelay library that helps you use millis for timing without having to write that many lines of code yourself. Great for multiple timing loops

  • @hakanpolat6495
    @hakanpolat6495 9 месяцев назад +1

    Thanks bro! Enjoying your videos👍

    • @playduino
      @playduino  9 месяцев назад +1

      thank you! I'm glad

  • @REG3305
    @REG3305 3 месяца назад

    This would be better if you did direct but manipulation to remove all the overhead of the digitalWrite function.

    • @REG3305
      @REG3305 3 месяца назад

      But, I like that you are willing to acknowledge shortcomings, address them, and educate those you've previously guided as to the better methods!

  • @stephanc7192
    @stephanc7192 4 месяца назад

    Great video
    Thank you

  • @AlexHerman-qj3pi
    @AlexHerman-qj3pi 9 месяцев назад

    You are a great teacher 😊

    • @playduino
      @playduino  9 месяцев назад

      Thank you 😊

  • @DRUMsetINkeyboard
    @DRUMsetINkeyboard 7 месяцев назад +1

    im the 1000 subscriber :)

  • @navassherif3839
    @navassherif3839 7 месяцев назад

    Awesome teacher

  • @larsniklassonhede3798
    @larsniklassonhede3798 8 месяцев назад

    Thanks. Now the LED starts off and it's take 1 sek to light up. If I want the LED to start at once and then starts to blink. I tried to move the !-sign first but it's not accepted. Can you suggest something?

    • @playduino
      @playduino  8 месяцев назад +1

      hmm one solution is to turn on the LED in the setup, directly after pinMode.

  • @philtaylor1483
    @philtaylor1483 9 месяцев назад

    Will the code cause both LEDs to change, out of time, on the ~50day overflow ?

    • @playduino
      @playduino  9 месяцев назад

      I think it should not 🤔

  • @cadillacescalade5428
    @cadillacescalade5428 7 месяцев назад

    Hi, I have 2 blocking coded that both have delay
    I have a servo code that goes from 30 to 60 and from 60 to 30 with a delay of (15) speed back an forth. And also a DF-Mini player that has delays..
    I'm not to familiar with Arduino so am needing some assistance

    • @playduino
      @playduino  7 месяцев назад +1

      Hi, instead of delay(15) you could use the code shown in this video and then handle the servos instead of blinking the led (what I did)

    • @cadillacescalade5428
      @cadillacescalade5428 7 месяцев назад

      @@playduino would you still have the code ?

    • @playduino
      @playduino  7 месяцев назад +1

      Hi the thing is, I do not know exactly what you are trying to do. However I think in your case the simplest solution is actually to use a library called TimerOne. You can keep your working blocking DF-Mini code in the loop. And then have a timer isr function called every 15ms. Inside you change the angle of the servo. You will need two static volatile global variables, one for current angle (int) and one for the direction(bool). Inside or the isr you increment the angle if direction true and decrement the angle is the direction is false.
      If you hit the maximum angle you need to change direction to false.
      If you hit the minimum angle you need to change direction to true.
      Put all this logic into ISR, but don’t put a delay into the ISR. You do not need it, because the ISR is called every 15ms.
      I’ll upload a video about TimerOne soon. But if you look at example code I’m sure you can do it

    • @cadillacescalade5428
      @cadillacescalade5428 7 месяцев назад

      @playduino HI well what I am trying to put together is a sketch for a wig-wag (sweep servo) using a IR sensor and a DF-Mini player.

  • @cchstechguy
    @cchstechguy 8 месяцев назад

    Before you deploy this to your nuclear power plant, what happens when currentMillis overflows and is less than the storedTimeStamp?

    • @playduino
      @playduino  8 месяцев назад

      I would not deploy this to my nuclear power plant yet, but I am pretty confident that this will work because subtracting the big number will lead to a overflow that results in a small Number. Let's for a moment assume that we only have 8 bits. If storedTimeStamp = 255 and currentMillis is already very small, lets say 10.
      Now we calculate 10 - 255. it will overflow to the result 11.
      I just tried it by running the code:
      Serial.begin(9600);
      byte x = 10 - 255;
      Serial.print(x,DEC);

    • @cchstechguy
      @cchstechguy 8 месяцев назад +1

      @@playduino Ah. I wasn't sure how Arduino handled types in conditional expressions, but it does look like it remains unsigned and overflows correctly. This is not always the case. Evaluating the difference of 2 unsigned types within a conditional can return a signed negative value on other platforms. Looks like you are safe to deploy after all. ;)

    • @playduino
      @playduino  8 месяцев назад +1

      interesting. I assume as soon as one of the numbers in signed, the result will also be signed. Yeah all good, lets get this power plant up and running :D

  • @longdarkrideatnight
    @longdarkrideatnight 8 месяцев назад +1

    You need to create a class so you can make timers without writing more code that is the same for each now timer.

    • @playduino
      @playduino  8 месяцев назад

      Do you mean functions? I will talk about functions in 2 weeks. They are a great way to reduce code duplication

    • @longdarkrideatnight
      @longdarkrideatnight 8 месяцев назад

      I have a classy example for you who would you like to send it to you, I can put it on drop box for you to pick up @@playduino

    • @Enigma758
      @Enigma758 2 месяца назад

      @@playduino I think he means class, such as a "task" class.

    • @playduino
      @playduino  2 месяца назад

      @@Enigma758 ah, I see. @longdarkrideatnight it would be awesome if you could share the example you mentioned in the message that I currently cant see for some reason

  • @Steven_Bennett_YT
    @Steven_Bennett_YT 8 месяцев назад

    // Blink an LED on PA2 on an ATTiny1614 MCU
    // Pin definitions
    // Important - always use the full pin definition i.e. PXn where X is the port letter and n the pin number
    const int ledPinRed = PIN_PA2;// Pin 2 Port A
    const int ledPinBlue = PIN_PB1;// Pin 1 Port B
    // Variable definitions
    unsigned int A = 888; //dividend
    unsigned int B = 444; //divisor
    unsigned int C = 666; //dividend
    unsigned int D = 222; //divisor
    void setDefaultPinStates() {
    pinMode(ledPinRed, OUTPUT); //set as output
    pinMode(ledPinBlue, OUTPUT); //set as output
    digitalWrite(ledPinRed,HIGH); //start with LED off
    digitalWrite(ledPinBlue,HIGH); //start with LED off
    }
    void setup() {
    setDefaultPinStates();
    delay (1000);
    }
    void loop() {
    /*
    Flash the LEDs on PA2 & PB1 with a single line of code.
    The remainder of millis divided by A is compared to B
    and when greater the result is 1 and when less is 0, this binary result
    is written to the appropriate ledPin
    */
    digitalWrite(ledPinRed, millis() % A > B);
    digitalWrite(ledPinBlue, millis() % C > D);
    }

    • @playduino
      @playduino  8 месяцев назад

      digitalWrite(ledPinRed, millis() % A > B)
      looks like a very interesting way to get blinking patterns, thanks for sharing

    • @Steven_Bennett_YT
      @Steven_Bennett_YT 8 месяцев назад

      Not my idea I discovered to concept from ruclips.net/video/foiqs-rNHig/видео.html@@playduino