Introduction: ATtiny85 Mini RGB Mood Light!

I have seen RGB mood lights using Arduino, PIC, and larger AVR chips, but never one with the ATtiny85. That's why I decided to make one.

This mood light is super simple to make and all the parts can be purchased online for about $5.00 total (not including the Arduino used to program the chip).

This is a contest entry in the LED contest with Elemental LED and the Hurricane Lasers contest, so if you like it, vote!

EDIT: I have changed this instructable so that it is a NIGHT LED Mood Lamp. It now only lights up when the ambient light in the room is very low (at night with all the lights off). You do need an LDR and a 10K ohm resistor to add this part though. If you want it to not have this feature, just remove the LDR/10K resistor part and connect Analog Input 3 of the ATtiny (pin 2) straight to ground.

Step 1: How Does It Work?

The ATtiny85 only has 2 PWM pins, so obviously you can't make all 3 colors of the RGB LED fade in and out smoothly, right? Wrong.

The way I got around this was by using software PWM. This means that I can fade in and out of all 3 colors using any of the pins on the ATtiny.

How software PWM works is by setting the pin HIGH and then LOW at different rates so that the LED looks like it's dimming. This is called Persistence of Vision or POV (for more on POV, see my instructable here). The LED blinks so rapidly that the human eye can't detect that it is flashing at all, and it sees instead that the LED appears to be dimming.

Step 2: Parts List

You will need:

1x Common cathode RGB LED
3x 220 ohm resistors
1x ATtiny85 Microcontroller

For the Light sensing part:

1x LDR (light dependent resistor)
1x 10K ohm resistor

And to program the ATtiny:

1x Arduino Uno or equivalent
1x A to B USB cable for Arduino

Step 3: Program the Chip

Go here and it will show you how to connect the ATtiny85 to the Arduino and program it. Once you are ready to upload the code to the ATtiny85, paste it into the Arduino IDE and click upload.



//ATtiny85 RGB color fading Mood Light NOW WITH LIGHT SENSING CAPABILITIES!!!

const int redPin = 2; 
const int grnPin = 1; 
const int bluPin = 0;
const int sensor = 3;


void setup()
{
  pinMode(redPin, OUTPUT);    
  pinMode(grnPin, OUTPUT);    
  pinMode(bluPin, OUTPUT);
  pinMode(sensor, INPUT);
}

void loop() {
  if (analogRead(sensor) <= 200)
  {
    redtoyellow();
    yellowtogreen();
    greentocyan();
    cyantoblue();
    bluetomagenta();
    magentatored();
  }
  else if (analogRead(sensor) >= 201)
  {
    digitalWrite(redPin, LOW);
    digitalWrite(grnPin, LOW);
    digitalWrite(bluPin, LOW);
  }
}

void redtoyellow()
{
  digitalWrite(redPin, HIGH);
  digitalWrite(bluPin, LOW);

  // fade up green
  for(byte i=1; i<100; i++) {
    byte on  = i;
    byte off = 100-on;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(grnPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(grnPin, LOW);
      delayMicroseconds(off);
    }
  }
}



void yellowtogreen()
{
  digitalWrite(grnPin, HIGH);
  digitalWrite(bluPin, LOW);

  // fade down red
  for(byte i=1; i<100; i++) {
    byte on  = 100-i;
    byte off = i;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(redPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(redPin, LOW);
      delayMicroseconds(off);
    }
  }
}


void greentocyan()
{
  digitalWrite(grnPin, HIGH);
  digitalWrite(redPin, LOW);

  // fade up blue
  for(byte i=1; i<100; i++) {
    byte on  = i;
    byte off = 100-on;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(bluPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(bluPin, LOW);
      delayMicroseconds(off);
    }
  }
}



void cyantoblue()
{
  digitalWrite(bluPin, HIGH);
  digitalWrite(redPin, LOW);

  // fade down green
  for(byte i=1; i<100; i++) {
    byte on  = 100-i;
    byte off = i;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(grnPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(grnPin, LOW);
      delayMicroseconds(off);
    }
  }
}


void bluetomagenta()
{
  digitalWrite(bluPin, HIGH);
  digitalWrite(grnPin, LOW);

  // fade up red
  for(byte i=1; i<100; i++) {
    byte on  = i;
    byte off = 100-on;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(redPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(redPin, LOW);
      delayMicroseconds(off);
    }
  }
}



void magentatored()
{
  digitalWrite(redPin, HIGH);
  digitalWrite(grnPin, LOW);

  // fade down blue
  for(byte i=1; i<100; i++) {
    byte on  = 100-i;
    byte off = i;
    for( byte a=0; a<100; a++ ) {
      digitalWrite(bluPin, HIGH);
      delayMicroseconds(on);
      digitalWrite(bluPin, LOW);
      delayMicroseconds(off);
    }
  }
}

Step 4: Connect It

Connect the ATtiny to the LEDs and 3V like shown in the schematic, and that's it!

If you want the circuit to not respond to light and be constantly on and fading, just remove the LDR and 10K resistor and connect Analog Input 3 (pin 2) straight to ground.

Step 5: You're Done!

Good Job! When you apply 3 volts it should start to fade through the different colors.

Comments

author
blyamur made it!(author)2017-07-12

Great work. I changed it a little for my own needs and it was great.

P7120004.JPG
author
samlf3rd made it!(author)2015-01-17

How can I make this without the sensor? I just want it to run constantly. Thank you!

author
blyamur made it!(author)2017-07-12

Hi, you can use this example:

//ATtiny85 RGB color fading Mood Light NOW WITH LIGHT SENSING CAPABILITIES!!!

const int redPin = 2;

const int grnPin = 1;

const int bluPin = 0;

long sensor;

void setup()

{

pinMode(redPin, OUTPUT);

pinMode(grnPin, OUTPUT);

pinMode(bluPin, OUTPUT);

sensor = random(10, 300);

}

void loop() {

if (analogRead(sensor) <= 200)

{

redtoyellow();

yellowtogreen();

greentocyan();

cyantoblue();

bluetomagenta();

magentatored();

}

else if (analogRead(sensor) >= 201)

{

digitalWrite(redPin, LOW);

digitalWrite(grnPin, LOW);

digitalWrite(bluPin, LOW);

}

}

void redtoyellow()

{

digitalWrite(redPin, HIGH);

digitalWrite(bluPin, LOW);

// fade up green

for(byte i=1; i<100; i++) {

byte on = i;

byte off = 100-on;

for( byte a=0; a<100; a++ ) {

digitalWrite(grnPin, HIGH);

delayMicroseconds(on);

digitalWrite(grnPin, LOW);

delayMicroseconds(off);

}

}

}

void yellowtogreen()

{

digitalWrite(grnPin, HIGH);

digitalWrite(bluPin, LOW);

// fade down red

for(byte i=1; i<100; i++) {

byte on = 100-i;

byte off = i;

for( byte a=0; a<100; a++ ) {

digitalWrite(redPin, HIGH);

delayMicroseconds(on);

digitalWrite(redPin, LOW);

delayMicroseconds(off);

}

}

}

void greentocyan()

{

digitalWrite(grnPin, HIGH);

digitalWrite(redPin, LOW);

// fade up blue

for(byte i=1; i<100; i++) {

byte on = i;

byte off = 100-on;

for( byte a=0; a<100; a++ ) {

digitalWrite(bluPin, HIGH);

delayMicroseconds(on);

digitalWrite(bluPin, LOW);

delayMicroseconds(off);

}

}

}

void cyantoblue()

{

digitalWrite(bluPin, HIGH);

digitalWrite(redPin, LOW);

// fade down green

for(byte i=1; i<100; i++) {

byte on = 100-i;

byte off = i;

for( byte a=0; a<100; a++ ) {

digitalWrite(grnPin, HIGH);

delayMicroseconds(on);

digitalWrite(grnPin, LOW);

delayMicroseconds(off);

}

}

}

void bluetomagenta()

{

digitalWrite(bluPin, HIGH);

digitalWrite(grnPin, LOW);

// fade up red

for(byte i=1; i<100; i++) {

byte on = i;

byte off = 100-on;

for( byte a=0; a<100; a++ ) {

digitalWrite(redPin, HIGH);

delayMicroseconds(on);

digitalWrite(redPin, LOW);

delayMicroseconds(off);

}

}

}

void magentatored()

{

digitalWrite(redPin, HIGH);

digitalWrite(grnPin, LOW);

// fade down blue

for(byte i=1; i<100; i++) {

byte on = 100-i;

byte off = i;

for( byte a=0; a<100; a++ ) {

digitalWrite(bluPin, HIGH);

delayMicroseconds(on);

digitalWrite(bluPin, LOW);

delayMicroseconds(off);

}

}

}

P7120006.JPG
author
diy_bloke made it!(author)2015-02-16

you could take the IF...ELSE loop out of the program.
If you do not know how to do that, well you could replace the sensor by a wire bridge or leave it open, depending on how it is wird
In the program you see that if the value read from the sensor is greater or equal than 201, the lights shld go out.
As I presume the lights shld go out when it is light ( low resistance of LDR) and on when it is dark (high resistance of LDR), I guess just omitting the sensor would do the trick.

author
samlf3rd made it!(author)2015-02-16

I did get it, and after a little learning it was very easy to run without any other components. Forgive me I just started learning on Christmas, and thank you!

author
diy_bloke made it!(author)2015-03-02

we all have to start learning at one point :-)

author
BrandonT7 made it!(author)2015-05-06

Any ideas as to how I can slow down the rate at which the colors cycle? Love this project, by the way, you're awesome!

author
diy_bloke made it!(author)2015-03-07

OK, finally got around to build it and found the light changes extremely slow (on 8MHz). Which core are you using?

author
diy_bloke made it!(author)2015-04-17

found it. forgot to set the fuses for 8MHz

author
Hassan+balaha made it!(author)2015-03-12

Nice work buddy

author
mikroskeem made it!(author)2013-06-26

Where can i get another version of it? i don't use Adruino IDE, since i program with parralel port

author
diy_bloke made it!(author)2015-02-20

ide supports parallel programmer

author
mikroskeem made it!(author)2015-02-21

okay... i couldn't get it working :/

author
diy_bloke made it!(author)2015-02-22

I do not know why that is, the only thing I know is that the IDE supports a parallel programmer. If you cant get it to work you have to upload the hex file:

http://forum.arduino.cc/index.php?topic=114503.0

pp.png
author
diy_bloke made it!(author)2015-02-16

Great article.
Though you are right on the software PWM, there is some discussion on wether it has 2 or 3 PWM outputs.
Supposedly it has 3, all addressable from inside the IDE
IC leg 6 (PB1),
IC leg 5 (PB0),
IC leg 3 (PB4),
Supposedly, strictly speaking IC leg 2 (D3/PB3) is also capable of PWM, but internally it shares the same timer used on leg 3.
I didnt try it myself, but that is what I have been reading. Some discussion going on here:

http://forum.arduino.cc/index.php?topic=134754.0

author
ironheartbj18 made it!(author)2014-12-30

a special thanks to you https://www.youtube.com/watch?v=rupib_N7zqw

author
ironheartbj18 made it!(author)2014-12-24

other tutorial great how to install attiny 0022 with library http://makezine.com/2011/10/10/how-to-shrinkify-your-arduino-projects/

author
I3L4ck5h33p made it!(author)2014-11-30

Which LDR was used for this?

author
kshowell made it!(author)2014-08-28

Nice Instructable. Thank you for the work. It was fun to build.

author
waterlubber made it!(author)2014-07-20

actually, I built this and ran it using my original code from my arduino sketch, apparently there is a hush hush third PWM that's buggy but functional on the AtTiny, and the code eliminates functions and uses for().

author
agrady1995 made it!(author)2014-04-15

Thank you SO MUCH!!! I was trying to figure out which ATtiny to get, but it looks like it will work with this! now all I need is to be able to program it with my stupid Arduino 2560.. It's not working so far.. I think i need to add the .1uF cap to ground... :/

author
agrady1995 made it!(author)2014-04-15

This is the ONLY (current) reason I wanted to program an ATtiny anyway xD

author
WWC made it!(author)2012-09-22

Hi
This is my first go around with ATtiny85, other than the blink sketch. So i thank you for this project.

Is all of the transitions in colors smooth?
I get a blink from red to green, or a fast switch. Not a smooth transition as all the other colors.
Is this the nature of this sketch or have i thrown a monkey wrench in here somewhere?

Thanks

W

author
xBacon made it!(author)2012-09-23

Yes, the transitions of the colors should be smooth. Between red and green, it should slowly fade yellow. Try re uploading the sketch and checking your wiring.

author
WWC made it!(author)2012-09-23

Now that i investigate it more looks like it's the LED i have doing that.

author
siliconghost made it!(author)2014-04-13

I had a similar problem and it ended up being because I still had the AtTiny85 running at 1Mhz. You need to go through the process of burning the boot loader at 8Mhz before it will be smooth.

author
WWC made it!(author)2012-09-23

I had 2 RGB's in a row that were not switching smoothly. All the other RGB's i have tried are fine. Whats the chances of 2 defective in a row out of 50?

Thanks
W

author
waterlubber made it!(author)2012-08-17

Great able! Just got my shipment of my ATtiny45's (they were out of 85's, and I didn't want to pay $10 shipping @ other site) I have a problem:
I have common anode(seriously? Who thought of that?)RGB LEDS. Can I just change something in the code, or do I have to use transistors?

author
xBacon made it!(author)2012-08-17

I think you can just connect the common anode with resistors to +5V, and change all the ++ things in the 'for' statements to --. Tell me if this works.

author
siliconghost made it!(author)2014-04-13

I had one of these too. All you have to do is connect the LED to +5V instead of GND. I didn't have to change anything else in the code.

author
codongolev made it!(author)2013-03-04

go where to find out how to connect to the arduino?

author
Troyirl made it!(author)2014-04-12

Go here to see how to program a ATtiny45/85 with an Arduino

https://www.youtube.com/watch?v=30rPt802n1k

author
Mike6158 made it!(author)2014-03-28

"Go here and it will show you how to connect the ATtiny85 to the Arduino and program it."

Go where???

author
tecnocubeguy made it!(author)2013-07-30

You can replace the 3 resistors hooked up to the LED anodes with only one. Just connect the LED anodes directly to the microcontroller, and put one 220 ohm (or appropriate) resistor between the common cathodes and ground.

Be warned that some RGB LEDs need a different value resistor on the red anode than the blue and green ones. In that case, you would have to use 3 resistors on the anodes. In this case, since all 3 colors apparently use the same value resistors, you can put one of that value on the cathodes and still have the same results.

Just make sure you use the right resistor. :)

author
tecnocubeguy made it!(author)2013-07-30

I've improved this code. New features include:

Easier to read and understand
Generalized fadeUp and fadeDown functions
Arbitrary speed control
Easy control of light threshold

Here is the new code:

const int redPin = 2;
const int greenPin = 1;
const int bluePin = 0;
const int sensor = 3;
int lightThresh = 550; // Light threshold. 0 - 1023. Lower number = activation at lower light level.
int time = 50; // Speed control. Higher number = slower fades.


void setup()
{
  pinMode(redPin, OUTPUT);   
  pinMode(greenPin, OUTPUT);   
  pinMode(bluePin, OUTPUT);
  pinMode(sensor, INPUT);
}
//fadeUp & fadeDown syntax: (color to fade, color to turn on, color to turn off)
void loop() {
  if (analogRead(sensor) <= lightThresh)
  {
    fadeUp(greenPin, redPin, bluePin);   //red to yellow
    fadeDown(redPin, greenPin, bluePin); //yellow to green
    fadeUp(bluePin, greenPin, redPin);   //green to cyan
    fadeDown(greenPin, bluePin, redPin); //cyan to blue
    fadeUp(redPin, bluePin, greenPin);   //blue to purple
    fadeDown(bluePin, redPin, greenPin); //purple to red
  }
  else if (analogRead(sensor) > lightThresh)
  {
    //turn all colors off
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, LOW);
    digitalWrite(bluePin, LOW);
  }
}

void fadeUp(int fadePin, int onPin, int offPin) {
  //set constant colors
  digitalWrite(onPin, HIGH);
  digitalWrite(offPin, LOW);
  //set current brightness out of 1000
  for(int bright = 1; bright < 1000; bright = bright + 10) {
    //set PWM lengths
    int on = bright;
    int off = 1000 - bright;
    //software PWM for 'time' ms
    for(int run = 0; run < time; run++) {
      digitalWrite(fadePin, HIGH);
      delayMicroseconds(on);
      digitalWrite(fadePin, LOW);
      delayMicroseconds(off);
    }
  }
}

void fadeDown(int fadePin, int onPin, int offPin) {
  //set constant colors
  digitalWrite(onPin, HIGH);
  digitalWrite(offPin, LOW);
  //set current brightness out of 1000
  for(int bright = 1; bright < 1000; bright = bright + 10) {
    //set inverse PWM lengths
    int on = 1000 - bright;
    int off = bright;
    //software PWM for 'time' ms
    for(int run = 0; run < time; run++) {
      digitalWrite(fadePin, HIGH);
      delayMicroseconds(on);
      digitalWrite(fadePin, LOW);
      delayMicroseconds(off);
    }
  }
}


I would recommend setting your internal ATtiny85 clock to 8 MHz, instead of the default 1 MHz. This is optional, but it provides you with more accurate control of the fade time, as the chip isn't limited by its slow clock speed. This is easy to do within the Arduino programming environment, and it just as easily reversed. However, it does take more power, and will drain a battery faster. I am running mine on USB 5V, so it isn't a concern. If you are interested, just go here to see how to do it.

author
PowerCat made it!(author)2013-07-23

@mikroskeem once you click "Upload" on the arduino software, it'll fail to upload to the atmega, so then click Start > Run > %temp%

Look for a folder called something like build7137078911822462892.tmp the newest one in your system. Then find inside the file SketchName.cpp.hex

That is the compiled program. Simply upload that hex file using avrdude.

author
Ploopy made it!(author)2013-06-10

Cool

author
marcusone made it!(author)2013-01-20

You can use a Common Anode version of the RBG LED -> Actually you just connect the common to +3v via 1 resistor (so saves you 2 resistors this way). Then in the code switch all the HIGH -> LOW and LOW->HIGH. I just switched the "off" part to HIGH's, as I didn't care if the code was technically wrong (where you state/label which color is being changed).

author
cowlick3 made it!(author)2012-08-22

For the longest time I believed this myth that the ATTiny85 only has 2 PWM pins as well. Until I started testing the pins myself and found a 3rd one, so there are at least 3 (PB0, PB1 & PB4) which you can PWM with simple analogWrite() calls. I've tested smooth HSV fades with an RGB LED and it works perfectly. It even works when using the slower 1MHz clock without any noticeable flicker (and lower power consumption). It could have something to do with the core that you use. I think I'm using the "Arduino-Tiny" core.

author
hilukasz made it!(author)2012-12-14

you can actually squeeze 5 out of it :) check this out http://www.kobakant.at/DIY/?p=3393

author
waterlubber made it!(author)2012-08-30

Wait a sec... analogWrite? I thought you had to use xBacons method. Cool!

author
waterlubber made it!(author)2012-08-30

Where do you get it?

author
xBacon made it!(author)2012-08-30

Here: http://code.google.com/p/arduino-tiny/downloads/detail?name=arduino-tiny-0100-0015.zip

author
waterlubber made it!(author)2012-08-30

Thanks!

author
xBacon made it!(author)2012-08-23

Ok, I will try out that core. Thanks!

author
amandaghassaei made it!(author)2012-08-16

nice work getting around the PWM issue! I'd really like to use an ATtiny for a project soon.

author
xBacon made it!(author)2012-08-16

Thanks! You can get the '85s for about 80c each at Digi-key or Mouser if you didn't already know :)

About This Instructable

68,953views

158favorites

License:

Bio: I'm a big Arduino fan. I'm always looking for new and exciting things to do with electronics and Arduino. I also like video ... More »
More by xBacon:DIY Infrared Proximity Sensor (Arduino Compatible)Color Changing LED TreePlug-in LED Color Fading Night Light
Add instructable to: