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

Поділитися
Вставка
  • Опубліковано 14 жов 2024

КОМЕНТАРІ • 48

  • @playduino
    @playduino  8 місяців тому +1

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

  • @Volker-Dirr
    @Volker-Dirr 8 місяців тому +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  8 місяців тому

      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 8 місяців тому

      @@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  8 місяців тому +1

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

  • @yoyohuba
    @yoyohuba 8 місяців тому +4

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

  • @NormanNodDunbar
    @NormanNodDunbar 7 місяців тому +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  7 місяців тому +2

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

    • @evanbarnes9984
      @evanbarnes9984 7 місяців тому +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 6 місяців тому

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

    • @NormanNodDunbar
      @NormanNodDunbar 6 місяців тому

      @@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 6 місяців тому

      ​@@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 6 місяців тому

    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 8 місяців тому +1

    Thanks bro! Enjoying your videos👍

    • @playduino
      @playduino  8 місяців тому +1

      thank you! I'm glad

  • @stephanc7192
    @stephanc7192 2 місяці тому

    Great video
    Thank you

  • @AlexHerman-qj3pi
    @AlexHerman-qj3pi 8 місяців тому

    You are a great teacher 😊

  • @DRUMsetINkeyboard
    @DRUMsetINkeyboard 6 місяців тому +1

    im the 1000 subscriber :)

  • @REG3305
    @REG3305 2 місяці тому

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

    • @REG3305
      @REG3305 2 місяці тому

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

  • @navassherif3839
    @navassherif3839 6 місяців тому

    Awesome teacher

  • @larsniklassonhede3798
    @larsniklassonhede3798 7 місяців тому

    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  7 місяців тому +1

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

  • @cadillacescalade5428
    @cadillacescalade5428 6 місяців тому

    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  6 місяців тому +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 6 місяців тому

      @@playduino would you still have the code ?

    • @playduino
      @playduino  6 місяців тому +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 6 місяців тому

      @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.

  • @philtaylor1483
    @philtaylor1483 7 місяців тому

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

    • @playduino
      @playduino  7 місяців тому

      I think it should not 🤔

  • @cchstechguy
    @cchstechguy 7 місяців тому

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

    • @playduino
      @playduino  7 місяців тому

      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 7 місяців тому +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  7 місяців тому +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 7 місяців тому +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  7 місяців тому

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

    • @longdarkrideatnight
      @longdarkrideatnight 7 місяців тому

      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 21 день тому

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

    • @playduino
      @playduino  21 день тому

      @@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 7 місяців тому

    // 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  7 місяців тому

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

    • @Steven_Bennett_YT
      @Steven_Bennett_YT 7 місяців тому

      Not my idea I discovered to concept from ua-cam.com/video/foiqs-rNHig/v-deo.html@@playduino