![]() Full Brightness |
![]() Dim Lighting |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Project DescriptionThis project uses an inexpensive programmable microcontroller to sense voltage across a photosistor and send output to a 7 segment LED. It outputs the digit 0 for very dim lighting and 9 for relatively bright lighting (and values in between). The goal is to learn how to program the Tiny26L Microcontroller through a simple, entertaining, and educational project. The HardwareThis guide is meant to be fairly general and will work with any AVR series microcontroller and virtually 7 segment displays and sensors. A note on powerThe onboard 5V regulator (LM78L05) will accept from 6V to about 20 V and still output 5 V, but if you run anything below 6 volts the regulator will start to drop out and supply less voltage. For the Tiny26L this does not pose a major problem because it can run on as little as 2.7 V. Powering the chip with 4 AA batteries in series will work fine ( 1.2V x 4 batteries = 4.8 V, which will be around 3 volts from voltage regulator). Make sure the chip does not see more than 5.5V (absolute maximum rating) and . Always measure your input voltage before connecting because if the voltage is too high or you plug in power backwards you will fry the chip! Initial Calculations We will be using the Fairchild MAN6980, one digit, common cathode led display. The MAN6980 will be powered directly from the chip using resistors to control the current through each LED segment. The data sheet states that each segment has a maximum forward current of 30mA and a maximum voltage drop of 2.5 volts. By looking at the Tiny26L datasheet we know that it can run at a maximum of 5.5V so the theoretical maximum each pin can supply is 5.5V (this will most likely never happen in actual operation, we'll take the precautions for absolute maximum calculations). The sensorYou can use any sort of voltage varying sensor for this project. Some simple examples include: photosistor, thermistor, infrared sensor. As a sensor I will use a photosistor which, unfortunately, has no available datasheet. Determining the setup, however, is quite easy and the same process can be applied to other resistive sensors that you do not have datasheets for. There are two approaches you can take: 1.) You can measure the resistance for the maximum and minimum conditions, take the average, and use that resistance value for the voltage divider. 2.) You can measure the resistance in the condition you would expect to be the most common. For a photosistor this might be average interior lighting.Connections
Connection Table:
Logic Table:
Compiling CodeI assume a typical user will be running Windows XP, however, all of these tools are available under Linux. To compile/program the code you will need to download WinAVR. WinAVR is a very useful set of tools which includes the GNU C Compiler (GCC) and the required AVR libraries for translating your C code into AVR assembly instructions. In addition, it gives your DOS command prompt some Linux/Unix commands. To compile C-code simply fire up the command prompt, navigate to the code directory and type "make" (Note: you must have a makefile in the directory for this to work.) Another approach to compiling your code is using Atmel's AVR studio. This has a nice IDE and makes the compile/build process transparent to the user.
The Tiny26L is an 8-bit RISC processor which on a very simplified level means the microcontroller manipulates one 8-bit data value at a time. As a result it is efficient to use 8-bit (char) variable types when coding in C. There are many 8-bit registers onboard the microcontroller that govern how it operates (page 170 of the datasheet lists a summary of all registers). We'll start with the most basics ones - the I/O registers. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
DDRA = 0b11111111; //Set all pins as outputs PORTA = 0b00000000; //Output logic low on all pins of port A DDRB = 0b01011111; //PA7 = input, PA5 = input, the rest are outputs PORTB = 0b00000000; //Output logic low on output pins and no pull-up resistors on input pins |
DDRA is an 8-bit register which stands for Data Direction Register for Port A. The binary value 11111111 tells the chip that all the pins on the side of port A are outputs.
0 = INPUT
1 = OUTPUT
DDRB - Data Direction Port B |
||||||||
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Value |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
Controls |
PB7 |
PB6 |
PB5 |
PB4 |
PB3 |
PB2 |
PB1 |
PA0 |
Function |
IN |
OUT |
IN |
OUT |
OUT |
OUT |
OUT |
OUT |
| DDxn | PORTxn | I/O | Pull-up | Comment |
| 0 | 0 | Input | No | Tri-state (HI-Z) |
| 0 | 1 | Input | Yes | Can source current |
| 1 | 0 | Output | No | Output low (sink) |
| 1 | 1 | Output | No | Output high (source) |
PORTB |
||||||||
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Value |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Controls |
PB7 |
PB6 |
PB5 |
PB4 |
PB3 |
PB2 |
PB1 |
PA0 |
Function |
IN (no pull-up) |
OUT (logic low) |
IN (no pull-up) |
OUT (logic low) |
OUT (logic low) |
OUT (logic low) |
OUT (logic low) |
OUT (logic low) |
Analog to Digital Conversions
| // Read the AD conversion result unsigned int read_adc(unsigned char adc_input){ // Select pin for conversion ADMUX = adc_input|ADC_VREF_TYPE; // Start the AD conversion ADCSR|=0b01000000; // Wait for the AD conversion to complete while ((ADCSR & 0b00010000) == 0); ADCSR|=0b00010000; // Return 8-bit conversion value return ADCH; } |
The Tiny26L has a 10-bit analog-to-digital converter which can be read by the ADCH and ADCL registers.
ADMUX and ADCSR registers enable and control the operation of the the analog-to-digital converter.
| Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Name | ADEN | ADSC | ADFR | ADIF | ADIE | ADPS2 | ADPS1 | ADPS0 |
Bit 7 – ADEN: ADC Enable
Setting this bit to "1" enables the AD converter
Bit 6 – ADSC: ADC Start Conversion
Setting this bit to "1" starts an AD conversion
Bit 5 – ADFR: ADC Free Running Select
Setting this bit to "1" runs the ADC at a continuously updated rate.
Bit 4 – ADIF: ADC Interrupt Flag
This bit is automatically set to "1" when an AD conversion has completed
Bit 3 – ADIE: ADC Interrupt Enable
Setting this bit to "1" enables the ADC interrupt.
Bits 2-0 - ADPS Bits: ADC Prescaler Select Bits
These bits govern the frequency of the AD conversions based on the following table of values:
| ADPS2 | ADPS1 | ADPS0 | Division Factor |
| 0 | 0 | 0 | 2 |
| 0 | 0 | 1 | 2 |
| 0 | 1 | 0 | 4 |
| 0 | 1 | 1 | 8 |
| 1 | 0 | 0 | 16 |
| 1 | 0 | 1 | 32 |
| 1 | 1 | 0 | 64 |
| 1 | 1 | 1 | 128 |
The actual speed of the AD conversion is determined by dividing the chips speed (1Mhz with no external oscillators and no fuse bits programmed) by the division factor.
ADC Comparisons
| Var = read_adc(0x08); if (Var > 200) //very bright PORTA = 0xF6; //9 else if(Var > 180) PORTA = 0xFF; //8 else if(Var > 160) PORTA = 0x32; //7 else if(Var > 140) PORTA = 0xEE; //6 else if(Var > 120) PORTA = 0xE6; //5 average room lighting else if(Var > 100) PORTA = 0xD2; //4 else if(Var > 80) PORTA = 0xB6; //3 else if(Var > 60) PORTA = 0xBC; //2 else if(Var > 40) PORTA = 0x12; //1 else PORTA = 0x7E; //0 very dim |
| Description | Qty | Manufact. Part # | Supplier Part # | Cost | Supplier |
| Atmel Tiny26L Microcontroller kit from Oregon State University: | 1 | TekBots | |||
| Atmel Tiny26L chip | 1 | Digi-Key | |||
| 5V Linear Regulator | 1 | LM78L05 | LM78L05ACZFS-ND | Digi-Key | |
| ISP connector, 2.5 pin, boxed | 1 | Digi-Key | |||
| 1nF 100V Capacitor 10% | 1 | D102K20Y5PH63L6R | 1445PH-ND | $0.12 | Digi-Key |
| 0.1uf Decoupling Capacitor | 3 | Digi-Key | |||
| .33uF 50V Capacitor Z5U 20% | 1 | Digi-Key | |||
| CONN HEADER .100 SNGL STR 36POS | 1 | Digi-Key | |||
| 100 kOhm resistor, 1/6 watt | 1 | Digi-Key | |||
| AVR Parallel Port Programmer w/ Cable (Kanda STK200 programmer) | 1 | TekBots | |||
| Fairchild 7-segment LED display () | 1 | MAN6980 | Digi-Key | ||
| 100 Ohm resistor, 1/2 watt | 7 | Digi-Key | |||
| 1k Ohm resistor, 1/2 watt (these will depend on what sort of sensor you use) | 2 | Digi-Key |
Copyright 2006 Paul Filitchkin