Subscribe to Make Magazine Today!

Good Instructable for the advanced folks out there, your code won’t be portable, but you’re advanced, so whatever :) RazorConcepts writes-

Arduino is slow? What? This instructable will show just how slow a part of Arduino is, and how to fix it. It’s true – more specifically, Arduino’s digitalWrite command takes a considerable amount of time. If you are just switching on a LED once or something, you won’t be able to notice it. However, I realized how slow it was while I was trying to use a TLC5947 PWM driver. That requires the microcontroller to shift in 288 bytes each time! Each byte required about 12 digitalWrites, for a total of 3456 digitalWrites each time I wanted to shift in new data to the TLC5947. How long did that take? 30 seconds of just digitalWrite! But there is a solution – using “true c” style commands, or what the AVR GCC (GNU C Compiler) uses. The brains behind Arduinos are ATMega168s or ATMega328s. The AVR community typically uses “true c” commands to program these c

  • Dale Wheat

    The instructable does a great job of explaining the mapping of digital and analog pins in Arduino-speak to the ports and bits of the underlying chip. Good job!

    The “bit value” functions _BV(), etc., have always seemed clumsy to me. Once upon a time, the AVR GCC compiler supported “Set Bit in I/O register” and “Clear Bit in I/O register” macros called sbi(port, bit) and cbi(port, bit). These emulated the AVR machine language instructions SBI and CBI, respectively. The macros were smart enough to tell when the I/O register was beyond the limited SBI and CBI address space and would substitute appropriate read+modify+write instruction sequences, which were not as fast as a single SBI or CBI instruction but still a LOT faster than the digitalWrite() Arduino function.

    Alas, these macros were deprecated a few years ago, mostly for being “non-portable”, which is true. The _BV() functions are portable and, to some, more self-explanatory in their function.

    For me, not so much. I re-wrote my own macros for SBI and CBI like this:

    #define sbi(port, bit) (port) |= (1 << (bit))
    #define cbi(port, bit) (port) &= ~(1 << (bit))

    Now I can set or reset a bit without having to either remember which logical operators to use or do the math in my head every time. I just have to remember where I keep these macro definitions… :D

    The next step is inline assembly programming, but the AVR porters of the GCC tools did not make this easy for us. They tried, bless their hearts, they tried.