Julian Investigates: How Slow is Arduino?

Поділитися
Вставка
  • Опубліковано 13 лип 2024
  • Arduino is designed to be easy to use. But what penalty does that impose on instruction execution times? Find out how direct port bit manipulations can speed things up ten fold. Plus a little look at interrupts.
  • Наука та технологія

КОМЕНТАРІ • 321

  • @deangreenhough3479
    @deangreenhough3479 9 років тому +2

    Interesting, thoughtful and intelligently explained. You have a gift Julian, once again you just make it sound so easy to understand

  • @das250250
    @das250250 8 років тому +51

    Julian - As always a very well explained video . You are the master of complexity made simple : a great teacher.

    • @JulianIlett
      @JulianIlett  8 років тому +12

      +graham kaveman Many thanks Graham. Much appreciated.

    • @seanocansey2956
      @seanocansey2956 6 років тому

      The Kaveman so true

  • @jeffbeck6501
    @jeffbeck6501 9 років тому

    This video gets better and better every time I watch it. Jam packed with amazing info. Thank you Jullian.

  • @GrahamDIY
    @GrahamDIY 7 років тому +1

    Love this video. Ever since school I've wanted a reason to buy an oscilloscope- now I gave one!
    Seriously, another great and well explained video. I learnt a lot!

  • @DasIllu
    @DasIllu 9 років тому

    As always i learn something from your videos. It's never wasted time. Thank you

  • @stephencripps9643
    @stephencripps9643 5 років тому

    Excellent stuff, extremely well explained and also showed why we should be cautious about what we see on a scope.

  • @clearwavepro100
    @clearwavepro100 8 років тому

    Thank you for creating and sharing this! My favorite part about(of) this video, is the awesomely good perspective to have(applicable to anyone, really) that doesn't point a finger at anyone, just points a finger to the answer!!!! Perfect, thank you. :)

  • @nunyabiznez4408
    @nunyabiznez4408 9 років тому

    Very insightful. Thanks for answering these questions, I wish more folks would do the same.

  • @mikeydk
    @mikeydk 9 років тому +78

    Could be interesting to se to see how fast
    while(true)
    {
    PORTB = B001000000;
    PORTB = B000000000;
    }
    is, compared to loop(), the "while" should remove the arduino housekeeping on every loop()

    • @RWoody1995
      @RWoody1995 9 років тому +6

      K5HJ wouldn't that just continually set PINB to 1 so it would just stay high?

    • @RWoody1995
      @RWoody1995 9 років тому

      K5HJ ah gotcha, forgot about those, been using them a lot while programming xmega chips and for some reason assumed the older mega chips didnt have the same functionality and could only directly write to the pins hehe... >

    • @AnsyCrofts
      @AnsyCrofts 9 років тому +3

      K5HJ Good Grief! Never used that!!!
      When I've finished Windows 10 upgrade, I'll give it a shot! Time to re-read the datasheet. Knew Xmegas had it, but...

    • @seanocansey2956
      @seanocansey2956 6 років тому

      K5HJ that is very cool actually

    • @JensRoland
      @JensRoland 6 років тому +5

      Of course, you could unroll the loop and just insert a hundred identical lines of:
      PINB = B00100000;
      PINB = B00100000;
      PINB = B00100000;
      PINB = B00100000;
      ...
      That would be much faster 99% of the time, limiting the loop overhead to just one ‘sputtering’ every 100 instructions. It’s a hack, but it would show more clearly how many times Arduino can actually switch a pin on and off in a microsecond.

  • @AlexBlate
    @AlexBlate 9 років тому +11

    And to the many folks who have suggested that Julian take up AVR assembly programming... I would remind you of two important principles. The first, paraphrasing the great Don Knuth, is, "a cardinal sin in computer science is premature optimization." Put simply, focus on getting your code and algorithms correct and then address performance issues as needed. The second is Amdhal's Law, which basically says that you should focus optimizations on code that is both slow and which takes up a significant percent of processing time. Julian followed both of these rules -- he wrote a correct program, assessed its performance, and then optimized the bits that were causing performance issues. Granted, this is a very simple example. But, unless one just really enjoys coding in assembly, one is best advised to avoid it except in the (generally) rare circumstances where it's appropriate to insert it. And, at that, one should examine the machine code generated by the compiler *first* before claiming that the compiler didn't/doesn't do a good job or that it can be done substantively better by hand and that the cost of doing so in terms of readability, portability, and time invested is really worth it.
    And, for the record, yes, the Arduino libraries do introduce overheads, sometimes very large ones. So, if timing or performance is critical, bypassing them, which is generally quite easy to do without abandoning the Arduino IDE, is certainly the right thing to do... or, perhaps, write better ones and contribute them back to the community. :)

  • @dkean4
    @dkean4 7 років тому +1

    Good Digital Design insights. Excellent presentation, Julian.

  • @mirkomueller3412
    @mirkomueller3412 9 років тому

    How amazing - will probably come in handy with my next project. Great Job !

  • @kitecraft
    @kitecraft 6 років тому

    That was a really neat experiment. Thanks for sharing it.

  • @Derek_Read
    @Derek_Read 6 років тому

    Thanks for bringing this to my attention. I can't see the need for it at the moment given the projects I'm playing around with, but it is good to be aware of these kinds of things in case I run into something very time-sensitive in future.
    That would probably have to be a very specific requirement though, as I very much appreciate ability to write once and compile for different systems, plus the readability of most Arduino commands, and the fact that I don't have to worry about taking all port values into account when using PORTB/C/D.

  • @ChrisFredriksson
    @ChrisFredriksson 9 років тому +1

    Quite interesting and fun! Thanks for trying and sharing this with the internet =) Great video! =)

  • @flyingbrick88
    @flyingbrick88 6 років тому

    I'm a very novice arduino user- You are a brilliant teacher. This should have been way over my head but you made it quite understandable.
    My mind boggles at how you know what you are talking about!

  • @jakesoft
    @jakesoft 8 років тому +1

    Wow, I've been using Arduino for years and had no idea I was incurring this kind of overhead. I guess I've been lucky that it hasn't mattered for any my projects yet, but it's good to know. Thanks for sharing!

  • @malgailany
    @malgailany 9 років тому

    Thanks Julian, good to know this kind of information.

  • @DrenImeraj
    @DrenImeraj 9 років тому +19

    The Global Interrupt Enable is bit 7 of the Status Register (SREG)

    • @JulianIlett
      @JulianIlett  9 років тому +5

      Dren Imeraj Ah, too simple! I missed the obvious. Thanks Dren.

    • @DrenImeraj
      @DrenImeraj 9 років тому +1

      Julian Ilett No problem. Great video, as usual. Please keep them comin!

    • @superdau
      @superdau 9 років тому +6

      Julian Ilett
      Or ignore the bit and just call "noInterrupts()". Yeah, it's that obvious ;) . And you get them back with "interrupts()". "cli()" and "sei()" do the same but might not be that obvious if you don't know AVR assembler.

    • @alexholguin4825
      @alexholguin4825 7 років тому

      Dren Imeraj black movies play Wet Willie

  • @davidkempton2894
    @davidkempton2894 9 років тому

    Hey Julian, that was really interesting. Thanks.

  • @MilanKarakas
    @MilanKarakas 8 років тому

    Good examples! Thanks for the video.

  • @spikekent
    @spikekent 7 років тому

    Wow! That was fascinating and very expertly explained for a novice like me.

  • @makingthings277
    @makingthings277 9 років тому

    Very inturesting! Good in depth check!

  • @collingtech1
    @collingtech1 8 років тому

    very good masterclass julian thanks for video , cheers

  • @s4rg380
    @s4rg380 4 роки тому

    For what it is, and what it costs, it is still an impressive little piece of hardware. Thanks for the insightful video,

  • @james7145
    @james7145 9 років тому

    Excellent video.

  • @k.chriscaldwell4141
    @k.chriscaldwell4141 Рік тому

    Fascinating, and good info. Thanks.

  • @rupertrooksby
    @rupertrooksby 9 років тому

    I have only just begun playing about with Arduinos this month (pretty much due to your videos - you are responsible for the postman visiting almost everyday this week with a new little free-shipping treat).
    But the first thing I did after Blink was throw the Arduino IDE and its libraries overboard. I understand the beginner-friendly broad-appeal thing they were going for, and it probably works for that, but as your video clearly shows, too much is happening behind the curtain. For me anyway, I think a lot of the fun of mucking about with this whole embedded caper is to be right down there, and just that little bit closer to the silicon. You can't do that with Arduino libraries slowly moving the scenery behind your back.
    So for me that means using something like SublimeText, makefiles, and writing code just based directly off the Atmel datasheet and lots of google. Very happy with that setup. Fast and direct. There's a steeper learning curve for sure, but that's more than half the fun.

  • @Ed19601
    @Ed19601 6 років тому

    Very good explanation

  • @GogogoFolowMe
    @GogogoFolowMe 6 років тому

    Very interesting, I was going to make these mesures, thanks for the vid !

  • @AxelWerner
    @AxelWerner 8 років тому +7

    btw: there is a "arduino function" to disable interrupts. i think its " nointerrupts() " . you should also try using bitwise or and bitwise and operations to set and delete bits on a register. dont know it its faster, but it clearly does not overwrite or clear any other bits in the register. Also if you want to be in total controll or timing and things to happen, it might be a good idea to NOT USE the "loop()" routine, but making your own "while" loop. that is, because if you disabled interrupts in your own while loop there will be nothing else but what you wrote yourself. with the "loop()" loop its more likely that this is "NOT" a real loop, there are things happening before and after one "loop()" run. things that are not interrupt driven, but may interfere with your expected timing.

    • @AxelWerner
      @AxelWerner 8 років тому +13

      +Julian Ilett , i did some more research and testing. i was able to bring it up to 2.6MHz. see my results and screenshots here: bit.ly/1P00hKn

  • @joseperezmiranda6226
    @joseperezmiranda6226 8 років тому

    Very well explained. Thanks.

  • @raccoonnyc
    @raccoonnyc 9 років тому

    Nicely done, thanks!

  • @Disillusioned_one
    @Disillusioned_one 8 років тому +2

    Julian, I used atmel studio 6 and wrote the blink program in C without delays. I loaded this compiled program and unset the div8 fuse, I scoped the output at 4mz I was amazed.

  • @DJignyte
    @DJignyte 9 років тому

    Excellent stuff!

  • @tubical71
    @tubical71 9 років тому +1

    Thanx Julian!!!
    This is very commen on high-level coding, as it is more easy for beginners to get something going, it creates also a lot of overhead in the final code. Best example here is BASIC. As it is an interpreter language and it also creates lots and lots of code to be executed, when you use a compiler BASIC.
    But you can always do some "inline-assember" for quick execution, but it you do so you have to deal with all this "unwanted" side-effects witch made assembler coding more difficult....
    Speed or simplicity YOU have to choose.....and as always, it all depends on YOUR very own needs;)
    Julian, you may take a look at the final output ASM-code to be executed by the AtM168 when using the arduino envoirement. As it clearly shows the overhead created by the arduino IDE....;)

  • @DeepankarMaithani
    @DeepankarMaithani 9 років тому

    Great video

  • @SheltonDCruz
    @SheltonDCruz 6 років тому

    excellent tutorial!

  • @JerryEricsson
    @JerryEricsson 7 років тому

    Cool video, I dug out one of my old Nano's and installed Tiny Basic in it, now I can play around with the first programming language I ever used, and on such a small platform. It is really cool that I can reach it with both the Arduino programmer or cool term, actually cool term makes it feel more like programming on the C=128, my first computer, and, of course my first love.

  • @sbern42
    @sbern42 9 років тому +6

    It should most definitely be a crystal. They get smaller than that. :)
    Also, if you set your scope probes to 10x (and tell your scope that's what they're set at) it should show a better square shape. 1x mode usually lowpass filters the input at around 8MHz or so.
    And if you put a while(1) { } inside the loop() around the PORTB:s, it should reduce the overhead a little bit more in the jump back to the start again.

  • @hemashri
    @hemashri 5 років тому

    Thanks. I enjoyed very much

  • @AlexBlate
    @AlexBlate 9 років тому

    Great tutorial on high-performance Arduino magic.
    To avoid the overhead of the loop() routine, you can enclose the body of loop() in an infinite loop, e.g.,
    void loop() {
    while(1) {
    //your code here
    }
    }
    At minimum, this avoids the overhead of returning from loop() and calling it again from the Arduino libraries. This should also obviate the need for any delays between the writes, though parasitics may still give you an "ugly" square wave.
    Another useful trick along the same lines as what you presented is to change the state of multiple pins (on the same port/bank) simultaneously. Due to the goofy mapping of Arduino canonical pin names and the actual ports, you sometimes end up with goofy combinations of pins... but, if you wanted to do a simple bit-banged 8-bit DAC, for example, this would do the trick. (I think W2AEW used this trick in one of his videos a while back).
    Cheers, mate!
    Alex

  • @Inspironator
    @Inspironator 6 років тому +1

    I like your Arduino videos, especially the finer points in this video, as well as your MPPT videos. Maybe you could create a how it's done video on the MPPT graphing -- really cool.

  • @mankav
    @mankav 8 років тому

    Interesting video

  • @TKomoski
    @TKomoski 9 років тому +13

    Morning Julian - If you really want to push the speed limit try Assembly Language. The native code that all micro's normally use. What Arduino does is disassemble your code into assembly language so that the micro can execute it. Assembly is quite lengthy and cryptic, understanding the Instruction Set is the key. I would suggest using Atmel Studio 6.X because you have the benefit of a full fledged programmer. If you don't want to use assembly try using C+ because it is the closest thing to it. I'm sure that you are aware of this and your channel is geared toward the beginers side. Since Atmel Studio is FREE for Windows users I never use Arduino to code any more. Sure the learning curve for steep, but there is ton's of info online to get you started. Code you write in Arduino is the same as in Atmel Studio, but the major difference is that you're not restricted to one language. Thanks for all the great video's, Cheers ;-)

    • @originalmianos
      @originalmianos 9 років тому +8

      T Komoski C is closer the machine than c++. Yep, good idea to try Atmel Studio of you don't mind the 2G download but the problem here is the overhead in the 'arduino' libraries and chip setup, and that's how the majority of people here are going to be using the boards.
      Also, I use gcc with my own waf 'makefiles'. You can use -S with to output the actually assembly language generated. If you do that in this case you will see there are surprisingly few instructions emitted for this code. The problem here is all in the 'arduino' framework.

    • @RogerKeulen
      @RogerKeulen 7 років тому +3

      Thanx for the advice... I'm downloading it now !
      I hate these higher languages for simple devices. Now i can use my old C64 tricks to optimize for speed but also important SIZE ! (speeds doesn't cost money, memory size does)

    • @FawfulDied
      @FawfulDied 6 років тому +2

      Under GCC, identical C and C++ code produces identical output. C++ classes and C++ iterators are zero-cost abstractions (compared to the same thing in C).
      avr-gcc is pretty smart; it is able to turn PORTB |= (1

  • @MrTopfpflanze1
    @MrTopfpflanze1 8 років тому +1

    I really love your idea of trying to get the most out of these microcontrollers, and the video is really nice to watch.
    I'm not sure if it works for this specific chip, but the avr libs include the functions "cli()" (clear interrupt) and "sei()" (set interrupt), which disable or enable all kinds of interrupts (timers, external, etc), I don't think it wouod change anything though as you disabled the timer0 interrupt already.
    Also I think digitalWrite and digitalRead are slower because to my knowledge function calls (depending on the used calling convention) just happen to be slow (pushing parameters, creating stack frame, jumping to function, jumping back etc). I could imagine though that these time critical functions are inlined and I don't know if function calls are the same on microcontrollers, I have way more experience on Intel/AMD CPUs in regular home computers.
    Keep up your work!

  • @PetRatty
    @PetRatty 9 років тому

    Great work Julian, this extract is taken from the core library arduino folder/hardware/arduino/cores/arduino/wiring_digital.c
    void digitalWrite(uint8_t pin, uint8_t val)
    {
    uint8_t timer = digitalPinToTimer(pin);
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;
    if (port == NOT_A_PIN) return;
    // If the pin that support PWM output, we need to turn it off
    // before doing a digital write.
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);
    out = portOutputRegister(port);
    uint8_t oldSREG = SREG;
    cli();
    if (val == LOW) {
    *out &= ~bit;
    } else {
    *out |= bit;
    }
    SREG = oldSREG;
    }
    As you can see there are loads of C commands just to change the pin state.

  • @DeeegerD
    @DeeegerD 9 років тому

    Did something similar a few months back using a logic analyzer. I was able to get the Arduino board to 4 MHz and could see those glitches in the pattern as well. I did not set interrupts off - just bit toggled the one pin off and on.

  • @suelinerr
    @suelinerr 9 років тому

    Thanks for sharing.

  • @ArcAiN6
    @ArcAiN6 7 років тому

    and now that i've watched the rest of the video, i see you've already figured that out :D

  • @mortensentim511
    @mortensentim511 9 років тому

    I did exactly this experiment before Christmas for a project I'm working on. Port masking and manipulation are more confusing to deal with, but the overhead of DigitalWrite is huge. Nice catch with the interrupts, I didn't think about that.
    After that was sorted the ADC became the bottleneck, it's a shame the Arduino has such a slow ADC compared to say a Nucleo board.

  • @RaoulRacingRC
    @RaoulRacingRC 8 років тому

    Nice video, I got a question after watching this video. What do I need to use instead of analogWrite, analogRead and digitalRead? If my porgram still contains analogWrite, analogRead or digitalRead it is slowing down on that isn't it?

  • @gerrymcerlean8432
    @gerrymcerlean8432 3 роки тому

    Thank you. Extremely well explained. Doesn't the Arduino also have a 'micros' function which keeps a count of the elapsed microseconds? Does this also use an interrupt?

  • @MithiSevilla
    @MithiSevilla 9 років тому

    Thanks for this! Great video!
    I do hope the developers find a way to optimize the conversion eventually.
    For example from pololu's library this command:
    set_digital_output(IO_D3, HIGH);
    compiles to this in assembly:
    sbi 0x0b, 3 ;i.e. PORTD |= 1

  • @36trooper
    @36trooper 9 років тому

    Do you still need the pinmode function in the setup if you're using port assignments instead of the digital out command?

  • @JerryEricsson
    @JerryEricsson 9 років тому

    Nice to see a fellow can still get to the raw insides of one of these little gems. Shades of the old C=64 machine language programmer that came with RUN magazine or one of those Commodore magazines, perhaps it was Commodore?

  • @ribb4200
    @ribb4200 6 років тому

    Yes, the C compiler leaves a lot of guesswork for bit-banging. Look at the machine code, then write in machine code, or simply do it in assembly language which can be done on Arduino if you can find an assembler. Microchip was more my style since that is native assembly language. At first and still, I was disappointed with Arduino, trying to figure out what it was doing and immediately started on a difficult path looking for an Arduino assembler to make the Arduino do what I wanted it to do. Not much luck, except that assembly language with Arduino is possible or fast machine code can be inserted into the compiler for critical fast timing.
    Thank you Julian for scoping the Arduino and showing the C compiler confusion trying to make the Arduino do what you wanted to do and what you know is possible.

  • @k0ppit
    @k0ppit 9 років тому

    +Julian Ilett A trick to toggle an output pin is to write 1 to that pins "Input Pins Register". Use "cli()" end "sei()" to disable/enable global interrupts.

    • @k0ppit
      @k0ppit 9 років тому

      k0ppit
      Got an Arduino Diecimila to toggle pin 8 at 2,66MHz and 50% duty cycle with this code.
      void setup() {
      cli(); // clear global interrupt
      DDRB |= 1

    • @k0ppit
      @k0ppit 9 років тому

      k0ppit
      Got an Arduino Diecimila to toggle pin 8 at 4MHz and 25% duty cycle with this code.
      void setup() {
      cli(); // clear global interrupt
      DDRB |= 1

  • @asiw
    @asiw 6 років тому

    Fascinating.

  • @leebolton9275
    @leebolton9275 9 років тому +1

    Hi, love watching your videos, thought i would do a comparison between arduino bootloader and using Atmel Studio, Atmel Studio was 120ns between port on and off where as Arduino was 400us. Massive diference!!

  • @EZ_shop
    @EZ_shop 8 років тому

    Very interesting.

  • @tobortine
    @tobortine 9 років тому +13

    Some one has already suggested this but I will repeat it. If you're going to do these type of experiments then use assembler. The Arduino IDE is designed to make development easy but in so doing it introduces masses of overhead. Even the loop in the code is generating many, many instructions. The IDE abstraction prevents you from getting accurate results at the level you're measuring.

    • @superdau
      @superdau 9 років тому +19

      tobortine
      That's why he wrote "How slow is Arduino?" and not "how slow is an atmega?". It wouldn't be Arduino if you are programming in assembler.

    • @tmmtmm
      @tmmtmm 9 років тому +1

      superdau but then i guess then it is "how slow are arduino functions" and not "how slow is arduino" since arduino doesn't limit you to using the provided libraries.

    • @tobortine
      @tobortine 9 років тому

      superdau
      Ardiuino = Atmel processor + Peripherals + IDE
      The peripherals are only used to load the code so the IDE (libraries, macros, etc) are what slow down the native chip. If you're making a video about how slow an Arduino can be then showing the relative speed of the native chip with efficient code illustrates the point.

    • @RWoody1995
      @RWoody1995 9 років тому

      tobortine i don't think so to be honest, i think if you are comparing arduino code to something you should compare it to C because C is the language someone looking to transition away from arduino is most likely to be moving to.
      you dont compare a sports car to a race car when your audience really want a supercar do you? :P

    • @AlexBlate
      @AlexBlate 9 років тому

      megaspeed2v2 At last check, the Arduino development environment already uses C++... some code does actually use the object-oriented features in C++, but most doesn't or cleverly hides it from you; so, without starting a religious war about C vs. C++, Arduino programmers are already programming in C. The point, though, is that you *can* develop high-performance applications while retaining some of the Arduino IDE and toolchain's benefits; you just have to RTFM a little more. The nice thing is that you can decide how much deep magic you wish to explore and are not thrust headlong into a raw microcontroller development environment with all of the attendant arcane goo that's required just to get a simple program working.

  • @NiCadHeliPilot
    @NiCadHeliPilot 8 років тому

    Great vid. That's quite a surprise on how slow the Arduino Bootloader (the firmware that uses the stuff that you've typed up in the IDE) actually is.
    I suppose it wouldn't matter so much for most general stuff, but I"m wonderin' how much would that hold back something like a brushless ESC?

  • @hellterminator
    @hellterminator 6 років тому

    And this is precisely why I do all my Arduino programming in Atmel studio. You lose all the Arduino functions and libraries, but you actually know what your code is doing.

  • @aaaafaaaaf
    @aaaafaaaaf 8 років тому

    Julian,
    Ca you please tell me what installer you used to program the arduino nano, I purchased 6 of them to save on shipping, but I am not able to attach to it via the USB. Can you tell the model number and where you go it, THANK YOU in advance.

  • @BokoMoko65
    @BokoMoko65 8 років тому

    Have you tried to invert the order of the high/low ? Just to make sure the overhead is actually from the flow control and not the high/low process itself.

  • @RobAbdul
    @RobAbdul 9 років тому +1

    How much is the current draw on this in an hour?

  • @byronwatkins2591
    @byronwatkins2591 5 років тому +6

    Try 'cli();' to disable all interrupts.

  • @Chiller3k
    @Chiller3k 9 років тому +1

    If you don't want to go through the trouble of using port manipulation, there is a great library called "Fast digital I/O for Arduino" from Jan Dolinay which is way more convenient but still gives you a considerably faster code execution

  • @n3qxc
    @n3qxc 7 років тому

    if you lowered the cycle frequency on pin 13 to an audible tone.... can that interrupt signal be detected in a speaker or audio amplifier?

  • @espenbgh2540
    @espenbgh2540 8 років тому

    The glory of the Arduino isnøt all that glory and the 16 MHz througput isn't allways 16 MHz. Brilliant show Julian.

  • @aitorsierra
    @aitorsierra 9 років тому

    I recently made this test with the same Arduino code but also i made other tests with other boards such as Stellaris (Texas Instruments), Arduino M0 Pro and Microchip PIC. I will upload a video with the results

  • @mantaz111
    @mantaz111 9 років тому +2

    What if you put port output set instructions in a while(true) loop, so that function loop() doesn't have to end?

    • @RonNewsham
      @RonNewsham 9 років тому +2

      mantaz111 I was wondering the same thing and dug out the code that Arduino executes. There is behind the scenes a main() that does some stuff including:
      setup();
      for (;;) {
      loop();
      if (serialEventRun) serialEventRun();
      }
      It is fairly clear that there is the overhead of calling the loop() function (so that's a few instructions to throw some registers onto the stack, perform the call then restore the registers from stack) - not too much, but nonetheless a function call.
      But then there is also the test to decide whether to run a serial event.
      The bottom line here is that there is the overhead of convenience (being able to use pin 13 rather than port D bit 5 or whatever), and the overhead of the framework (additional function calls, overhead of timers) that may be useful and helpful, or not.
      The nice thing is that you generally have a choice - use the Arduino and the convenience (and limitations), or use the lower-level machine instructions (either in C or assembly language).

  • @kuyanatnatdkrx7
    @kuyanatnatdkrx7 9 років тому

    if you want to remove the noise which is caused from the built pre coded interrupts you can type noInterupt() function to disable them and type interrupts() to reable them. If you really want a high efficient code for tasks that require high precision time based code then I think it is best to stick to the original type of microcontroller coding and that is doing it the hard way. Also note when I say efficient I mean being able to type code like _asm("wfi") and save power but that would be redundant in the arduino IDE and libraries as there is interrupts happening everywhere.

  • @jameslamb4573
    @jameslamb4573 9 років тому

    I'm surprised you didn't reverse the order, i.e. off then on, to check it was the loop introducing the delay and not some weird propagation problem or capacitance etc. effect.
    Funny how programming goes back to basics, it's as if machine code has decided to make itself known to a whole new generation of programmers.
    Nice work!

  • @neildarlow
    @neildarlow 9 років тому

    Let us analyse what is going on here:
    1) digitalwrite(output, state)
    The output number has to be translated to a specific bit of a specific port. This involves two lookups using tables. One lookup determines the port associated with the output and the other constructs a bitmask to associate with the output. Finally the action of setting or clearing the bit has to be determined from the state parameter. Given that the lookups incur significant overhead it is not surprising that digitalwrite takes a good amount of time to execute.
    2) loop function
    Associated with the loop function there is some housekeeping code. It is small but it is executed once per loop function iteration. I believe this housekeeping is associated with managing serial I/O at a low level.
    You should be wary of using direct port I/O for the reasons that Julian described but it is important to make your I/O operations atomic to prevent side-effects caused by code executed in e.g. interrupt service routines from clashing with the values you wish to write and causing undesirable effects. At a high level you can use the &=, |= and ^= assigmnent-with-modification syntax to only operate on the bit(s) you intend to modify but this requires that the compiler handles these assignments atomically. At a lower level, assembly language bit-set and bit-clear instructions are a better solution because they are atomic by design.

  • @pedromms8908
    @pedromms8908 9 років тому

    And that's why I allways used AVR Studio to develop Arduino ASSEMBLY scripts when I needed a "fast" arduino response time.
    I now it was slow, but I never thought that "arduino IDE style" sketches were so slow!

  • @reggiebacci
    @reggiebacci 9 років тому

    I think the reason for the runtime conversion is so that you're able to specify the Arduino output pin as a variable, so you can loop through or address a number of pins e.g. for (myPin...) {digitalWrite (myPin, HIGH); }
    Obviously this wouldn't be possible if these were translated as constants at compile time.

  • @r3corpinformatica
    @r3corpinformatica 9 років тому

    Julian, coud you please make the same video kind for the ESP 8266 ?

  • @tengelgeer
    @tengelgeer 9 років тому

    Julian, as you might have found by now there is a interrupt enable bit. It's (for a Atmega168) bit 7 of the SREG register. But there is a quick macro for it, cli() (CLear Interrupt) en sei() (SEt Interrupt).
    And yeay, Arduino has a lot of overhead. But it's always a trade of between fast, versatile and complex or slower, more static but a lot easier. And the last part is the whole reason, making it easy to use.
    But what are you planning on doing? Sounds like you should just use the PWM.

  • @davepauljones
    @davepauljones 4 роки тому

    Thanks Julian, I wonder if the bootloader is taking up any cycles or resources.

  • @eight-double-three
    @eight-double-three 7 років тому

    There's a valid reason to doing the mapping dynamically: This way you're able to use digital write with the port number from a variable. Analysing the code, and replacing the ones where the pin number argument to digitalWrite() is a constant would be a solution, but that's not a trivial job on one hand, and would pretty much make the timing with different digitalWrite() calls inconsistent.

  • @hurterbe
    @hurterbe 4 роки тому

    How do I read a complete port in a similar way that what you wrote to a port without using the Digital write function?

  • @nonchip
    @nonchip 6 років тому

    the digitalWrite actually performs a hell of hand-holding to try and prevent unexpected behaviour like writing digitally to a pin reserved by a peripheral and stuff like that, that's why they do it at runtime (they check a bunch of registers to see if it should actually do stuff to the port). also the loop does other stuff in the background like checking/managing a system timer etc, this most likely introduces the overhead. also remember arduino is derived from C++, this might also introduce a small call overhead as opposed to C, also loop is an actual function, so not just a jump-back has to be performed but also stack stuff and calling/returning.
    tl;dr: safer/nicer for hobbyists who aren't that much into low level programming or just too lazy to care for a small project that doesn't have to run that performant, but introduces a LOAD of overhead. that's why I try not to use it if possible (avr-gcc/libc and a few small libraries to link to for common tasks is just fine) but it's great it exists, gets people into microcontrollers :)

  • @TechBuild
    @TechBuild 7 років тому

    Which is the fastest and the slowest Arduino board?

  • @jpl0087
    @jpl0087 8 років тому +3

    arduino might use bitwise operation to change only 1 output. so your test ist missleading since you make 2 total different compairison. write the second part manipulation in a way that the other 7 bits are ignored. now you set acctually 1 bit high and 7 low. since it is an 8 bit processor you can manipulate 8 outputs in parallel. thanks for a follow-up

    • @NGC1433
      @NGC1433 7 років тому

      Atmegas ALWAYS overwrite the whole buffer at once, disregarding how much bits you change, it is a single cycle instruction.

    • @jpl0087
      @jpl0087 7 років тому +2

      yes, but to get a 8 bit row of outputs changed, you need some math, and that takes time. modify one complete Port in AVR, and you bypass the arduino implementation.
      DDRB = 0b11111111; //set all pins of port b as outputs
      PORTB = 0xFF; //write data on port
      This will be the faster way. It is regular C AVR programming and no arduino interaction is being processed.

  • @GoodScienceForYou
    @GoodScienceForYou 8 років тому

    When doing mechanical "operations" as on a machine (calling out functions) the Arudino is so fast that humans can't tell there is a delay. When "this" goes on and "that" goes off, or from the time the button is pressed and 16 relays are switched It is less than 1/2 second. It is an amazingly easy to use device for controlling a lot of things. I am using a Mega board for my project and all but 4 pins are empty.

  • @IGBeTix-Electronique
    @IGBeTix-Electronique 9 років тому

    Exact, my mesurements where approximately 5 microseconds for the "high 13" instruction (on the parallax propscope).

  • @stefflus08
    @stefflus08 8 років тому

    I have very little real knowledge to bring to this topic, so I'm genuinely asking:
    1. @ 9:45 , if we assume the asymmetry is from programming, it should potentially run at somewhere around 2Mhz?
    2. Does this chip have and use a CKDIV8? These two presumptions would make your 16Mhz?

  • @Relations99
    @Relations99 9 років тому

    Hey Julian!
    Great work on and research on this topic! Long time supporter and fan of your channel. Do you have anyway to speed up AnalogRead? I am trying to use the arduino as a oscilloscope. I dont have the $$$ to get one xD And I already have an arduino around. Thanks!

    • @sbern42
      @sbern42 9 років тому

      Relations99 While it is possible to speed up analogRead() a bit, its main delay isn't due to code overhead (that much). The ADC needs time for the hardware to convert analog to digital. If you were to skip analogRead(), you'd have to manually check if the ADC was done converting before reading its registers, otherwise you wouldn't get sensible data. This is done by analogRead() for you, by simply waiting until it returns something.

    • @JulianIlett
      @JulianIlett  9 років тому

      Relations99 I think you read my mind! I'll be looking at analogRead() next. I also want to build a cheap Arduino oscilloscope and speeding up ADC operation is the key to maximising it's frequency range. There may be a way to have continuous analogRead()s by putting all the other code into the gaps where the successive approximations take place. This would require interrupts from the ADC to break into the code for display updates and keyswitch reads etc. Not sure how feasible this is yet though ;)

    • @AsafShahar
      @AsafShahar 9 років тому

      Julian Ilett this meettechniek.info/embedded/arduino-analog.html might save you a lot of work... (and much less fun) but the overall estimation you are looking at 77khz max using continuous ADC conversion (about 13 clock cycles per conversion) for the ATMEGA328. not very impressive.

    • @sbern42
      @sbern42 9 років тому

      Relations99 Also, using an arduino as an oscilloscope is a useful exercise for your own development, but to be honest, it will be useless for pretty much anything as a scope. Even the oldest analog scopes from the 60's and such will be far more capable.
      As a learning experience and fun project, go for it. It'll be a great thing. As a useful tool, look around with universities, second hand on-/offline and auctions and such, even ebay, and get the cheapest analog scope you can possibly find where the trace is visible and a curve is shown on the display (indicates that the scope works and triggers). I got myself a Tektronix 2465 (300MHz 4-channels) for less than the equivalent of 100 GBP about 8 months ago at an annular university electronics auction. And that's much more than you'll need. Lesser scopes went for 10-30 GBP.

    • @Relations99
      @Relations99 9 років тому

      Stefan Berndtsson yeah noted thanks. I was and still am looking out for scopes. But it's rather frustrating because they then to go very very fast.
      Julian Ilett there is a sort of a guide online, On indestructibles, that uses and external ADC and external clock for the ADC, all to save some processor calls on the arduino. Also, might wanna look into SerialWrite. ;)

  • @Jadinandrews
    @Jadinandrews 9 років тому

    Great video, I see a lot of people saying you should have used assembly, but then you wouldn't really be assessing the performance of an 'Arduino'. I'd rather switch to a more powerful micro if performance was that big a deal before learning assembly. That said, it would be real interesting to see how far the atmega 328 can be pushed with assembly.

  • @VoidHalo
    @VoidHalo 5 років тому

    That is some really rustic looking soldermask and silkscreen on that arduino. Looks almost like when you get a PCB from the 80s where the solder mask goes all crinkly.

  • @mybirds2525
    @mybirds2525 5 років тому

    The issue is loop overhead. Calling a subroutine is very tedious. This is fixable by applying Bit-Banging which is port read right of all 8 pins in a port in one step. Reading a port the same way is much faster. Also clocking loop out using while(1) {...} to contain the action speeds up things by about 62 clock cycles vs the loop() { .... } thing

  • @jwcolby54
    @jwcolby54 4 роки тому

    Two things. C++ is closer to the metal but it is not assembler.
    1) Each line of code will be 1 to n lines of assembler.
    2) any function call in c++ pushes values onto the stack and the return pops those values off the stack... Or potentially anyway. Pushes and pops are moving registers to / from memory and take time.
    3) use an xor to flip the bit. That should leave the other bits of the register alone.

  • @yoramstein
    @yoramstein 7 років тому

    QUESTION- if an Arduino gets 5Volts Vcc what should be input at one of the Analog inputs in order that it will show 1024 reading from its A/D converter? is it also 5volts?

    • @JulianIlett
      @JulianIlett  7 років тому

      Interesting question. The A/D converter can't return 1024, the maximum result is 1023. This does not indicate a precise voltage - it indicates a voltage range - very close to 5V but with about 5mV of latitude.

  • @das250250
    @das250250 8 років тому

    When the disappearing occurs are you suggesting the square wave stops working ? Missing pulses ? Can your oscilloscope sample when such an interrupt occurs to see the waveform Vs time ? If this is the case wouldn't this cause many errors for all output projects based on timing ?

    • @raykent3211
      @raykent3211 8 років тому

      my guess: the output is oscillating continuously but the length of a pulse may be increased periodically by the timer0 interrupt service. We see stuff vanishing briefly while the scope re-syncs, or we're getting a strobing effect. Maybe an old-fashioned analog scope would do better? It's only really significant for projects that need to make pulses at accurate length and/or "high frequency" e.g. audio output at an acceptable sample freq.

  • @fifaham
    @fifaham 4 роки тому

    Remember that the sampling capability of your scope may not be linear relative to slowing down and speeding up the time scale. May I ask what is the sampling capability of your scope? And if it maintains the same sampling rate at this very slow time scale? You are doing great job BTW.

  • @PeterBrockie
    @PeterBrockie 9 років тому

    I think A0-A5 are defined as D14+ under Arduino if you don't need the analog functions.

  • @fifaham
    @fifaham 4 роки тому

    In time frame of 5:30 and time frame 11:50 there appear to be signal aliasing, although I could be wrong. Signal aliasing arises from the fact that the scope maybe not perfectly aligned to sampling the Atmel chip signal. You may need to use a scope of higher sampling capability at this specific setup.

  • @nickyflachy6599
    @nickyflachy6599 6 років тому

    Hi Julian, at first, well explained and easy to understand, but you can do something to bring the speed up to nearly 8MHz ( 2 clockcycles), without using Assembler. For example, try a "while 1- loop" (like Captain-Slow sad) with Portmanipulation. I know, its not good in a program, but works fine. At second, You don't have to write only "1" to Pin 13 and at last once "0", if you "copy-paste" the "ON-OFF-command" a serval times, the speed will increase drastically. ^^) (I tried with about 100, 200, 400 and 21000 changes within the while(true) [last one doesn't work --> little joke :) ] )
    I know you are a few steps ahead of me, but I like it if someone gives me a little push to see new/better results. ^^)