3 Simple Ways to
Share What You Make

With Instructables you can share what you make with the world — and tap into an ever-growing community of creative experts.

PhotosPhotos

Share one or more photos of a project, recipe, or whatever you've made, quickly and easily.

Step by StepStep-By-Step

Share your step-by-step photos with text instructions of what you made so others can do it too!

VideoVideo

Share your how-to video. You'll need your embed code from a video site such as YouTube.

Arduino is Slow - and how to fix it!

Arduino is Slow - and how to fix it!
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 chips, using AVR Studio 4. The advantage of using these “true c” commands is that it does exactly what you tell it to do.
 
But before we get in to these commands, we must get familiar with port and pin definitions in the next step!

(If you predict you will like this instructable, feel free to vote for the Arduino contest!)
 
Remove these adsRemove these ads by Signing Up
 

Step 1The Truth about Pins

The Truth about Pins
Arduino users know that the pins are labeled as digital 0-13 and analog 0-5. The makers behind Arduino used this for simplicity. The actual ATMega chip’s pins are labeled differently, however. Each pin has an assigned letter and number. The numbers range from 0-7. For example, pins can be A0-A8, B0-B8, and so on. All of the AVR 8-bit pins are labeled this way.
 
To help you clarify which digital/analog pin corresponds to which AVR pin, see the chart below.
 
My Seeeduino has a LED built in on digial pin 13. So, looking at the chart, its real pin would be B5.
 
Next I will show you what the actual C command is.
« Previous StepDownload PDFView All StepsNext Step »
23 comments
Nov 13, 2011. 6:57 AMrcarvalho4 says:
It's better change just the part after the logic operator:

PORTB |= 0b00100000;
PORTB &= ~0b00000000;

If you don't use the logic operators, but just the equal "=" sign, all the pins are going to be set like the byte you sent, not just pin B5. In the case where you set B5 high, you would set all ohter B pins to low.
Apr 8, 2010. 9:45 AMn8hfi says:
Part of the reason this works is that the DigitalWrite() and DigitalRead() do some error checking before it sets the register bit--in particular, it checks and turns off PWM if it's enabled for that pin.  Directly accessing the bit yourself is fine, but you're also assuming responsibility for skipping the check.

This is pretty safe if your sketch is simple and doesn't do much multitasking or multiplexing of pins, but can get perilous if you've got a complex one.
Mar 21, 2010. 2:31 PMvilts says:
 I wonder why I get this error:

In function void loop():
Error: 'PB5' was not declared in this scope.

I use 0018 software.


I used form PORTB = B.....;

and it took 3808 vs 284 microseconds.

I'm trying to get TLC5945 communicating with arduino, no luck with digitalWrites, hopefully this version works.
Apr 7, 2010. 12:47 AMeewithmac says:
 I have the same problem. The example code is obviously missing something. Where and how should PB5 be declared? 

Me, I'm trying to PWM on all the pins of an Arduino Duemilanove to dim some LEDs. 
Jan 18, 2010. 10:15 AMjust_watching says:
Thanks this helped a lot becaus its the only way to programm the 16 extra pins on the Seeduino Mega
Dec 9, 2009. 3:19 PMzuixro says:
Thanks for this instructable. Not only does this save a lot of time, it also knocks the program size down quite a bit.  You can also you the registers DDRx an PINx (where x is the letter of the port) to change a port's input/output status, and to check what the input value is.
Nov 20, 2009. 10:06 AMghaon says:
 So do you then use the AVR Studio 4? 
Or how do you program an Arduino in this way?
Can you use the Arudino's usb ftdi connection?

Please elaborate. Thanks!
Nov 12, 2009. 7:20 AMfunlw65 says:
Maybe using this "Arduino" ?


Oct 26, 2009. 11:01 AMwholder says:
Actually, there is a very nice writeup on "Direct Port Manipulation" (which is the Arduino folk's name for what you are doing) on the Arduino site.  Here's the link:

  http://www.arduino.cc/en/Reference/PortManipulation

The description at the top of the page says "Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board."

Wayne
Oct 25, 2009. 11:17 AMWyoJustin says:
Nice tutorial.  You should enter it into the Arduino contest.
Oct 25, 2009. 5:10 AMgmoon says:
Some explanation of C "bitwise" operators might be helpful, too... And maybe break it down without using compound assignment ops first.

Here's my fav bitwise link: AVR bit tutorial

Other than that, it's a good 'ible...
Oct 24, 2009. 11:02 PMNerdz says:
How come you didnt you Hardware SPI instead of Bit Banging the commands to the PWM chip? I checked briefly and it seems it use SPI commands. Looking at the Atmega168 Data sheet, It Does have support for hardware SPI, and if you used hardware, it would much Much faster than bit Banging SPI Commands since you can usually get up to 20Mhz Data Transfer depending on your internal clock (or external, but usually it requires you to go with the max clock rate for the chip) since it would Free up the CPU to do other things.
Oct 25, 2009. 5:16 AMrichms says:
SPI uses the USART doesnt it? And thats pre-wired on the arduino to support the bootloader
Oct 25, 2009. 6:56 AMDantex says:
does this work for arduino mega? (chip is atmega1280
Oct 25, 2009. 6:18 AMmtbf0 says:
reading and writing pwm pins will also be somewhat slower than writing non-pwm pins.

hmmm, i notice that there's no longer any range checking on pin numbers.  although this speeds things up i wonder what havoc a pinMode or digitalWrite to some out of range value might wreak.
Oct 25, 2009. 5:36 AMflof says:
Good to know that there is such an overhead!
How does the ShiftOut() command compare to this? Looking at the arduino reference it seems to be dedicated for this task (if the SPI pins are available..)
Would be nice if someone posts some numbers, since i do not own an arduino to test with..

Oct 25, 2009. 1:27 AMwestfw says:
There's a pretty extensive discussion on pin-toggling on the arduino forums here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016


Pro

Get More Out of Instructables

Already have an Account?

close

All Steps Viewing
View all steps of an Instructable on the same page when you're a Pro Member.

Upgrade to Pro today!
21
Followers
9
Author:RazorConcepts
Check out razorconcepts.net for some projects.