W drugiej części poradnika zajmiemy się napisaniem programu i krótkiego progamu do pomiaru temperatury za pomocą termistora. Niezbędny nam będzie oczywiście termistor – wykorzystamy termistor NTC (1o kΩ). Zaprzęgniemy też do pracy mikrokontroler ATmega8, a dla wizualizacji wyników podłączymy wyświetlacz LCD 16×2. Schemat połączeń przedstawia Rysunek 1.
Podłączenie termistora do mikrokontrolera poprzez dzielnik napięcia (zgodnie z rozważaniami w poprzednim wpisie). Ze względu na wykorzystywany termistor (10kΩ) zastosowanow dzielniku rezsytor o tej samej rezystancji – 10kΩ. Wyniki prezentować będziemy na wyświetlaczu LCD 16×2 (za obsługę wyświetlacza odpowiadają biblioteki M. Kardasia z tzw. Bluebooka).
Do pomiaru temperatury napisałem bibliotekę – thermistor (zawierajacą dwa pliki: thermistor.c i thermistor.h). Biblioteka umożliwia wywołanie siedmiu funkcji:
- funkcja inicjująca działanie przetwornika analogowo-cyfrowego:
void thermistor_init(void) - funkcje wykonujące pomiar temperatury i zwracająca wynik (jako typ float) w wybranej skali temperatur (K – Kelwiny, C – stopnie Celsjusza, F – stopnie Fahrenheita). Jako argument, do funkcji przekazujemy numer kanału przetwornika, na którym dokonujemy pomiaru.
float get_temperature_K_float(uint8_t ADC_channel);
float get_temperature_C_float(uint8_t ADC_channel);
float get_temperature_F_float(uint8_t ADC_channel);
- funkcja wykonująca pomiar temperatury i zwracająca wynik (jako tablicę znaków) w wybranej skali temperatur (K – Kelwiny, C – stopnie Celsjusza, F – stopnie Fahrenheita). Jako argument, do funkcji przekazujemy numer kanału przetwornika, na którym dokonujemy pomiaru oraz liczbę miejsc dziesiętnych, do których ma zostać zaokrąglony wynik pomiaru. Funkcja zwracająca tablicę znaków jest niezwykle przydatna, gdy chcemy wyświetlać wynik np. na wyświetlaczu 16×2.
char get_temperature_K_string(uint8_t ADC_channel, uint8_t decimal);
char get_temperature_C_string(uint8_t ADC_channel, uint8_t decimal);
char get_temperature_F_string(uint8_t ADC_channel, uint8_t decimal);
thermistor.h
#ifndef THERMISTOR_H_ #define THERMISTOR_H_ #define beta 3950 // stała materiałowa termistora [K] #define T0 298 // temperatura odniesienia (zwykle 298K) [K] #define R0 10000 // rezystancja termistora w temperaturze odniesienia [Ω] #define R 10000 // rezystancja opornika w dzielniku [Ω]
void thermistor_init(void); float get_temperature_K_float(uint8_t ADC_channel); float get_temperature_C_float(uint8_t ADC_channel); float get_temperature_F_float(uint8_t ADC_channel); char get_temperature_K_string(uint8_t ADC_channel, uint8_t decimal); char get_temperature_C_string(uint8_t ADC_channel, uint8_t decimal); char get_temperature_F_string(uint8_t ADC_channel, uint8_t decimal); #endif /* THERMISTOR_H_ */
W pliku nagłówkowym podajemy wartości charakterystyczne dla termistora oraz rezystancję opornika w dzielniku .
thermistor.c
void thermistor_init(void){ ADMUX |= (1<<REFS0); // ustawienie napięcia odniesienia dla ADC (5V) ADCSRA |= (1<<ADEN) | (1<<ADPS1)|(1<<ADPS2); // uruchomienie ADC + ustawienie preskalera na 64 }
Funckja thermistor_init inicjalizuje (uruchamia) przetwornik analogowo-cyfrowy znajdujący się na pokładzie ATmegi.
float get_temperature_K_float(uint8_t ADC_channel){ ADMUX = (ADMUX & 0xF8)|ADC_channel; // pomiar ADC ADCSRA |= (1<<ADSC); // pomiar ADC while(ADCSRA & (1<<ADSC)); // pomiar ADC t=1024-ADCW; t= t/ADCW; t= log(t); t=t + beta/T0; t=beta/t; return t; }
Pierwsze 3 linie kodu funkcji get_temperature_K_float odpowiedzialne są za wykonanie pomiaru na wskazanym kanale przetwornika ADC. Następnie uzyskana wartość zamieniana jest na wartość temperatury (w odpowiedniej skali). Oczywiście zapis obliczeń można uprościć, jednak zachowałem kilka linijek więcej w celu poprawy czytelności i zrozumienia kodu.
char get_temperature_K_string(uint8_t ADC_channel, uint8_t decimal){ dtostrf(get_temperature_K_float(ADC_channel),1,decimal,temp); return temp; }
Funkcja get_temperature_K_string zwraca tablicę znaków, którą następnie możemy wyświetlić np. na wyświetlaczu. Do zamiany liczby zmiennoprzecinkowej na łańcuch znaków używamy funkcji dtostrf. Jadnym z jej argumentów, który musimy podać jest liczba miejsc po przecinku, które chcemy uzyskać po konwersji – odpowiada za to argument decimal.
main.c
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include „lcd44780.h”
#include „thermistor.h”
int main(void){
lcd_init();
thermistor_init();
while(1){
lcd_locate(0,0);
lcd_str(get_temperature_K_string(0,1));
lcd_str(” K”);
lcd_locate(0,8);
lcd_str(get_temperature_C_string(0,2));
lcd_str(” C”);
lcd_locate(1,0);
lcd_str(get_temperature_F_string(0,2));
lcd_str(” F „);
_delay_ms(100);
}
}
Funkcja główna main.c korzysta z biblioteki do obsługi wyświetlacza lcd44780.h. i wyświetla aktualną temperaturę na podłączonym wyświetlaczu LCD 16×2. Pracę układu przedstawia filmik. Cały układ został zmontowany na płytce uniwersalnej zl2avr firmy Kamami. Jak widać układ spisuje się całkiem nieźle. Jedynym minusem jest dość duże zużycie pamięci mikrokontrolera (ze względu na operacje zmiennoprzecinkowe – w szczególności logarytmowanie). Po skompilowaniu program zajmuje ok. 50% pamięci.
Enjoy!