Interesting, thoughtful and intelligently explained. You have a gift Julian, once again you just make it sound so easy to understand
@das2502509 жыл бұрын
Julian - As always a very well explained video . You are the master of complexity made simple : a great teacher.
@JulianIlett9 жыл бұрын
+graham kaveman Many thanks Graham. Much appreciated.
@seanocansey29567 жыл бұрын
The Kaveman so true
@mikeydk9 жыл бұрын
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()
@RWoody19959 жыл бұрын
K5HJ wouldn't that just continually set PINB to 1 so it would just stay high?
@RWoody19959 жыл бұрын
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... >
@AnsyCrofts9 жыл бұрын
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...
@seanocansey29567 жыл бұрын
K5HJ that is very cool actually
@JensRoland6 жыл бұрын
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.
@GeeTheBuilder8 жыл бұрын
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!
@DrenImeraj9 жыл бұрын
The Global Interrupt Enable is bit 7 of the Status Register (SREG)
@JulianIlett9 жыл бұрын
Dren Imeraj Ah, too simple! I missed the obvious. Thanks Dren.
@DrenImeraj9 жыл бұрын
Julian Ilett No problem. Great video, as usual. Please keep them comin!
@superdau9 жыл бұрын
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.
@alexholguin48258 жыл бұрын
Dren Imeraj black movies play Wet Willie
@jeffbeck65019 жыл бұрын
This video gets better and better every time I watch it. Jam packed with amazing info. Thank you Jullian.
@flyingbrick887 жыл бұрын
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!
@JulianIlett7 жыл бұрын
Thanks mate :)
@AxelWerner9 жыл бұрын
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.
@AxelWerner9 жыл бұрын
+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
@rupertrooksby9 жыл бұрын
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.
@stephencripps96436 жыл бұрын
Excellent stuff, extremely well explained and also showed why we should be cautious about what we see on a scope.
@AlexBlate9 жыл бұрын
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. :)
@jakesoft8 жыл бұрын
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!
@sbern429 жыл бұрын
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.
@fifaham4 жыл бұрын
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.
@Derek_Read6 жыл бұрын
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.
@DasIllu9 жыл бұрын
As always i learn something from your videos. It's never wasted time. Thank you
@s4rg3805 жыл бұрын
For what it is, and what it costs, it is still an impressive little piece of hardware. Thanks for the insightful video,
@MrTopfpflanze18 жыл бұрын
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!
@dkean48 жыл бұрын
Good Digital Design insights. Excellent presentation, Julian.
@Chiller3k9 жыл бұрын
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
@fifaham4 жыл бұрын
Time frame 8:50 > this is because of the parasitic on board capacitor and the sampling capability of your scope. If you use a scope with much higher sampling capability, and probes with better isolation, then you may be able to see that flat top ON section of your "Square" wave. Since you are still using the brackets of your loop then that takes relatively much more time to execute and that why the OFF period is way much longer that ON. If you use assembly code and the Atmel Studio I bet you will get way much better response / without having to duplicate PORTB = B00100000 and slow down the CPU execution speed > better yet, use PORTB.5 to slightly speed it up. Atmel Studio is easy to use and has very powerful features and I highly recommend that everyone use it along with Arduino IDE. That also looks good on your resume.
@JerryEricsson9 жыл бұрын
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?
@clearwavepro1008 жыл бұрын
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. :)
@nunyabiznez44089 жыл бұрын
Very insightful. Thanks for answering these questions, I wish more folks would do the same.
@ribb42007 жыл бұрын
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.
@mortensentim5119 жыл бұрын
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.
@tobortine9 жыл бұрын
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.
@superdau9 жыл бұрын
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.
@tmmtmm9 жыл бұрын
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.
@tobortine9 жыл бұрын
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.
@RWoody19959 жыл бұрын
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
@AlexBlate9 жыл бұрын
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.
@stefflus088 жыл бұрын
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?
@jpl00878 жыл бұрын
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
@NGC14338 жыл бұрын
Atmegas ALWAYS overwrite the whole buffer at once, disregarding how much bits you change, it is a single cycle instruction.
@jpl00878 жыл бұрын
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.
@k0ppit9 жыл бұрын
+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.
@k0ppit9 жыл бұрын
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
@k0ppit9 жыл бұрын
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
@nonchip7 жыл бұрын
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 :)
@Inspironator7 жыл бұрын
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.
@jwcolby545 жыл бұрын
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.
@oreubens9 жыл бұрын
Just because a CPU runs at X Mhz doesn't mean it can do X million instructions per second (or 1 instruction per clock cycle). It still depends on bus cycle, memory speed, instruction decoding and some complex instructions like multiplying and especially dividing can be pretty slow. And stuff like memory waitstates, DRAM refresh can make things even slower. For example on the intel 8086 a bus cycle takes 4 clock cycles, so fetching any memory (instructions as well as data) couldn't happen any faster than once every 4 clockcycles, this also explains why the 8088 with it's 8bit bus was so much slower because fetching instructions was half as fast (and accessing 16bit data as well). A full IDIV (32bit/16bit signed integer divide) Could take up to a whopping 212 clockcycles. CPU designers have become better (even for very cheap cpu's) since then and on the 8bit AVR, most common instructions take 1 cycle, but there's a few handsfull that take 2 or 3, and a couple go up to 5 (CALL, RET, RETI). FYI. There's optimal digitalWrite() versions in the Wiring framework for arduino. if the pin number is const (as is the case here), the digitalWrite will be compiled to a single SBI or CBI When the pin number is in a variable however, then there's a price to pay for the convenience of writing digitalWrite(pinnum, HIGH). Avoid if possible (even a switch/case cascade with const pin numbers will be faster (at the expense of code size).
@igorspitz7 жыл бұрын
If you look at Atmel Atmega datasheet, they do say that most instructions takes 1 cycle. The problem is, that turning GPIO on/off is more than one instruction - in 'arduino language' for sure. Maybe if he would set DDR & PORT registers directly, it would be faster. Apart to that, he said enough.
@igorspitz7 жыл бұрын
Ok, he got to that in video. I showed myself... :D
@PerchEagle6 жыл бұрын
How about defining the pins as #define? Is it similar as putting them as const int ? Or even const byte.
@byronwatkins25916 жыл бұрын
Try 'cli();' to disable all interrupts.
@mybirds25256 жыл бұрын
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
@fifaham4 жыл бұрын
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.
@eight-double-three7 жыл бұрын
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.
@gerrymcerlean84323 жыл бұрын
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?
@mantaz1119 жыл бұрын
What if you put port output set instructions in a while(true) loop, so that function loop() doesn't have to end?
@RonNewsham9 жыл бұрын
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).
@BokoMoko659 жыл бұрын
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.
@Jadinandrews9 жыл бұрын
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.
@kitecraft6 жыл бұрын
That was a really neat experiment. Thanks for sharing it.
@DeeegerD9 жыл бұрын
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.
@GoodScienceForYou9 жыл бұрын
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.
@36trooper9 жыл бұрын
Do you still need the pinmode function in the setup if you're using port assignments instead of the digital out command?
@AlexBlate9 жыл бұрын
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
@tengelgeer9 жыл бұрын
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.
@jameslamb45739 жыл бұрын
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!
@tubical719 жыл бұрын
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....;)
@PeterBrockie9 жыл бұрын
I think A0-A5 are defined as D14+ under Arduino if you don't need the analog functions.
@reggiebacci9 жыл бұрын
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.
@TKomoski9 жыл бұрын
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 ;-)
@originalmianos9 жыл бұрын
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.
@RogerKeulen8 жыл бұрын
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)
@FawfulDied7 жыл бұрын
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
@neildarlow9 жыл бұрын
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.
@mirkomueller34129 жыл бұрын
How amazing - will probably come in handy with my next project. Great Job !
@nickpelov9 жыл бұрын
the arduino is probably doing more than just a jump in the loop function. What you could try is to do the direct portB write instructions in a while loop.
@PetRatty9 жыл бұрын
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.
@kuyanatnatdkrx79 жыл бұрын
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.
@davepauljones4 жыл бұрын
Thanks Julian, I wonder if the bootloader is taking up any cycles or resources.
@ChrisFredriksson9 жыл бұрын
Quite interesting and fun! Thanks for trying and sharing this with the internet =) Great video! =)
@VoidHalo6 жыл бұрын
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.
@RaoulRacingRC8 жыл бұрын
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?
@PabloPazosGutierrez8 жыл бұрын
Using a high level programming language will always generate more than one processor level instructions. Also the loop itself is not 1 processor instruction, at a machine level that is mapped to many processor instructions. The functions digitalWrite and pinMode, might also be implemented in hundreds of low level instructions.
@xFuaZe8 жыл бұрын
Using a low level programming language will always generate code that is not portable at all. I'm not sure what you consider high or low, but programming in C is as fast as assembly. There is no reason that a "While" loop in C should take more as a loop instruction. You can bet your ass it will be translated into the same code. But yes, Arduino itself is quite, inefficiënt. But that doesn't have to be a problem. You can check the code out, like for digitalWrite: 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; }
@RobAbdul9 жыл бұрын
How much is the current draw on this in an hour?
@aitorsierra9 жыл бұрын
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
@das2502509 жыл бұрын
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 ?
@raykent32118 жыл бұрын
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.
@MithiSevilla9 жыл бұрын
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
@a1fliema1fie9 жыл бұрын
As others have said , a while true loop and a single bit toggle is the fastest. For reference I got around 4MHz from an arduino uno. Also, I noticed you get a much cleaner signal if the usb power is supplied by a wall wart. Mty laptop usb produces an unacceptable amount of noise.
@leebolton92759 жыл бұрын
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!!
@JerryEricsson7 жыл бұрын
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.
@MilanKarakas8 жыл бұрын
The fastest possible output is 4 MHz for 16 MHz Atmega328P. But, it has 62.5 ns ON state, and three times that (three cycles, or 187.5 ns) OFF state (if one want equal ON and OFF state - out freq is 2.6666...7 MHz, so un-comment asm codes if needed): void setup(){ TIMSK0=0; //disable watchdog interrupt DDRB = DDRB | B00100000;//only pin13 (PB5) as output while(1){ PORTB=(1
@n3qxc7 жыл бұрын
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?
@hurterbe4 жыл бұрын
How do I read a complete port in a similar way that what you wrote to a port without using the Digital write function?
@robertw18716 жыл бұрын
You can use bitwise OR with a bitmask, this will set only the bit needed.
@hellterminator6 жыл бұрын
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.
@LynkedVideos8 жыл бұрын
Julian, you need only one statement in the main loop: PORTB ^= (1
@NormanNodDunbar4 жыл бұрын
Even better, writing 1 to the PINx register for an output pin, toggles it. PINB |= (1
@r3corpinformatica9 жыл бұрын
Julian, coud you please make the same video kind for the ESP 8266 ?
@NiCadHeliPilot8 жыл бұрын
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?
@davidkempton28949 жыл бұрын
Hey Julian, that was really interesting. Thanks.
@yoramstein7 жыл бұрын
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?
@JulianIlett7 жыл бұрын
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.
@MrSoulBack9 жыл бұрын
if you use a forloop inside the loop function it will work much faster. the loop function does some stuff every time it repeats itself.
@bwack9 жыл бұрын
Here is an improvement that Arduino IDE developers can improve. The MikroC compiler from MikroElectronica does compiletime optimizations. Does the Arduino IDE have a disassembler ? If so you can clearly see how a function call is compiled...
@aaaafaaaaf9 жыл бұрын
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.
@ArcAiN67 жыл бұрын
and now that i've watched the rest of the video, i see you've already figured that out :D
@malgailany9 жыл бұрын
Thanks Julian, good to know this kind of information.
@das2502509 жыл бұрын
Julin just a little note when showing the scope ..turning down ambient light makes the screen much sharper :_)
@JulianIlett9 жыл бұрын
+graham kaveman Thanks Graham. Reflections seem to be the biggest problem. But reducing ambient lighting (closing the blinds) would help that too.
@pedromms89089 жыл бұрын
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!
@TechBuild8 жыл бұрын
Which is the fastest and the slowest Arduino board?
@espenbgh25409 жыл бұрын
The glory of the Arduino isnøt all that glory and the 16 MHz througput isn't allways 16 MHz. Brilliant show Julian.
@JasperJanssen8 жыл бұрын
Doesn't atmega have a NOP for delay?
@therealmeisl56098 жыл бұрын
It does, and you can use it in the Arduino IDE as "_NOP();" It's a macro which gets translated straight to a machine nop which takes one clock cycle.
@GogogoFolowMe7 жыл бұрын
Very interesting, I was going to make these mesures, thanks for the vid !
@spikekent8 жыл бұрын
Wow! That was fascinating and very expertly explained for a novice like me.
@RWoody19959 жыл бұрын
Just gonna post this since you didn't mention it, you can use the direct manipulation method in a way that means you dont have to worry about changing all pins on the port at once if you do PORTB /= B00100000; rather than just =, it will only write 1 to the positions you write 1's into becuase it will take the current state of PORTB and OR it with the number you give it so any 0 stays 0, any 1 stays 1 and any 0 you want changed to 1 will become 1. Also for changing something from 1 to 0 you'd do PORTB &= ~(B00100000); and again it will take the state of PORTB and AND it with the complement of the number you give so whatever you put as 1 will turn to 0 and everything else stays as it was. I don't know if this would add much/any extra time to execute the line of code but it should still be faster than arduino functions.
@allanpatterson74716 жыл бұрын
1:00] 16m not k, thanks for sharing, they come in handy for replacing a few old custom ics made in late 70's early 80's.
@csbluechip9 жыл бұрын
Can you please supply URLs for the datasheets you are using; especially the ATmega Arduino pinout datasheet?
T Komoski Fantastic, Thank You ...I wonder if the ATmegaArduino pinout datasheet is something created by Julian?
@jope71379 жыл бұрын
csbluechip You know what's funny? If you type "ATmega Arduino pinout datasheet" into the Google search box, guess what you find?
@csbluechip9 жыл бұрын
Do you know what's even funnier? If you look at the circuit diagram for the nano v3 on arduino.cc it shows how all 32pins of this 28pin device are connected :)
@Relations999 жыл бұрын
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!
@sbern429 жыл бұрын
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.
@JulianIlett9 жыл бұрын
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 ;)
@AsafShahar9 жыл бұрын
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.
@sbern429 жыл бұрын
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.
@Relations999 жыл бұрын
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. ;)
@ChatNoirLe9 жыл бұрын
Even if you go into assembly on ATMEL not all the IO are the same speed, some are faster and some are slower. PIC's on the other hand are the same speed and generally faster, no multi-clock cycle turn on and turn off, generally...
@collingtech19 жыл бұрын
very good masterclass julian thanks for video , cheers
@makingthings2779 жыл бұрын
Very inturesting! Good in depth check!
@KiR_3d6 жыл бұрын
Wow, impressed! I guess you have a professor degree. Did they've used some improvements for the compiler? Three years passed... Probably somebody from the Arduino team is watching your videos constantly. They should know...