Archive for February, 2011
Designing RGB LED Shield – 3. Power and Temp sensor
2
Independent power for the shield
Maximum input voltage of the Arduino is 20V. Recommended maximum voltage is 12V. Since the shield is buck LED driver, you can drive only 3 LEDs per channel with 12V. Otherwise, you need to supply two different voltage inputs: one for Arduino and ICs on the shield, the other for LEDs. Because of nature of linear voltage regulator, you can not use high input voltage for 5V ouput. The shield consume about 100mA of 5V for powering LT3496, Attiny85, MCP4728, and optional temperature sensor. 100mA is not that much, but none of small linear voltage regulator like 7805 can output 5V from 40V at 100mA. Because there is a 35V difference between input and output voltage, voltage regulator will dissipate 3.5W of heat at 100mA.
To have just one power for both Arduino and the shield, only choice left was another switching voltage regulator which have high voltage input. I found National LM2841 is good enough and simple to use. LM2841 is 42V input, 300mA switching IC. It is a bit more expensive that I hoped. Cheaper yet old type of switching ICs require larger foot print which I don’t have.
With the LM2841, 100mA is used for powering the shield. Rest 200mA can be used to power up Arduino. It also allow the shield is operated independently from Arduino.
Temperature sensor for LED and the shield
This is the one that I didn’t put it in my initial design and is totally optional. Some people want to monitor LED temperature, since temperature of LED is the most important factor that affect life time, color, current, voltage drop and so on. Maintaining LED temperature within acceptable range is mostly done by current limit and heat sink. When you can not have big enough heat sink or operates LEDs at high ambient temperature, you can maintain temperature by dynamically lower the current to LEDs.
Monitoring LED temperature can be done by putting temperature sensor close to the led. If the sensor is cheap enough, you can just glue the sensor close to the LED using thermal epoxy wherever you want. However temperature sensors are not cheap. Cheapest one is still cost about $1. You can not glue it every LED panel you have. The real cheap temperature sensor turn out to be transistors. It is cheap enough you can just glue them anywhere you want, and monitor the temperature when you need by connecting to Arduino. The most commonly used transistor for temperature sensor is 2N3906 which is a basic and common transistor. You can find them anywhere and is very cheap. You can buy 100 of 2N3906 at $4.
A bad side of using transistor as a temperature sensor is that you can not connect it directly to Arduino. It requires circuit for it. Luckily companies make lots of temperature sensor that utilize 2N3906 as a remote sensor. You don’t need any complex circuit. So I decide to put Texas instrument TMP421 on the shield.
TI TMP421 is a I2C temperature sensor. Once again I don’t use more than 2 pins from Arduino, those two I2C pins are still available for any I2C devices. TMP421 has an internal temperature sensor and one remote sensor input. On the shield, TMP421 is located close to LT3496, so I can estimate the IC temperature. Remote sensor input is pinned out right next to the LED connector, so you can connect to 2N3906 on LED board.
Designing RGB LED Shield – 2. Dimming LEDs
2Dimming LEDs is an important feature in powering LEDs. It is especially critical when you want to mix red, green, and blue to get color you want. As I posted before, there are two dimming methods, analog dimming and PWM dimming. Advantages and disadvantages of each were described before as well. http://neuroelec.com/2011/02/led-dimming-methods/
In here, let me tell you how I implement two dimming methods in the shield.
PWM dimming
PWM dimming is achieved by fast turn on and off. Depending on how long you turn on, brightness of LED is determined. Since the pulse of PWM signal is short, human normally don’t notice the turn on and off at higher than 100Hz. Dimming ratio is determined by turn on and off speed of LED driver. If LED driver can turn on and off LEDs within 1us, 1:3000 dimming ratio can be achieved at 100-150Hz PWM signal as long as PWM signal has a such precision.
Implementation of PWM can be simple, since Arduino can generate PWM. All I need to do is connect PWM output pins from Arduino to LT3496 PWM input pins. There is two problems with that. First one is Arduino PWM has two different frequency depending on pins(500Hz and 1KHz). Default frequency is a bit high and PWM signal is 8 bit resolution. So, dimming ratio you can get is 1:256. Second, more important one is there are only 6 hardware PWM pins in an Arduino which limit the number of shield can be stacked.
I really want to have shields to be stacked more than two. So I decide to put serial controlled PWM signal generator, ATTINY85, small and cheap AVR microcontroller. Attiny is is quite popular for this kind of things. As you may know there is a quite popular product, BlinkM is based on Atttiny. The idea is generating PWM signal from Attiny which communicate with Arduino by I2C protocol. The beauty of I2C is many devices can be controlled in a single bus which use 2 pins (A4, A5) in Arduino. So It does not matter how many shields are stacked, with just two pins we can control as many shield we want. I2C bus use 7 bit address so theoretically 128 shield can be stacked. In practice, maybe 20 stacked shields are maximum due to the rated current of stackable pins. If you independently power the shields, 100 may be OK.
Analog dimming
Analog dimming is not a popular method for dimming LED. Because of disadvantages that I describe before as well as requirement of adjustable voltage input. Many LED driver offer pins that limit the current flow to LED. Maximum current is set by current sense resistor, and driver can lower the limit by current adjust pin which normally take certain voltage. In LT3496, There are CTRL pins to limit the current. If the voltage to the pin is > 1V, the driver output maximum current set by current sense resistor. If voltage to the pin is < 1, the driver linearly decrease the output current. For fixed current limit, it is normally just tied to the internal voltage reference pin. Some led driver board left a spot for additional current sense resistor to lower the current limit or simple jumpers. More flexible driver boards have a trimmer or potentiometer to adjust current limit.
Ultimate flexibility on current limit can be achieved by either digital potentiometer or DAC. By using one of those not only you have freedom on current limit adjustment but also you have possibility of analog dimming. Since DigitalPot and DAC adjust output fast, it can be used for dynamic current adjustment.
As you see in my first post, I initially use digital potentiometer, AD5254 along with a resistor. It is basically variable voltage dividers. AD5254 is four channel pot and has eeprom to save the settings. Main problems of this approach are output voltage is vulnerable to input voltage change and accuracy of the resistors. Input voltage can varies in some extent. Also total resistance of the potentiometer is not accurate and different on each channels. To correct this problem, I need to put more components and make the circuit complicated. So I dropped the digital potentiometer. Instead looking into a DAC. There were three reasons why I chose AD5254. It is 8 bit potentiometer which is quite high resolution for potentiometer. It use I2C protocol, so I don’t need to waste any more Arduino pins. People who don’t need analog dimming, they can set current value into EEPROM, and forget about it. AD5254 read the values from EEPROM when powering up. Finding a DAC that has all those good things was not easy. Particularly DAC with the EEPROM is rare. Luckily, I found a perfect DAC for this. Microchip MCP4728 is I2C quad 12 bit DAC with EERPOM. Everything that I have in AD5254 with higher resolution and faster output. Even Availability and price was better. What can I ask more?
Three out of four pins are connected to CTRL pins of LT3496, one is connected to frequency adjustment pin. Now, Arduino control current limit of three channel independently and operating frequency. EEPROM of MCP4728 can store settings. Also, MCP4728 adjust current output within 1ms which is more than enough for analog dimming. Since 1ms adjustment time result in 1000Hz, you can even make analog dimming to pseudo-PWM.
MCP4728 has a programmable address feature. Users can set I2C slave address into EEPROM without physical jumper changes. Detailed explanation was posted before: http://neuroelec.com/2011/02/soft-i2c-and-programmable-i2c-address/
If you use analog dimming, maximum stackable shields are 8, since MCP4728 allow 8 programmable addresses.
Designing RGB LED Shield – 1. LED Driver
6
I will start to write why I chose particular chips and components while I designed the shield. It will be a expanded version of my first post. First part of the writing is about LED driver which is the part that I spent majority of time during development.
A primary reason for designing the shield was that I want to control high power RGB LEDs with the Arduino. There are many chips specifically designed as LED driver from many different companies. I need three independent channels to mix red, green, blue light to get any color I want.
A most common type of high power LED is 350mA one. These day, maximum current of high power LED is going higher and higher. Still common and easy to source types are 350mA and 700mA. So I looked at the LED driver chips that can power up to 700mA LEDs. Then, I found LT3496 from Linear Tech.
LT3496 is a just perfect chip for my designing goal. It has 45V, 1A internal switch that can drive up to 750mA. Best of all is three independent channels in a single chip which minimize the circuit and foot print. Since it can take up to 45V, it can drive 10 LEDs per channel, total 30 LEDs from a single chip.
Now, let’s take a look at what is LED driver is. LEDs need to be operated at constant current, otherwise they burn out quickly. LED driver is essentially a constant current power supply which can be linear mode or switching mode. Switching mode LED driver is a bit difficult to design, but it is way more flexible and efficient especially when it is going to drive different number of LEDs. So most of LED drivers are constant current switching power supply. Main differences between regular voltage regulated switching power supply and LED driver are current control and dimming circuit for LED brightness control. Dimming LED can be achieved by varying current limit or PWM input. Depending on how a driver circuit is designed, both of dimming methods can be implemented. Since I want to have RGB color mixing, dimming LED is a essential feature to have. I will write more about how I implement both dimming methods in a separate post.
In here, I will focusing on current mode switching power design. Constant current mode is achieved by regulating output current instead of voltage. Current monitoring is done by measuring voltage drop across a small value resistor (called current sensing resistor). There is a voltage drop across the resistor depending how much current flow. It is Ohm’s law. For example, when 1A current flow across a 0.1 ohm resistor, the voltage drop across the resistor is 1A x 0.1 ohm = 0.1V, 100mV (V = I x R). The driver monitor the voltage drop and make it constant. Rest of the part is regular switching power supply.
Basic components for switching power are switch, inductor, diode and input/output capacitors. One important factor of the design is switching frequency, how fast switch will turn on and off. Switching frequency is normally hundreds KHz to a few MHz. With high frequency switching, low value of inductor and capacitors can be used. So overall foot print of circuit is small and components are cheaper. But high frequency operation is not as efficient as lower frequency operation. Also switch itself dissipate more heat at higher frequency switching. Even though switching power is quite efficient, at high power output, switch will dissipate a lot of heat. Compromise between size/cost and efficiency/heat has to be made.
LT3496 operates from 330KHz to 2.1MHz. Linear tech’s reference design for the LT3496 runs normally at 2.1MHz. So the design is small and has low cost components. If input voltage and output voltage (number of LEDs) is fixed, you can still achieve relatively high efficiency. However if you don’t know or input and output voltage varies, it is very difficult make a circuit efficient at high operation frequency. Since I don’t know how many LEDs and what input voltage people will use with the shield, I can not optimize the circuit for a particular configuration.
To have flexibility of operation frequency, it is require to have high value inductor, which means bigger size, higher cost. The higher the inductance of the inductor, lower the ripple current to LEDs, lower minimum operation frequency. Among the same value inductors, bigger size inductor normally have higher current rate and lower DCR (resistance). Low DCR is important since it affects efficiency and amount of heat dissipation from the inductor. At high frequency operation, 10-15uH is normally good enough. For the large range of input and output voltages, I chose high value inductor, 47uH rated 1.5A. Rated amp looks overkill, but for 700mA operation at least 1A inductor is required and high amp rated inductor have low DCR. With the 47uH inductor, operation frequency can be as low as 330KHz depending on input and output voltage. Because of low ripple, output capacitor can be small which also helps for higher dimming ratio as well.
LT3496 can be configure for buck, boost, buck/boost design. In buck design, input voltage has to be higher than output voltage. However, it is most efficient and simple as well as allows high current output.
the final design of the LED driver handles LEDs pretty well. It has good current regulation, wide operation frequency, modest heat dissipation, low current ripples.
Later, I will post a page that summarize the appropriate operation frequency and input voltage depending on output voltage (number of LEDs) and a spread sheet that calculate recommended frequency and input voltage ranges.
Soft I2C and Programmable I2C address
5While writing the mcp4728 library, one of most difficult thing was implementing programmable I2C address.
Single I2C bus can be used to connect multiple I2C devices, so addressing a specific device on the bus require a specific address for the device. Normal I2C devices have couple of pins for selectable address. Address of device is determined by whether address pins (ADx) is ground or VCC. There are some devices like mcp4728 has a advanced way of selectable address. Without physical pins, their address can be programmed and stored in EEPROM of chip. I love this feature of mcp4728, since it allow to stack the shield without physical jumpers.
Microchip’s implementation of programmable address is slightly non-standard, because it require another pin other than two I2C pins. While I understand why they did this way, it make a bit difficult to implement in arduino library. It is not because of requirement of third pin, but because of critical timing of pin latch. Let’s take a look at datasheet how programmable address works.
As you see, LDAC pin need to be latched between 8th and 9th clock. The problem was AVR’s hardware I2C don’t allow me to do it. AVR’s TWI register return it’s status after it receive the ACK from slave device. There was no way me to know when to latch, since TWI register only return status after 9th clock (ACK). So, I need to look for Software I2C library (bit-bang).
There are couple of software I2C library for arduino. I found that SoftI2C from fat16lib is most useful for this.
http://forums.adafruit.com/viewtopic.php?f=25&t=13722
Also, simple logic logger for arduino was quite handy for debugging.
http://jdesbonnet.blogspot.com/2010/05/using-arduino-duemilanove-as-quick-and.html
Dotted blue line show what I can do with wire library of arduino. Notice LDAC latch after ACK ( 9th clcok).
By modifying softI2C library, I was able to latch LDAC pin between 8th and 9th clock.
It is included in mcp4728 library and you can find modified SoftI2C library from google code.
http://code.google.com/p/neuroelec/source/browse/#svn%2Ftrunk%2FSoftI2cMaster
Arduino sketch for reading and writing address of mcp4728.
LED dimming methods
1Dimming LED is controlling brightness of light. Especially, when you are using RGB led to make mixed color, it is very important to have a good dimming method.
There are basically two dimming methods for LED: analog dimming and PWM dimming.
Here are the summary of each
Analog dimming
- control current to led
- better energy efficacy.
- color of light change
- light output is non-linear to current to led
PWM dimming
- control pulse width (quickly turn on / off)
- efficiency of led driver get lower at low PWM %
- color of light relatively constant
- light output is linear to PWM
You can find details from following article.
www.lightingresearch.org/programs/solidstate/pdf/Gu-SPIE6337-17.pdf
Here is a video showing two different methods on oscilloscope with high power RGB led shield.
HP RGB LED Shield Schemiatics and Design
0I am releasing schemiatics and board design of High Power RGB LED Shield under the Creative Commons Attribution-ShareAlike 3.0.
So, that should make the shield open source hardware
You can find eagle cad files, png, pdf of schematic and board design from google code.
http://code.google.com/p/neuroelec/source/browse/trunk/#trunk%2FHP_RGB_LED_Shield
HP RGB LED Shield for Arduino demonstration
0Here is a brief explanation and demonstration of the shield. I will post lots of details of it soon as well.
AD5254 example for arduino
0Even though I abandon ad5254, it is a nice digital potentiometer to use.
In case, anyone want to need. Here is a example code with all functions that ad5254 support.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
int readAllRDAC()
{
Wire.beginTransmission(0x2c); // transmit to device U1 (0x2c or hex for 0101100)
Wire.send(0x00);
Wire.endTransmission();
Wire.requestFrom(0x2c, 4);
int rdacnum = 0;
while(Wire.available()) // slave may send less than requested
{
byte rdac = Wire.receive(); // receive a byte as character
Serial.print("RDAC");
Serial.print(rdacnum,DEC);
Serial.print(" = ");
Serial.print(rdac,DEC); // print the character
Serial.print(" ");
rdacnum++;
}
Serial.println(" ");
}
byte readRDAC(int address)
{
Wire.beginTransmission(0x2c); // transmit to device U1 (0x2c or hex for 0101100)
Wire.send(address);
Wire.endTransmission();
Wire.requestFrom(0x2c, 1);
byte rdac;
if(Wire.available()) { // slave may send less than requested
rdac = Wire.receive(); // receive a byte as character
}
return (rdac);
}
void readAllEEMEM()
{
Wire.beginTransmission(0x2c); // transmit to device U1 (0x2c or hex for 0101100)
Wire.send(0x20);
Wire.endTransmission();
Wire.requestFrom(0x2c, 4);
int eemnum = 0;
while(Wire.available()) // slave may send less than requested
{
byte eem = Wire.receive(); // receive a byte as character
Serial.print("EEMEM");
Serial.print(eemnum,DEC);
Serial.print(" = ");
Serial.print(eem,DEC); // print the character
Serial.print(" ");
eemnum++;
}
Serial.println(" ");
}
byte readEEMEM(int address)
{
address = address + 32;
Wire.beginTransmission(0x2c); // transmit to device U1 (0x2c or hex for 0101100)
Wire.send(address);
Wire.endTransmission();
Wire.requestFrom(0x2c, 1);
byte eem;
while(Wire.available()) // slave may send less than requested
{
eem = Wire.receive(); // receive a byte as character
}
return (eem);
}
void RDACWrite(int address, int value) {
Wire.beginTransmission(0x2c);
Wire.send(address); // sends instruction byte to RDAC1 (0x01 or hex for 0000001)
Wire.send(value);
Wire.endTransmission();
}
void loop()
{
readAllRDAC();
byte rdac = readRDAC(1);
Serial.println(rdac,DEC);
readAllEEMEM();
byte eem = readEEMEM(1);
Serial.println(eem,DEC);
delay(4000); // time delay to see resistance values change via multimete
}
mcp4728 library for arduino
mcp4728 is microchip I2C 4 channel DAC with eeprom.
I write a library for mcp4728 because I replace ad5254 to mcp4728 in the newer version of HP RGB LED Shield that I will post later.
It is basically 4 channel version of mcp4725 ( you can find the break out board from sparkfun). If you want to have mcp4725, let me know. I will write a library.
Basic spec of mcp4728.
- Quad 12-bit voltage output Digital-to-Analog Convertor (DAC)
- I2C communication with programmable address.
- Internal or External voltage reference
- EEPROM for default values.
Documentation
I did not fully document the source code yet. Example files have description for functions.
Here is a part of example file. full example pde code
#include <Wire.h>
#include “mcp4728.h”void setup()
{
Serial.begin(9600); // initialize serial interface for print()
dac.begin(); // initialize i2c interface}
void loop()
{/*
Basic analog writing to DAC
*/dac.analogWrite(500,500,500,500); // write to input register of DAC four channel (channel 0-3) together. Value 0-4095
dac.analogWrite(0,700); // write to input register of a DAC. Channel 0-3, Value 0-4095
int value = dac.getValue(0); // get current input register value of channel 0
Serial.print(“input register value of channel 0 = “);
Serial.println(value, DEC); // serial print of valuedac.voutWrite(1.8, 1.8, 1.8, 1.8) // write to input register of DAC. Value (V < VDD)
dac.voutWrite(2, 1.6) // write to input register of DAC. Channel 0 – 3, Value (V < VDD)
float vout = dac.getVout(1); // get current voltage out of channel 1
Serial.print(“Voltage out of channel 1 = “);
Serial.println(vout, DEC); // serial print of value}
Source code
http://code.google.com/p/neuroelec/
Download
New blog with new domain
It is been two month without update. I have finally finish all things regarding High power led shield for arduino.
I will update what I have been working on so far.





Recent Comments