High-Power Control: Arduino + N-Channel MOSFET

Monday, March 5 th , 2012

Eventually you are going to find yourself holding a 12v solenoid, motor, or light and wondering “How the heck am I supposed to control this from my Arduino?” And we have covered this in the past. Today we are going to talk about another way of doing just that, this time with an N-Channel MOSFET metal–oxide–semiconductor field-effect transistor, specifically the RFP30N06LE MOSFET (You can pick these up from sparkfun). but you can use any N-Channel MOSFET 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.

First off, a MOSFET is a transistor, just a special kind.

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 Source, an Out called the Drain, and a Control called the Gate. When you send a HIGH signal to the gate (control pin), the transistor switches and allows current to flow from the source (in) to the drain (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 drain. When our arduino sends a HIGH signal to the transistor’s gate, it switches the transistor (connecting the drain and source) and completes the circuit for the motor, solenoid, or light.

More Information

If you want to know more, or actually know what is actually going on in there. Pete over at Sparkfun put out amazing video explaining MOSFETs for a solid 20min. Highly recommended.

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

This circuit is pretty simple. The only part that looks funny is the resistor. This is a pull-down resistor. The resistor holds the gate low when the arduino does not send a high signal. This is here incase the arduino comes loose, or the wiring is bad it will default to off. You don’t want this pin to ever be floating as it will trigger on and off.

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 MOSFET. 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 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.

Limitations

Transistors like the RFP30N06LE are really great for controlling high-power devices from your arduino, 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 MOSFETS have both a voltage and an amperage/current limitation. The RFP30N06LE can handle switching up to 60V, and the amperage is limited to 30A (with heat sink and proper wiring). 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 RFP30N06LEs, you can not solder them to the same heat-sink as the back is connected to the drain of the MOSFET, not the source. If you need to switch 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 MOSFET’s gate is connected to a PWM pin.

Code

You don’t really need code for this, you just send a HIGH signal to the gate 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).

//////////////////////////////////////////////////////////////////
//©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 3

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);
  }

}
Unless otherwise stated, this code is released under the MIT License – Please use, change and share it.

Video

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

Triple Axis Magnetometer HMC5883L + Arduino

Monday, February 27 th , 2012

One of the first articles we did was on the hmc6352 digital compass. Well this is his older brother (or younger but smarter). I really don’t know what to say about the HMC5883L other than it is a three axis magnetometer, so it is capable of sensing in 3 directions.

That doesn’t mean that it is tilt compensated, because you really don’t know how it is orientated when the reading comes in. For that, you would need to combine this with an accelerometer to do that. But this can get you one step closer. If you are looking at using this as a digital compass, make sure to read the following section.

Magnetic Declination

Something I found interesting and obvious once I thought about it, is that all compasses point to magnetic north, and not true north. The difference between them is called Magnetic declination. And how much they vary depends on where you are, and… when it is, because as weird as it is, it changes over time (awesome animation of that). You can look up your Magnetic declination here.

Hooking it up

Hooking you HMC5883L up to your arduino is pretty simple. The HMC5883L is an I2C device, a type 2-wire serial connection, so we 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. (The Arduino Leonardo will also be different). Other than these 2 lines, we just need to connect power(3.3v), ground and we are all set.

Code

The code for the HMC5883Lis a bit more complex than his single-axis brother, and the readings from it come in a few different forms, so we will be using a library to achieve this.

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

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.

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

Tilt Sensing with the RPI-1031 + Arduino

Tuesday, February 14 th , 2012

Once in a while something comes out that I think is going to be really awesome, but when you get it, it is just so so. Im sure you all know what I mean… But yeah… This is one of those.

The RPI-1031 available from sparkfun is a pretty simple (heck, it is dead simple) sensor for sensing when it is tilted. And it does this really well. But it seriously only does that. If it is not tilted, it freaks out and reports tilt anyways.

It actually just uses a metal ball that rolls around inside (you can hear it moving around when you tip it). Because of how it is made, the ball is always up against one side even when it is flat. Unfortunately this means you can never know the difference between a reading, and it being flat, only changes in reading.

Hooking it up

This is as simple as it gets I guess. Just power and ground, then connect the 2 digital pins and you are done. These 2 digital pins will output LOW/LOW, LOW/HIGH, HIGH/LOW and HIGH/HIGH depending on the wall it is touching. Again, even if it is flat, it is still touching a wall.

Code

The code for this guy is really simple, it just checks 2 pins, to see what side is being touched – The simple function just takes the 2 digital outputs and returns 0,1,2 or 3 depending on the side.

//For the RPI-1031 - http://www.sparkfun.com/products/10621 

int tilt_s1 = 2;
int tilt_s2 = 3;

void setup(){
 pinMode(tilt_s1, INPUT);
 pinMode(tilt_s2, INPUT);
 Serial.begin(9600);
}

void loop(){
  int position = getTiltPos();
  Serial.println(position);
  delay(200); //only here to slow down the serial output
}

int getTiltPosition(){
   int s1 = digitalRead(tilt_s1);
   int s2 = digitalRead(tilt_s2);
   return (s1 << 1) | s2; //bitwise math to combine the values
}
Unless otherwise stated, this code is released under the MIT License – Please use, change and share it.

« Older Entries
Newer Entries »