High-Power Control: Arduino + TIP120 Transistor

Tuesday, March 29 th , 2011

Up until now, we have talked about working with a lot of low-power devices. [[Sensors]], [[LED]]s, [[IC]]s, and the like are all capable of being powered directly from your Arduino, but as many awesome 5 and 3.3v [[components]] as there are, eventually you will find yourself holding a 12v [[solenoid]], [[motor]], or light and wondering “How the heck am I supposed to control this from my Arduino?” Well today we are going to talk about doing just that from a magical device know as a [[transistor]], specifically the [[TIP120 Darlington Transistor]].

The reason I’m covering this particular [[transistor]] is because it is readily available, and you can usually pick one up from Radio Shack, Adafruit or other local parts store in a jam, but you can use any NPN [[darlington transistor]] like the BD651 exactly the same way.

How this works

WARNING: I am about to simplify the crud out of this, so beware… it is here in an attempt to explain, in simple terms, what is going on.

If you don’t know transistors at all, they are 3 lead components that have 2 simple functions, to switch or amplify (in this example it is setup as a switch). You basically have an In called the Collector, an Out called the Emitter, and a Control called the Base. When you send a HIGH signal to the base (control pin), the transistor switches and allows current to flow from the collector (in) to the emitter (out).

So we connect it so that our motor, solenoid or light is connected to V+ but not ground (V-). Ground is connected to the transistor’s collector. When our arduino sends a HIGH signal to the transistor’s base, it switches the transistor (connecting the collector and emitter) and completes the circuit for the motor, solenoid, or light.

Hooking it up / What’s the diode used for?

This circuit is pretty simple. This type of [[transistor]] is switched by [[current]] and not [[voltage]], so we need to make sure to supply the correct current to the base to switch it, so a [[resistor]] is connected from the Arduino to the base to limit the [[current]] to the proper amount.

You can see that in 2 of the 3 illustrations, there is a [[diode]] parallel to the device we are powering. Any time you are powering a device with a [[coil]], such as a [[relay]], [[solenoid]], or [[motor]], you need this guy, and don’t leave home without it. What happens is when you stop powering the coil, a reverse [[voltage]], up to several hundred volts, spikes back. This only lasts a few microseconds, but it is enough to kill our transistor. So this [[diode]] (only allows current to pass one way) is normally facing the wrong direction and does nothing. But when that voltage spikes comes flowing the opposite direction, the diode allows it to flow back to the coil and not the [[transistor]]. We will need a diode fast enough to react to the kickback, and strong enough to take the load. A rectifier diode like the [[Diode Rectifier – 1A 50V |1N4001]] or SB560 should do the job. If you are looking for extra protection you could use an optoisolator between the Arduino and the transistor. An optoisolator optically isolates both sides (high and low power) of the circuit so the high-voltage can not possibly come back to the microcontroller.

Just make sure that protection [[diode]] is facing the correct way (stripe facing the V+ of device). If it is facing the wrong direction, the device you are trying to power will not work as the [[diode]] will just allow the current to bypass it.


[[Transistors]] like the [[TIP120 Darlington Transistor|TIP120]] are really great for controlling high-power devices from your [[microcontroller]], but they do have some limitations. This current configuration is only useful for switching [[DC]] current, so don’t try this with an [[AC]] source, also transistors have both a [[voltage]] and an [[amperage]]/current limitation. The TIP120 can handle switching up to 60V, and the amperage is limited to 5A, or up to 8A pulses of 300µs. I have managed to blow out one of these with a 5A load because of heat. Actually anything over a few amps, especially when the current is constant (like in a motor) and not short pulses, I would recommend using a heat-sink. I usually just solder a bent pice of metal to the back, just something to help dissipate the heat. Just note, if you are using more than one of the TIP120s, you can not solder them to the same heat-sink as the back is connected to the base of the transistor, not the emitter. If you need to switch more than 5A or AC, I would look at using a [[relay]] instead.

Fade it!

You know the [[PWM]] outputs on your Arduino? Yeah, the thing that allows you to analogWrite(pin, value). Well, [[PWM]] is not actually an [[analog]] output. The Arduino is actually pulsing (very quickly) between 0 and 5v so that the average [[voltage]] is somewhere in between 0 and 5. Because of this, the [[PWM]] can be extended through the [[transistor]] (the transistor can only turn on or off, but can do so very quickly) allowing us to fade lights or control the speed of a motor just like if they were connected directly to the Arduino. All you need to do in order to take advantage of this is make sure the [[TIP120 Darlington Transistor|TIP120]]’s base is connected to a [[PWM]] pin.


You don’t really need code for this, you just send a HIGH signal to the base pin, and BAM… it works. But I threw this together for you so you can test it fading with the PWM- This code fades in a sin wave like the video below. (only useful for a motor or light obviously).

[code lang=”arduino”]
//©2011 bildr
//Released under the MIT License – Please reuse change and share
//Simple code to output a PWM sine wave signal on pin 9

#define fadePin 9

void setup(){
pinMode(fadePin, OUTPUT);

void loop(){

for(int i = 0; i<360; i++){ //convert 0-360 angle to radian (needed for sin function) float rad = DEG_TO_RAD * i; //calculate sin of angle as number between 0 and 255 int sinOut = constrain((sin(rad) * 128) + 128, 0, 255); analogWrite(fadePin, sinOut); delay(15); } } [/code]


This video is showing the capabilities of PWM with the TIP120. The light, though it looks like a standard house light, is actually a 15W 12V DC light.

Extending this

This is something so basic that you will find your self with an abundance of things to use this with. Most recently I put this to use in a few places: I helped a local artist create an automatic morse code machine, helped a friend prototype a touch-based light dimmer (test video above), and at work, I use it for controlling 8 musical bells over the internet.

We need your help

bildr is in need of people interested in helping write any sort of blog post for bildr. If you think you would like to help bildr by writing something, supplying code or schematic, or just have an idea for an article you think should be written, please contact us at blog@bildr.org or let us know in the forum.

Tap, Tap, Drop. ADXL345 Accelerometer + Arduino

Wednesday, March 16 th , 2011

You know [[accelerometers]] right? Yeah… the things that tell your phone how it is orientated. But, believe it or not accelerometers are best suited for something other than sensing orientation. Excuse my oversimplification here, but this is going to help those who don’t know what’s going on. [[Accelerometers]] for all intents and purposes sense movement, so because gravity is pulling on the object it senses that and we can then determine orientation. Well… many actions like walking, throwing or jumping have particular movements associated with them, and a profile can be designed to recognize these movements. This is how your wii-mote can tell if your are bowling and not throwing, and your high-end pedometer knows the difference between running and walking. But we mortals often lack the insane math skills needed to write these movement profiles, and so we often just use our accelerometers as orientation sensors. BUT!!! What if your accelerometer did the heavy lifting for you? Well the [[ADXL345]] does just that. It is able to sense taps, double taps, free-fall, activity and inactivity all by just configuring some parameters. Im using the ADXL345 breakout board from sparkfun.

Out of the box, the [[ADXL345]] is an [[I2C]] 3-[[axis]] accelerometer with user selectable sensitivity and 10-13 bit resolution (depending on sensitivity). And… It is pretty decent all around, but were not really going to spend much time talking about boring stuff today. Today, we are talking about getting the special features of the ADXL345 up and running. (tap, double tap, free fall, activity and inactivity)

These special detection features have the ability to trigger 2 interrupt pins, making the pin go HIGH the moment one of the events is sensed. You can select what events to watch for, and what interupt pin to trigger when it is sensed (I had issues with INT2, it would not reset). You can take these interrupt pins and connect them to your Arduino to trigger an interrupt. An interrupt, when sensed on the Arduino, pauses the system instantly, even if it is in the middle of something, and responds to that interrupt how ever you have it setup before returning to the normal code. Like a police officer coming down the street with its lights on… Even if you have a green light, you stop and let them go. But using interrupts is a little beyond the scope of this article, so we are going to just keep checking for these actions in code and respond to them when we see them.

Hooking it up

The ADXL345 supports both [[SPI]] and [[I2C]], but we are just going to talk I2C here. I2C is a 2-wire serial connection, so you just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On your Arduino (everything but the mega) SDA is on analog pin 4, and SCL is on analog pin 5. On an arduino mega, SDA is digital 20, and SCL is digital 21.

Make sure both [[VCC]] and the CS pins on the sensor are connected to 3.3v. We connect CS to 3.3V to tell the sensor we will be using it as an [[I2C]] device, and not an [[SPI]] device.


Again, because this project is made up of many files, I am using bildr’s fancy bildrCode wrapper. All this example code will do for you now is output the name of the triggered action in the serial terminal. But I left the code in a state that should be pretty obvious how to extend it.

The special features require a lot of setup to get them working, but because this is bildr, we are going to start you off with working code, everything all setup, and spend a little bit explaining why certain things are how they are. To simplify everything in code, we will be using this Arduino library. But I have made a few small changes to it to make this a little easier to do, and to make it work a little better with other libraries, so the new library files are included in the code below.

To make this code work, before you load the code, or even open the Arduino program, we need to place the “adxl345” folder into your Arduino Library. If you don’t know where that is by default, Look to the right.

Once the ADXL345 folder is in there, you can just go ahead and open ADXL345_Example.pde in your Arduino software, and upload it.

The parameters that are set in the code should get you going, but you will most likely find that your project requires something different. Read through the setup code, there are a lot of things that can be changed, from the force needed to activate “activity”, the time before “inactivity” is triggered and the maximum length / minimum intensity of a tap. You can also completely turn off actions. I found that it was hard to trigger tap without triggering action, and double tap most often triggered tap as well. If you are up for it, the documentation on this chip is quite good, and explains a lot of the values in much greater detail (PDF).

Default Library Folder Location

On your Mac:: In (home directory)/Documents/Arduino/libraries
On your PC:: My Documents -> Arduino -> libraries
On your Linux box:: (home directory)/sketchbook/libraries


If you click the download button to the right of “Arduino” you can download the whole thing as a zip, so you dont need to copy all the files.


Extending this

Im sure you could come up with 101 ways to expand on this, but incase you need some help, here we go: What about a tap dance sensitive floor that caused lights to change with the rhythm of the dance? Shoes that shock you if you haven’t walked in 5 min. Something as simple as a ball that you throw up and only lights up on its way down… Anything you could think of that needs or could incorporate (in)activity, free-fall, or taps, you could find a way to use this to make it happen.

We need your help

bildr is in need of people interested in helping write any sort of blog post for bildr. If you think you would like to help bildr by writing something, supplying code or schematic, or just have an idea for an article you think should be written, please contact us at blog@bildr.org or let us know in the forum.

Are we getting close? Proximity Sensors + Arduino

Tuesday, March 8 th , 2011

In past tutorials, we have covered temperature, color, time, direction, but never distance or proximity. I think I strayed away from this because most of the lower cost proximity sensors are pretty drop-dead-simple to use and thought it might not be that useful. But the time has come, I’m writing about some distance/proximity sensors. While using them is technically simple, I have 3 pretty different sensors that all have pros/cons, and none of them would make a very suitable replacement for the others, so maybe this will help you choose the right one if you find yourself in need.

All 3 sensors will be outputting an [[analog]] [[voltage]] that we will be reading with our [[Arduino]]. The typical Arduino has 6 “Analog In” [[pins]] located on them. These analog inputs act just like a voltage meter, sensing the voltage on that pin, and are actually 10 [[bit]] [[ADC|Analog to digital converters]] ([[ADC]]s). The 10 bit part is the resolution of the ADC. 10bit, or 2^10 = 1024 values. That means that when we read the voltage on that pin, 0-5v value will be translated to between 0 (0V) and 1023(5V). Read our [[ADC|wiki article]] for more information on ADCs. This resolution limitation of the Arduino’s ADCs are a large part of the reason that [[analog]] sensors are often inferior to their [[digital]] counterparts. But, digital distance sensors are pretty expensive and hard to come buy. So…

The 3 sensors we will be going over are:
[[LV-EZ1|Maxbotix LV-EZ0 Ultrasonic Range Finder]]
[[Infrared Proximity Sensor – Sharp GP2Y0A21YK |Sharp GP2Y0A21YK Infrared Proximity Sensor]]
[[QRD1114|QRD1114 infrared emitter / Phototransistor combo]]

Maxbotix LV-EZ0

First up is the [[LV-EZ1|Maxbotix LV-EZ0]] because of the undeniable popularity of it. It is an ultrasonic range finder meaning that it uses a projected sound and measures how long it takes for the sound to bounce off of an object and come back. The sound is ultrasonic so it can not be heard.

Hooking it up

Hooking up the LV-EZ0 up is like day one of the Arduino tutorial. The only confusing part is that it has many output types. What you want is the “AN” pin. That is the [[analog]] output. Connect this to an analog input as seen in the illustration.

What it is good/bad for

The LV-EZ0’s range is really dependent on the size of the object – About 8ft for something the size of a finger, to over 20ft for something the size of a piece of paper. The best part is that the output is linear, so something that is 6ft way will output half that of something 12 ft away. This makes it very easy to read actual distance with it.

Maxbotix says the LV-EZ0 has a 1 inch resolution and a range of 0 – 254in meaning you could track something with 1in reliability over 254in of movement from the sensor. The reality is that this guy has trouble sensing distances under 1ft, and the output can be pretty shaky especially when trying to sense objects that are not perpendicular with the sensor.

Other options

Maxbotix makes a few different versions of this sensor with various beam widths. A narrow beam is better when you only want to know about objects directly in front of the sensor, and wide is better if you need to know if anything is near. Maxbotix also offers a more precise line (XL Series) that has 1cm accuracy, longer distance, and better noise suppression (makes the read out less shaky)

Sharp GP2Y0A21YK IR Proximity Sensor

The Sharp [[Infrared Proximity Sensor – Sharp GP2Y0A21YK |GP2Y0A21YK]] is an [[Infrared]] proximity Sensor. It shines a beam of [[IR]] light from an [[LED]], and measures the intensity of light that is bounced pack using a [[phototransistor]]. If you stare at the sensor, you can see one of the [[LED]]s glowing slightly red as some of the IR falls into the visible-light spectrum.

Hooking it up

Hooking up the GP2Y0A21YK up is, again, like day one of a Arduino tutorial. The only issue, the sensor does not come wired, so I recommend buying the pigtail to connect to it. Connect this just as seen in the illustration with the yellow wire to an analog input.

Because the GP2Y0A21YK is sensing the intensity of its reflected [[IR]] light, the sensor outputs near 0V when nothing is in front of it (approx. > 3ft), and ramps up as an object comes near. At about 4in, the reading from the Arduino is about 630.

What it is good/bad for

The GP2Y0A21YK is half the cost of the LV-EZ0, and incredibly simple to use, but there are a few downfalls that make it unsuitable for sensing distance reliably. Unlike the LV-EZ0, its output is not linear, so using this to read actual distance is difficult. Also because it is sensing IR, I have seen the output value thrown off by a TV remote shined directly into it. And lastly, once an object comes within 4in of the GP2Y0A21YK, the read values start to drop again down to around 430 (reading from the arduino) when an object is in contact with the sensor.

But with all the downfalls… if you just need a sensor so your robot does not to bump into walls, this should work as a great low-cost solution.

Other options

Sharp does makes a few different versions of this sensor suitable for different ranges (between 1.2in to 5ft).

QRD1114 IR emitted / Phototransistor

Last, but not least, is the [[QRD1114]]. The QRD1114 is actually 2 components, an [[IR]] transmitter, and a [[phototransistor]], held together in one package. This, like the [[GP2Y0A21YK]], works by shining an IR light and seeing how much of it bounces back. An object that is closer will bounce back more light than one far away. The QRD1114 is only able to sense objects between 0 and 3cm away. On the Arduino, the read value will be in between 600 and 1024.

Hooking it up

The QRD1114 is a little more complicated to hook up than the other two, but that is because this is actually just two raw components. But… it only requires two [[resistors]], (200-200ohm and a 4.7k – 5.6k ohm) to get it up and running. See the illustration on the right for exact wiring. The 4.7k – 5.6k resistor is a [[Pull Up Resistor|pull-up resistor]], and changing this will change the values read by the Arduino, but can be used to make it more or less sensitive.

What it is good/bad for

Like the Sharp sensor, this is not intended for use in determining exact distance, but for checking the proximity of objects under 3cm away. This sensor can also be used to detect white vs black surfaces because a white surface will reflect more light than a black surface resulting in a higher reading. Because of this, an array of these can be used for line detection and following.

I have quite successfully used this sensor for detecting when an object passes over a track to trigger an event. In fact, it is so fast at this detection, that properly setup, an object the size of your finger could be detected passing over it at about 10 times the speed you can flick your finger.

Because the sensor component simply measures IR intensity and is unaware of the light’s source, it is susceptible to false positives caused by outside sources that put off IR such as camera flashes, lamps, and even the sun. Just make sure you consider your environment before you use this as a mission critical component.

Other options

If you are looking at detecting lines alone, a better choice might be the [[QRE1113]] specifically designed for line sensing. If you are looking at sensing when an object passes by, and the object is small enough, you might also consider [[Photo_Interrupter_GP1A57HRJ00F|Photo Interrupter]]. These are great for coin drop detection etc.


The code for any of these sensors is incredibly simple, and at the core, is exactly the same. All this does is read value on analog pin 0 and output it via the serial terminal. This way you can see the values change as you put your hand in front of it. I added a small delay so that the output is a bit slower and easier to read. But this also slows the reaction speed. In your project, you will want to remove the delay for best results.

[code lang=”arduino”]
int sensorPin = 0; //analog pin 0

void setup(){

void loop(){
int val = analogRead(sensorPin);

//just to slow down the output – remove if trying to catch an object passing by


Extending this

Just because these sensors are designed to check proximity, don’t let your imagination be limited to that. Obviously you could easily make a digital tripwire with a few of these, but… The LV-EZ0 can accurately sense distance, and you can ascertain time passed with your Arduino, so you can also find speed of an object. In fact I have used a device that used 2 IR reflectance sensors and could track a marble at 80+ MPH passing by just by knowing the time and exact distance between them.

These are very simple devices, but don’t let that limit you to simple ideas. What about a jacket that alerts you when someone approaches behind you? Or dog door that only opens when the dog is near. I don’t know, and we’re not here to give you the idea, just supply the know-how. So make something crazy, and we’ll see you next week.

We need your help

bildr is in need of people interested in helping write any sort of blog post for bildr. If you think you would like to help bildr by writing something, supplying code or schematic, or just have an idea for an article you think should be written, please contact us at blog@bildr.org or let us know in the forum.

« Older Entries