My Link


Thermometer dengan AVR


I bought the LED module from BanMor' last week, just 30Baht. The moduleprovide a prewired multiplex of 4-digit common anode LED, that's great.See the soldering pad of these signal in the 1st picture below. I thought,my friend gave me the AT90S2313 chip, and with a simple homemade ISP cableand a free software AVR ISP downloader, so we don't need the device programmer.Also I got the DS1820 from my friend. So I spent my freetime weekend puttingthem together, "the AVR Thermometer". The 2nd picture shows a samplecircuit using universal PCB, see the upper right, it was 10-pin headerfor STK200 compatible downloader. Of course the LED module was designedfor CLOCK display, so you may interested in writing C program for bothClock and Temperature display after built this project.


The circuit diagram is straight forward, similar to 89C2051Clock Circuit. PORTB sinks forward current of each LED segmentthrough a 220 Ohms resistor. The common anode pin for each digit is controlledby PORTD, i.e., PD2-PD5. The PNP transistor can be any types of small signaltransistor. S1-S4 are optional keypad. Also PD6 is optional output. Allof LEDs are driven with sink current.

The temperature sensor chip, DS1820 is connected to PD1 with a 4.7kpull-up resistor. The example of circuit uses only one sensor, you maytie multiple sensors on the same line and modify the program to read itwith the help of internal chip ID.

J3 is AVR ISP/STK200 compatible downloader. See the pin designationand build the cable from Experimentingthe AT90S8535 with CodeVisionAVR C Compiler

The software for download the hex code, thermo.hexto the 2313 chip, can get from ATMEL FTP website here ATMELAVR ISP.


The source porgram was written in C language and compiled with AVR CodeVisionC compiler. Actually my first try used the AT90S8535, then I moved theC code from 8535 to 2313 with a bit modification.

The program was foreground and background running, or interrupt driven.The background task is forever loop scanning 4-digit LED.

while (1)
scanLED(); // run background task forever

The function scan display was borrowed from 89C2051 Clock controller.(Actuallyno need any modifications if we use a preprocessor to define such I/O port.)

#define segment PORTB
#define LED_digit PORTD

void scanLED() /* scan 4-digit LED and 4-key switch, if key pressedkey = 0-3
else key = -1 */
// adapted from 89C2051 project if needs scan key, find onebit input port
char i;
digit = 0x20;
key = -1;
for( i = 0; i <>
LED_digit = ~digit; /* send complement[digit] */
segment = ~heat[i]; /* send complement[segment] */
delay_ms(1); /* delay a while */
segment = 0xff; /* off LED */
// if ((PORTD & 0x10)== 0) /* if key pressed P3.4 became low */
// key =i; /* save key position to key variable*/
digit>>=1; /* next digit */

for-loop statement provides 4-cycle scanning from digit0 to digit3.First we activate digit control line by sending complement of digit variable.Follow with segment data from heat[i] array. The delay 1ms provides enoughtime for electron to jump back to ground state converting to electromagneticradiation. Then turn off before changing digit. The digit data is thenshifted to the right one bit. Similarly for the next digit.

The foreground task is entered by timer0 interrupt every 1/15 s. Timer0get the internal clock from 4MHz/1024 or 3906Hz. So with an 8-bit timer0counting up from 0 to 255 and set interrupt flag from 255 to 0 transition,the rate of interrupt will be 3906Hz/256 or 15Hz.

I used a global variable "tick" for counting a number of interrupt entering.See below, when tick equal to 15 or one second has elapsed then functionread_temp() will be executed.

// Timer 0 overflowinterrupt service routine
// timer interrupt every 1/15 sec provides foreground taskto be run periodically.

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
switch (++tick){
case 15: tick = 0;

When read_temp() function has entered, I used another global variablefor couting up task that needs time
more than a second. The xtimer variable will count up until reachs5, or 5s, it will read data from DS1820, performs 5-point moving averageand convert the value to 7-segment pattern then.

if(++xtimer1 >=5)
xtimer1 = 0;
segment = 0xff; // turn segment off
T = ds1820_temperature_10(0)/10; // read DS1820 every 5 sec.
LPF(); //enter digital filter providing slowly change of temperature.
heatToBuffer(); // convert it

The function ds1820_temperature_10(0) was provided by CodeVision library.

See below what function of LPF() is;

LPF() // performs five-point movingaverage
X1= T;
T = (X1+X2+X3+X4+X5)/5;

T is computed from 5-point consecutive data.

The heatToBuffer() is the function that converts signed number T to7-segment LED pattern.

void heatToBuffer()
heat[3] = 0x40; // yes, negative, put -
heat[0] = 0x39; // C

T = abs(T); // get only amplitude
heat[1] = convert[T%10];
heat[2] = convert[T/10];
if (heat[2] == 0x3f)
heat[2] = 0; // off msd
heat[0] = 0x39; // C

heat[3] = convert[T/100];
temp = T%100;
heat[1] = convert[temp%10];
heat[2] = convert[temp/10];
// off msd
if (heat[3] == 0x3f)
heat[3] = 0;
if(heat[2] == 0x3f)
heat[2] = 0;

Reading data from 1-wire interface device, DS1820, takes about 0.2s, so when the program enter 1-wire connecting, the display will turn off, say 0.2s. Also the function that reads DS1820 will disable any interrupt, so we then loss such period of time.

Sample display shows 34 Celsius. DS1820 is located at bottom right.

Source codethermo.c
Intel Hex file thermo.hex
ATMEL generic ROM filethermo.rom

0 komentar: