Who has not happened to note that wonderful breathing led effect present on some electronic devices?
There are makers all over the world equipped with oscilloscope tried to do reverse engingering to find the algorithm and turn it into an Arduino sketch. The problem lies in the fact that most of the codes found in the network have two defects: the first is that such algorithms do not contain a function but a series of pre-calculated values that do not make the effect smooth, while the second resides in the fact that often these codes are blocking, making use of delay and therefore do not permit the correct execution of the remaining code inside of the sketch.
Ispired by the Sean Voisen’s post who find the function defining the PWM values to drive the LED, I made some changes and tests to make it non-blocking and to make it work in background allowing execution to other code.
The end result is the following:
The connection is obviously as for any other LEDs and the system is capable of driving even power LEDs or LED strip, through appropriate transistor or MOSFET (See: Driving a LED Strip with Arduino)
The Arduino code is the following:
/*
NonBlockingBreathingLed 0.1
by Luca Soltoggio - 2015
12 May 2015
http://www.arduinoelettronica.com/
https://arduinoelectronics.wordpress.com/
http://minibianpi.wodpress.com/
Use a exp + sin function to recreate a
non-blocking breathing led effect
Released under GPL v.2 license
*/
#include <math.h>
#define ledPin 11
int i=0;
int breathe_delay = 15; // delay between loops
unsigned long breathe_time = millis();
void setup()
{
}
void loop()
{
nonBlockingBreath(); // call the nonblocking function
// yourOtherCodeHere();
}
void nonBlockingBreath()
{
if( (breathe_time + breathe_delay) < millis() ){
breathe_time = millis();
float val = (exp(sin(i/2000.0*PI*10)) - 0.36787944)*108.0;
// this is the math function recreating the effect
analogWrite(ledPin, val); // PWM
i=i+1;
}
}
Finally after a long absence, in which I was immersed in the final realization of this project, I did it!
After months of planning, studies, research and other obstacles, the RGB LED Lamp 1.0 by Toggio is reality.
Here’s the video showing the final result obtained:
And now a brief history.
One of the things that attracted me the most when I first heard of Arduino, was light, and in particular I have always dreamed of achieving an LED lamp RGB.
Nothing difficult, you might think … Except that along this route I found several obstacles.
First of all, I did not find complete projects on the net … There is something, but, in my opinion, with bad algorithms, with little explanation or with complicated methods.
I wanted a simple present to give to the person who I love and that gave me a beautiful daughter …
I wanted something that had a powerful enough light, without too much heat. I wanted something that had a chance to choose the color and not a simple “color cycler.” I wanted something that would serve also as a standard lamp. And finally, I wanted something that was modular and upgradeable in the future.
After these reflections, I began to study the hardware first. I did not want to use the Arduino UNO because it seemed too big for my project. So I decided (and this could open up a huge parentheses) to use a board not so common, but in my opinion awesome (so much that I bought 4 or 5 piece): The Arduino Mini Pro.
(It is understood that in the project of this post, it can easily be replaced by an Arduino UNO or any other board.)
It ‘a very small board (18mm x 33mm), 100% compatible with Arduino Dumilanove, and low power consumption. It is available in four versions: with Atmega328 or with ATmega168, both with 3.3V or 5V.
So I opted in this project for the 5V version with ATmega168. In short it is a very economic solution (it costs about half of the Arduino UNO), very compact and beautiful to see.
I then thought of using the useful LED RGB strips, which offer many advantages over using 1W or 3W power LEDs: they do not heat up, they are powered with 12V and they offer a power up to 13-14W per meter.
Each channel can be powered by a PWM output of the Arduino using a simple transistor (in my case I used the BC337, but for higher power you can use other transistor, or even the MOSFET).
I then proceeded to build a kind of shield for my board. Practically I made a circuit in which the Arduino Pro Mini would fit with strip connectors and with the ability to be removed to upgrade the firmware. Everything has been designed with Fritzing and built by Fritzing Fab.
The final result of the printed circuit is as follows:
You can see the two rows of holes where the Mini Pro will be mounted… Basically, it’s the opposite of a shield 🙂
But let’s step back and see the circuit schematic:
I hope it is clear enough even if I have not drawn just fine!
In any case, the operation principle is as follows: The two 10k potentiometers connected between +5 V and ground, are the two analog inputs that allow to adjust the brightness and other parameters set by the software. The 3-position switch SW2 allows you to select three different functions for the lamp. The digital outputs 3,5,6 go through a resistor to drive the 3 BC337 transistors that will give negative voltage to the 3 channels (R, G, B) of the LED strip. The common positive goes to +12 V, while the Arduino is powered by RAW port (input from 7V to 13V) via a diode that in addition to providing reverse polarity protection, slightly lowers the voltage. SW1 is simply the bridge where will be connected a standard power switch.
Once soldered the components, connectors, potentiometers, mounted the circuit, encapsulated the Arduino board, and assembled it all in a electrician box, the result is as in the following picture:
The size of the box is approximately 10cmx10cmx7cm.
For the top, I used about 70cm of RGB led strip, for a total power of about 10W. To fit the whole strip I rolled it around the support of a “50 CD-R set”. I cut with a utility knife and I glued all with spacers on the box. I then glued with hot glue the wrapping strip led… In short, the job is a little rough but the end result is as follows:
The glass you see on the desk, is the final piece: the glass cover of a IKEA lamp, properly cut by a local glazier, so that it remains empty on both sides. This coverage will finally resting on the box and glued, obtaining the following results:
Not bad right?
Of course there is still the icing on the cake, a not less important part: the software.
The self-explanatory code is as follows:
/*
RGB Led Lamp 1.0a
by Luca Soltoggio
15/03/2012
http://arduinoelettronica.wordpress.com/
*/
int rpin = 3; // red pin
int gpin = 5; // green pin
int bpin = 6; // blue pin
unsigned int r=0, g=0, b=0,bm=0; // r,g,b, value and blue coefficient
unsigned int valh=0, vals=0, valv=0; // hue, saturation, value
unsigned int sensorValue; // analog sensor value
const int analogInPin = A0; // potentiometer pins
const int analogInPin2 = A1;
const int digitalInPin = 10; // switch pins
const int digitalInPin2= 11;
int red[]={255,255,135}; // predefined arrays for RGB / White
int green[]={157,255,158};
int blue[]={51,255,255};
boolean DIG1, DIG2;
long previousMillis = 0;
int i=0,j=0;
int dl=0; // delay
void setup()
{
pinMode(digitalInPin,INPUT);
pinMode(digitalInPin2,INPUT);
}
void loop()
{
DIG1=digitalRead(digitalInPin);
DIG2=digitalRead(digitalInPin2);
if (DIG1) {
bm=1.1;
HSV_Game();
}
else if (DIG2) {
bm=1.9;
RAINBOW_Game();
}
else {
bm=2.4;
LIGHT_Game();
}
analogWrite(rpin, r/1.09); // write RED PIN
analogWrite(gpin, g/1); // write GREEN PIN
analogWrite(bpin, b/bm); // write BLUE PIN
}
// analog input smoothing function
int SensorSmooth (int pin) {
sensorValue=0;
for (int i = 0; i<10; i++) {
sensorValue+= analogRead(pin);
}
return int ((float)sensorValue/10+0.5);
}
// first light game: modify HUE and VALUE with potentiometer
void HSV_Game() {
valh = SensorSmooth(analogInPin);
vals = 255;
valv = SensorSmooth(analogInPin2);
valh = map(valh,0,1023,0,359);
valv = map(valv,0,1023,32,255);
hsv2rgb(valh,vals,valv,r,g,b);
}
// second light game: three positions for Warm White, White and Cold White
void LIGHT_Game() {
valv = SensorSmooth(analogInPin2);
valv = map(valv,0,1023,16,255);
valh = SensorSmooth(analogInPin);
if (valh<=281) valh=0;
if (valh>=742) valh=2;
if (valh>2) valh=1;
r=red[valh]*valv/255;
g=green[valh]*valv/255;
b=blue[valh]*valv/255;
}
// color cycler
void RAINBOW_Game() {
dl = SensorSmooth(analogInPin); // delay time
dl = map(dl,0,1023,1,100);
valv = SensorSmooth(analogInPin2);
valv = map(valv,0,1023,64,255);
unsigned long currentMillis = millis();
switch (j) {
case 0:
r=255*valv/255;
g=i*valv/255;
b=0*valv/255;
break;
case 1:
r=(255-i)*valv/255;
g=255*valv/255;
b=0*valv/255;
break;
case 2:
r=0*valv/255;
g=255*valv/255;
b=i*valv/255;
break;
case 3:
r=0*valv/255;
g=(255-i)*valv/255;
b=255*valv/255;
break;
case 4:
r=i*valv/255;
g=0*valv/255;
b=255*valv/255;
break;
case 5:
r=255*valv/255;
g=0*valv/255;
b=(255-i)*valv/255;
}
if (currentMillis-previousMillis > (long)(100-dl)) { // use millis instead of delay
previousMillis=currentMillis;
i=i+1;
if (i==256) {
i=1;
j=j+1;
if (j==6) j=0;
}
}
}
/* HSV2RGB function
(c) Elco Jacobs, E-atelier Industrial Design TU/e, July 2011
http://code.google.com/p/shiftpwm/source/browse/trunk/examples/ShiftPWM_Example1/hsv2rgb.cpp?r=3
*/
void hsv2rgb(int hue, int sat, int val, unsigned int& r, unsigned int& g, unsigned int& b)
{
int H_accent = hue/60;
int bottom = ((255 - sat) * val)>>8;
int top = val;
int rising = ((top-bottom) *(hue%60 ) ) / 60 + bottom;
int falling = ((top-bottom) *(60-hue%60) ) / 60 + bottom;
switch(H_accent) {
case 0:
r = top;
g = rising;
b = bottom;
break;
case 1:
r = falling;
g = top;
b = bottom;
break;
case 2:
r = bottom;
g = top;
b = rising;
break;
case 3:
r = bottom;
g = falling;
b = top;
break;
case 4:
r = rising;
g = bottom;
b = top;
break;
case 5:
r = top;
g = bottom;
b = falling;
break;
}
}
In the previous post we saw a simple LED driver based on integrated LM317, but as explained one of the faults of the circuit is the high dropout.
Thus we see today a scheme based on a single transistor (in our case a BC337, but any NPN is fine as long as we know all the electronics characteristics), which has a dropout of about 1.25V.
The circuit is as follows:
Of course, you can also use just one LED. I put three in series as example, as we are able to drive three 1W LEDs with a high efficiency. In the abovbe figure, we have a LED power of about 3W, while the whole circuit consumes about 4W.
But let see the operation principle:
The LEDR is a standard LED and serves as a reference voltage for the transistor. The red LED dropout is about 1.8V, then the collector of the transistor will receive approximately 950mV. Always applying Ohm’s law 0.950 / 2,8 = 339, then with R2 at 2.8Ω there is a current leakage of 339mA, which will flow also through the emitter of Q1. In this way we will have a constant current regardless of the input voltage. This is true as long as the voltage will be sufficient to maintain the LEDR at 1.8 V, or 1.2V on the emitter of Q1. So in other words we expect that the input voltage is at least 1.2V higher than the dropout of the LED that we are going to drive. White leds for example, have a maximum voltage of 3.6V, so 3.6 × 3 = 10.8V and 10.8 + 1.2 = 12V. In this case we are perfect. I always recommend a voltage of about 1.5 V more for safety.
If the load to drive is greater than 500-600mA, it is possible to decrease the value of R1 up to 470Ω.
If we want to exceed 750mA instead, we should replace the transistor with a darlington type like the BD677A that can deliver up to 4A!
You can test the circuit by changing the values, using the free simulator online at this link.
Obviously this circuit is “PWM capable.” We can then feed the device via a PWM circuit, or use the following appropriate circuit in order to use a PWM output of Arduino:
In this case we have to slightly decrease the value of resistance R2, due to the fact that the Q1 driving voltage is not 12V but 5V.
The important thing as always is to experiment, experiment, experiment!
The use of LEDs in daily life, in recent years has increasingly taken hold.
With the release on the market of power LEDs (1W, 3W, 5W, 10W …) the ability to illuminate our lives with these diodes is within everyone’s reach.
Unfortunately, the integrated power LED (like brand name bulbs) have costs still high enough, but the individual leds are affordable.
The problem for many is the power, as compared to classic 20mA LED that typically are fed at 12V with a 470Ω series resistor, this type of LED need, considering the power, to be fed not with constant voltage, but with constant current.
When you buy a high power LED, often the seller also provides its specified power driver at prices not always acceptable.
Hence my research on the various sites and blogs for a system to power these LEDs, which give me the ability to be dimmed even by a PWM circuit or by a microcontroller (such as Arduino).
I found two interesting projects, simple, easy to implement, experienced and above all economic and built with components very common and widespread.
The first circuit that I want to present, is constructed using the integrated circuit LM317, which is a variable voltage regulator, but in this case we will use it as a current regulator.
The circuit shown here is quite simple to understand. Between Vout and ADJ is present a reference voltage of 1.25 V, then applying Ohm’s law I = V / R, with a voltage of 1.25 V and a resistance of 3.6 Ω, we will have a constant current of approximately 347mA flowing through LED1, irrespective of the input voltage. This circuit is therefore suitable for example for powering a 1W LED (which typically uses 350mA).
Of course you can put more LEDs in series, but remember that the dropout is about 3V, so the input voltage must be at least 3V higher than the nominal LED voltage. However, if the voltage is too high the chip will warm up too much as all the excess voltage is dissipated just from LM317.
In fact this circuit from the point of view of yield is not the maximum; to power a 1W LED, the circuit draws approximately 4W.
We must also think about the fact that the power dissipated by resistance is about 1.25V multiplied by the circuit current (347mA in this case), then we should pay attention that resistance is adequate to power (we can put two or more resistences in series or in parallel to avoid this problem).
Everything is “PWM capable“, so we can feed the device with a PWM power driver (maybe i will public one in a future post), or drive the LED with a low power PWM signal, such as the output of a 5V Arduino. In this case the schematic will be modified as follows:
We had to change the value of the resistance R1 because introducing R2, the reference value is brought to 1.75V approx. It should be tested and measured with an current meter.
In this circuit VCC, that is the TTL input of our circuit (PWM output of an Arduino, rather than the logic output of a NE555), when is at a high value (+5V), the transistor Q1 conducts and the ADJ pin of the LM317 goes to ground, inhibiting the flowing of current in R1 and then in the LED. Conversely, if I bring the logic input to a low value (0V) the transistor does not conduct allowing the flowing of current: the LED lights up as in the previous example. Obviously logic works in reverse and then in microcontroller programming this should be taken into account, or at least you can add an additional transistor to invert the logic again.
In a future post, we’ll create another circuit that has the same function, but using a transistor instead of the LM317.