Sunday, July 3, 2016

BONUS! Driving a High power RGB LED from Arduino only.

While I was working on the hardware side of the Sound Reactive LED lights tutorial, my friend decided to make one for his room as well. So hopefully I'll manage some better photos of the build process for that.

In the meantime, my Linux work laptop decided that I was being too productive in my vacations and decided that I should go on a break. Hence, I am struck with just one laptop now. I know, I sound crazy, but once you have used 2 computers simultaneously, having just one makes you feel restricted. Same goes for those insanely cool multi-monitor rigs.

Anyhow.

Along with all those components needed for the sound reactive lights, I had also ordered one small little thing. A 10 Watt RGB LED Module. These are classified as high power LEDs and it is required to use a proper heat sink with them as they get very hot. I used to wonder how hot can a 90% efficient device can be, so I tried to power it without a heat sink.
At 300mA for 3-4 seconds, the back plate of the LED got so hot that it burned my finger when I touched it. WOW!
Not to mention that these things are INSANELY BRIGHT! You cannot really directly look at them without hurting your eyes and going blind for a second afterward. And that is for a 10 watt LED. 100 watt LED's are also available and I can only imagine how bright those are.

Why did I buy one? I was curious.

The main issue with these high power LED's is that they require special methods to receive power, And are very sensitive to the power input. That is why you cannot simply attach them to a battery to make them work. Nope, you need a Constant current power supply to get the most from them.

Theory Time!

LED stands for Light Emitting Diode. It's a DIODE.
Remember Ohm's law? Stating that "For a given voltage, the current flowing in the circuit is dependent on the resistance" or mathematically V=I*R. Basic electrical law.

Also, remember that Diodes and other semiconductor devices do not obey the Ohm's law. What that means is that for a material obeying ohm's law, the V-I graph is linear. For something like a semiconductor, it's non-linear.

Values are not important. The nature of the curve is, which is linear here. This is for  normal resistance, following Ohm's Law


See the graphs on the right. Non-linear, and different for different colors.
The Dashed line represents the max efficiency current. Hence, constant current power supplies are required.



So what's the big deal? Well, for diodes, a small voltage change can cause a huge increase in the current. And as that current increases a certain limit, The diode junction is bound to get damaged.

That is the reason there always is a resistance in series with the LED, usually of a value of around 150 ohms, whenever an LED is to be used with Arduino or a Raspberry Pi. It limits the current flowing via the LED and protects both the LED and the board, by protecting from over-current.

Simple resistor, used to limit current to the LED


Neat solution. But this works only for low power LED's, typically those 3-5mm LED bulbs. What if we use a resistor to regulate current for a high power, say 3 watt LED? You need a big resistor. And I don't mean a big value resistor... I mean a resistor that can dissipate quite a lot of heat, without getting destroyed. Normal electronics resistance are 1/4 of a watt. For a 3 Watt LED, you need roughly a 5 Watt resistor. So to drive 3 watt LED, you end up wasting another 5 watts as heat. That's not very efficient, is it?

RGB LED strips have small resistance in the strips itself. hence we can simply connect it to a battery and it will work fine. That is not the case for high-power LED modules. They just have the diodes in them and no resistance is included, which makes it necessary to have a high power constant current source to power them. And you cannot simply connect them to a battery. They will burn out within a couple of seconds. Even more importantly, for RGB LED's, there are different forward voltages for different colors. For example, the LED I got had 4V for Red, 7V for blue and 9V for green. Those are the forward voltages. The forward currents were 350mA for each color. At such high current, there is no way that I can simply put a resistance in there.

Another solution is to use something like an LM317 as a constant current power source. That's a neat idea, but again it gets limited to about 100mA of constant current. Anything over that, and you will need a heatsink on the LM317 and again a high watt resistance. So that's also not a viable solution.

Yet another solution, one that is used commercially in LED light bulbs on mains is to use a DC Buck converter with an Op-Amp to get a constant current source. Such breakout boards are easily available on Amazon and EBay and have a precision potentiometer to tune the voltage and the current output of the buck. They can also supply around 3 amperes of current without the need of a heat sink. All this makes them ideal for constant lighting application, where there is just one color LED and that too is maintained at a constant brightness, just like a normal light bulb. For RGB LEDs, you need 3 of them, and there is no way to control the brightness other than manually changing the resistance values, and even then, most of the RGB LEDs won't work because they are the common anode type, that is single +ve and 3 -ve lines per color.

Commercial solution for Driving LEDs
Notice that Voltage is variable, but the current is fixed at 300mA. That means this supply can work with 3-5 watt LEDs


So it seems that if you want to drive an RGB LED, on a budget (I AM ALWAYS ON A BUDGET), there is no easy way to do so....  or is there?

There is. A very simple way. So simple that I did not even think of it.
The answer yet again was PWM.

So I loaded up the Arduino, connected the MOSFETs and the potentiometers, wrote a simple code to change the duty cycle of the PWM pulse as per the value from the potentiometer, and hooked up everything to my 12V 300W ATX power supply.

I used the following:-

  • Arduino Nano
  • 3X IRFZ44N MOSFETs
  • 3X 10kOhm Variable Resistance
  • 10 Watt RGB LED Common Anode (+ve)
Here is the final circuit diagram. P.S. I'm new to Fritzing. Yellow Wire is +12VDC. Black is ground.


The LED module is at the top. I could not find something similar to what I have, but the connections are similar..


You might think that connecting a 7V LED to a 12V line capable of pushing nearly 20A of current will surely blow out the LED. You are correct, but what you are missing is that it's not connected directly. There is a MOSFET in between that will regulate the power delivered to the LED. Of course, make a direct connection if you wish to see smoke and stuff.

Since I had no idea that how much of the duty cycle will result in how much current, I added a serial monitor output that gave me the duty cycle of the PWM on the screen of my laptop. That way, I could see the duty cycle of the PWM.

Here is the sample code, with the fixed values for my case. Yours may vary. Check accordingly.

int redled = 9;     //red channel to D9 of arduino
int greenled = 10;    //green to D10
int blueled = 11;    //blue to D11

int redPin = 0;        //red pot to A0
int greenPin = 1;       //green pot to A1
int bluePin = 2;        //blue pot to A3
int pred,pgreen,pblue,lred,lgreen,lblue;         // variable to store the read value

void setup()
{

  Serial.begin(9600);
  
  pinMode(redled, OUTPUT);   // sets the pin as output
  pinMode(greenled, OUTPUT);
  pinMode(blueled, OUTPUT);
}
void loop()
{

  pred = analogRead(redPin);    //reads the ADC values coming via the pots
  pgreen = analogRead(greenPin);
  pblue = analogRead(bluePin);

  lred = map(pred,0,1023,0,90);     //maps the ADC to pwm duty cycle
  lgreen = map(pgreen,0,1023,0,190);   //0,1023 is the adc values
  lblue = map(pblue,0,1023,0,145);      //0,90/190/145 are the pwm values

  analogWrite(redled, lred);      //output to the Digital pins for PWM
  analogWrite(greenled, lgreen);
  analogWrite(blueled, lblue);

  Serial.println(lred);      //prints the PWM duty cycle in serial monitor
  //Serial.println(".");
  Serial.println(lgreen);
  //Serial.println(".");
  Serial.println(lblue);
  Serial.println("  ");

delay(100);
}



Next, I simply connected my Multimeter in series with every color channel one by one and started to increase the duty cycle by rotating the pots. As soon as the current reached 320mA, I recorded the PWM Duty cycle for that color, via the serial monitor of Arduino.

Completed circuit. A bit of mess, but minimalist.
Proper heatsink with thermal conduction paste in between is a MUST!

The net result

The front of the LED is perpendicular from me, Its daytime, and you can still see lens flares here.
And this is 1/3rd the brightness.


Repeating this for every color, I found the maximum duty cycles for red, green and blue. Next, I simply replaced the maximum duty cycle of 255 in the Arduino code to the values I found above.

Upload the updated code, and it's done! Since the PWM signal is now limiting the maximum current using the software, I can directly power the RGB LED without any complex circuit, and still, operate the LED at full intensity. There is no heat loss, and the whole system works on 12V, and I can even select what color I want, by rotating the pots. Simple!

Did you enjoy reading this? Thinking of trying it out? Some mistakes here and there? Do let me know! Feedback is much appreciated, as always.

Have fun!