Arduino Digital Output Drive vs. Direct-connected LEDs

What happens when you jam an LED into an Arduino digital output and turn it on?

Direct LED drive - no ballast resistor
Direct LED drive – no ballast resistor

This plot gives the load-line solution for that situation:

Arduino Pin Driver - Direct LED Load
Arduino Pin Driver – Direct LED Load

The dotted curve comes from Figure 29-22 of the ATmega168 datatsheet and shows the typical source current vs. voltage for a digital output pin on your favorite Arduino.

The cheerful colored curves show the current vs. voltage characteristics of some random LEDs, with data from the same curve tracer setup as those.

Given a particular LED directly connected between an Arduino output pin and circuit common (without the formality of a current-limiting ballast resistor), the intersection of the dotted output pin curve with the colored LED curve gives you the current & voltage at the pin. For example, the violet LED would operate at 4 V and 40 mA.

Some gotchas:

  • Typical 5 mm LEDs, of the sort one might use for this experiment, have a maximum DC current limit of 20 mA
  • Arduino output pins have an absolute maximum current limit of 40 mA

So all of the direct solutions drive too much current through the LED. Although the blue and violet LEDs don’t quite exceed the output pin limit, the others certainly do. Those old standby red & amber LEDs would have absurdly high intercepts, well beyond the limit of sanity, in the region where the data you see here breaks down, where the pin driver gives up and goes poof, not that that ever stopped anybody from trying.

You’ve probably seen somebody do it. Next time, aim ’em here in a non-confrontational manner… [grin]

My Arduino Survival Guide presentation has other info that may help that poor sweating Arduino survive. You don’t get my performance-art patter, but the pictures and captions should carry the tale…

As part of conjuring up this plot, I discovered that, for whatever reason, Gnuplot’s TrueType font rendering (via gdlib) no longer works in Xubuntu 12.04: the font name has no effect whatsoever, but the point size does.

The Gnuplot source code:

#-- overhead
export GDFONTPATH="/usr/share/fonts/truetype/msttcorefonts"
Pinfile="ATmega Pin Driver Data - Source.csv"
LEDfile="LED Data.csv"
base="Arduino Pin Driver - Direct LED Load"
echo Output file: ${Outfile}
echo Font: ${fontname}
#-- do it
gnuplot << EOF
#set term x11
set term png font "${fontname},18" size 950,600
set output "${Outfile}"
set title "${base}" font "${fontname},22"
set key noautotitles
unset mouse
set bmargin 4
set grid xtics ytics
set xlabel "Pin Voltage - V"
set format x "%4.1f"
set xrange [0:${vds_max}]
#set xtics 0,5
set mxtics 2
#set ytics nomirror autofreq
set ylabel "Pin Current - mA"
#set format y "%4.1f"
set yrange [0:80]
#set mytics 2
#set y2label "Drain Resistance - RDS - mohm"
#set y2tics nomirror autofreq ${rds_tics}
#set format y2 "%3.0f"
#set y2range [0:${rds_max}]
#set y2tics 32
#set rmargin 9
set datafile separator "\t"
set label "Pin IOH" at 3.0,70 center font "${fontname},18"
set label "Pin Abs Max" at 1.4,40 right font "${fontname},18"
set arrow from 1.5,40 to 4.75,40 lw 4 nohead
set label "LED Max" at 1.4,20 right font "${fontname},18"
set arrow from 1.5,20 to 4.75,20 lw 4 nohead
plot \
"${Pinfile}" using 1:3 with lines lt 0 lw 3 lc -1 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 0:0 with lines lw 3 lc 1 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 1:1 with lines lw 3 lc 2 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 2:2 with lines lw 3 lc 0 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 3:3 with lines lw 3 lc 4 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 4:4 with lines lw 3 lc 3 ,\
"${LEDfile}" using (\$5/1000):((\$1>0)?\$2/1000:NaN) index 5:5 with lines lw 3 lc 7

A few early risers got to see a completely broken listing, with all the quotes and brackets and suchlike reduced to the usual HTML escaped gibberish…