Friday, April 26, 2013

15. Programming the ATTiny85 with the BreadboArduino

The ATTiny85 is a tiny 8-legged microcontroller, and it is a surprisingly powerful device.  It has 8kB of Flash memory, 512 bytes of EPROM (Erasable Programmable Read Only Memory) and 512 bytes of RAM (Random Access Memory), can operate up to 20 MHz, has an 8-bit AVR (an architecture developed by the Atmel company) central processing unit, up to 6 available input/output pins, and operates between 2.7 V and 5.5 V. 

Applications range from home climate control to remote health monitoring (Telecare), home appliances, and industrial sensor devices.  You can buy them for about £1.50 each.



You can also program them using an Arduino, with the Arduino IDE software.  So I thought I would have a go at xBacon's Mini RGB Mood Light (http://www.instructables.com/id/ATtiny85-Mini-RGB-Mood-Light/).  The version I decided to build is the Night version, which can detect when it's dark and automatically turn on the cycle of hundreds of colours.  

All the details are given above, but it has a light dependent resistor (LDR) which tells it when the ambient light level is low (night time).  


The Light Dependent Resistor


This is what it looks like:






Also known as a photoresistor, the LDR's resistance decreases as the amount of light falling on it increases.  This behaviour is known as photoconductivity.  Its working element is a semiconductor with high resistance.  Semiconductors work as conductors when something stimulates the electrons bound in its valence band, to jump to the conduction band.  

There are many things that can stimulate this, but in this case, visible ambient light has enough energy to enable electrons to jump to the conduction band.  The resulting electrons in the conduction band, and their associated vacancies (holes) in the valence band, effectively cause the material to become a conductor, which in effect is a lowering of resistance.

Most semiconductor materials are extrinsic as opposed to intrinsic, meaning that they have been doped with miniscule amounts of a chosen impurity, which makes it easier for the electrons to cross the valence band / conduction band energy gap.  This is basically how photocells work.  The labelled diagram above indicates cadmium sulphide as the active semiconductor.

LDRs can be bought for about 25 pence each.

PWM and POV

When LEDs are driven by digital signals (square wave signals with a fixed amplitude) and their output light intensity needs to be changed, the method of Pulse Width Modulation (PWM) can be employed successfully:  

The LED's brightness is not actually going up and down, it's only blinking on and off at the same voltage, but as the duty cycle changes, it appears to fade and glow.  The duty cycle of square waveforms is the ratio of the pulse width to the period.  

This smooth appearance is due to our visual perception - our eye-brain systems are not capable of seeing the very rapid flashing of the LED, and instead we perceive the brightness going up and down.  This effect is known as Persistence of Vision (POV).  The following cartoon has been made from a series of still drawings replayed at 12 frames per second.  Our persistence of vision  makes us think that there is smooth motion.

12 fps actually appears jerky and that's why modern movies work at 24 fps - for smooth persistence of vision.

It is relatively easy to vary the duty cycle with software.

The RGB LED

The Red-Green-Blue Light Emitting Diode is another nice component.  Not only can these show you how your circuit and software are working, but everybody likes them - particularly the multi-coloured ones.


The picture on the left shows the anatomy of a single-colour LED.  They can be produced in various colours, using different semiconductor materials for the diode.  On the right is shown the RGB LED, which is really 3 single colour elements in one - hence the need for two extra legs for the two extra colours.  

One of the legs is a different length from the others, indicating that it is common to all 3 elements ie either the common anode (positive terminal - only one of these needed for all three) or common cathode (negative terminal).  As can be seen in this example, there is a clear plastic cover, allowing white light to be emitted when all three elements are on.

Here is a demonstration of how the three primary colours of light can be combined to give secondary colours:
This shows how full intensity red, green and blue combine, but as the red, green and blue brightnesses change, many other intermediate colours are produced.  

Our lamp will cycle from red to yellow to green to cyan to blue to magenta to red, by smoothly reducing the duty cycle of the first colour while at the same time increasing the duty cycle of the second colour.  This should appear to be smooth as there are 100 steps involved in each transition.

Programming the ATTiny85

Before looking at the connections from chip to chip, let's look at the basic pin numbering convention for integrated circuits.  Here is a general chip:

The pins are numbered in an anti-clockwise direction, starting with Pin 1, indicated by the small spot beside it.  If the spot isn't there, there's still usually a half-moon mark on one end, which shows the end that Pin 1 is on.

This can be done by connecting the two chips as follows:

ATMega 328 (Hobbytronics.co.uk type label)



Connect the ATMega 328 chip's pins to the ATtiny as follows:

                              ATMega 328 Vcc (+5V)           --->  ATtiny85 Pin 8 (VCC)
                              ATMega 328 Ground (GND)    --->  ATtiny85 Pin 4
                              ATMega 328 Pin D10              --->  ATtiny85 Pin 1 (Reset)
                              ATMega 328 Pin D11              --->  ATtiny85 Pin 5
                              ATMega 328 Pin D12              --->  ATtiny85 Pin 6
                              ATMega 328 Pin D13              --->  ATtiny85 Pin 7

Then follow this link http://hlt.media.mit.edu/?p=1695 for instructions on how to download files, and use the Arduino ISP software.

The sketch comes straight from http://www.instructables.com/id/ATtiny85-Mini-RGB-Mood-Light/  The essence is that the 6 methods redtoyellow()  through to magentatored() run in a continuous loop until the detected ambient light level (analogRead(sensor) exceeds a pre-defined value.  At that point it turns the LED off until the room gets dark again.

The methods (sections of code beginning with void) select the pins involved in powering the LED elements and fade up in 100 steps,  one colour, by flashing it on and off for varying amounts of time, effectively increasing that colour's duty cycle. At the same time, the duty cycle of a neighbouring colour is gradually decreased, and the result is a pleasing transition from the first colour to the second. 

Here is the instructables.com sketch code again for convenience:

1:  //ATtiny85 RGB color fading Mood Light NOW WITH LIGHT SENSING CAPABILITIES!!!  
2:    
3:  const int redPin = 2;   
4:  const int grnPin = 1;   
5:  const int bluPin = 0;  
6:  const int sensor = 3;  
7:    
8:    
9:  void setup()  
10:  {  
11:   pinMode(redPin, OUTPUT);    
12:   pinMode(grnPin, OUTPUT);    
13:   pinMode(bluPin, OUTPUT);  
14:   pinMode(sensor, INPUT);  
15:  }  
16:    
17:  void loop() {  
18:   if (analogRead(sensor) <= 200)  
19:   {  
20:    redtoyellow();  
21:    yellowtogreen();  
22:    greentocyan();  
23:    cyantoblue();  
24:    bluetomagenta();  
25:    magentatored();  
26:   }  
27:   else if (analogRead(sensor) >= 201)  
28:   {  
29:    digitalWrite(redPin, LOW);  
30:    digitalWrite(grnPin, LOW);  
31:    digitalWrite(bluPin, LOW);  
32:   }  
33:  }  
34:    
35:  void redtoyellow()  
36:  {  
37:   digitalWrite(redPin, HIGH);  
38:   digitalWrite(bluPin, LOW);  
39:    
40:   // fade up green  
41:   for(byte i=1; i<100; i++) {  
42:    byte on = i;  
43:    byte off = 100-on;  
44:    for( byte a=0; a<100; a++ ) {  
45:     digitalWrite(grnPin, HIGH);  
46:     delayMicroseconds(on);  
47:     digitalWrite(grnPin, LOW);  
48:     delayMicroseconds(off);  
49:    }  
50:   }  
51:  }  
52:    
53:    
54:    
55:  void yellowtogreen()  
56:  {  
57:   digitalWrite(grnPin, HIGH);  
58:   digitalWrite(bluPin, LOW);  
59:    
60:   // fade down red  
61:   for(byte i=1; i<100; i++) {  
62:    byte on = 100-i;  
63:    byte off = i;  
64:    for( byte a=0; a<100; a++ ) {  
65:     digitalWrite(redPin, HIGH);  
66:     delayMicroseconds(on);  
67:     digitalWrite(redPin, LOW);  
68:     delayMicroseconds(off);  
69:    }  
70:   }  
71:  }  
72:    
73:    
74:  void greentocyan()  
75:  {  
76:   digitalWrite(grnPin, HIGH);  
77:   digitalWrite(redPin, LOW);  
78:    
79:   // fade up blue  
80:   for(byte i=1; i<100; i++) {  
81:    byte on = i;  
82:    byte off = 100-on;  
83:    for( byte a=0; a<100; a++ ) {  
84:     digitalWrite(bluPin, HIGH);  
85:     delayMicroseconds(on);  
86:     digitalWrite(bluPin, LOW);  
87:     delayMicroseconds(off);  
88:    }  
89:   }  
90:  }  
91:    
92:    
93:    
94:  void cyantoblue()  
95:  {  
96:   digitalWrite(bluPin, HIGH);  
97:   digitalWrite(redPin, LOW);  
98:    
99:   // fade down green  
100:   for(byte i=1; i<100; i++) {  
101:    byte on = 100-i;  
102:    byte off = i;  
103:    for( byte a=0; a<100; a++ ) {  
104:     digitalWrite(grnPin, HIGH);  
105:     delayMicroseconds(on);  
106:     digitalWrite(grnPin, LOW);  
107:     delayMicroseconds(off);  
108:    }  
109:   }  
110:  }  
111:    
112:    
113:  void bluetomagenta()  
114:  {  
115:   digitalWrite(bluPin, HIGH);  
116:   digitalWrite(grnPin, LOW);  
117:    
118:   // fade up red  
119:   for(byte i=1; i<100; i++) {  
120:    byte on = i;  
121:    byte off = 100-on;  
122:    for( byte a=0; a<100; a++ ) {  
123:     digitalWrite(redPin, HIGH);  
124:     delayMicroseconds(on);  
125:     digitalWrite(redPin, LOW);  
126:     delayMicroseconds(off);  
127:    }  
128:   }  
129:  }  
130:    
131:    
132:    
133:  void magentatored()  
134:  {  
135:   digitalWrite(redPin, HIGH);  
136:   digitalWrite(grnPin, LOW);  
137:    
138:   // fade down blue  
139:   for(byte i=1; i<100; i++) {  
140:    byte on = 100-i;  
141:    byte off = i;  
142:    for( byte a=0; a<100; a++ ) {  
143:     digitalWrite(bluPin, HIGH);  
144:     delayMicroseconds(on);  
145:     digitalWrite(bluPin, LOW);  
146:     delayMicroseconds(off);  
147:    }  
148:   }  
149:  }  
.  

It's really amazing that the bare-bones Arduino (BreadboArduino) can be used to flash a program to a tiny chip, which will just continue to drive the Night Time Mood Lamp for as long as it receives power.

And here is my ATTiny85 controlled Night Time Mood Lamp in the cyan part of its colour cycle:

The photoresistor is at the top right of the picture.

No comments:

Post a Comment