[093] Budujemy termostat - cz. 1

[093] Budujemy termostat - cz. 1

Jak to zwykle bywa w moich artykułach, będą nam towarzyszyć dwie myśli: jak zbudować taki po prostu zwyczajny termostat i jak budować projekty w sposób wygodny i dający satysfakcję w postaci widocznych postępów zdążających do celu. Mało tego, w połowie drogi przypląta się myśl trzecia: jak projekty lokalne przekształcić w zdalne? Ale to później. Najpierw odpowiedzmy sobie na pytanie: dlaczego często bywa tak, że za coś się zabieramy i pozostawiamy to niedokończone? Zwykle dlatego, że chcemy od razu stworzyć skończony projekt i jeśli gdzieś znajduje się słaby punkt, możemy go nie zauważyć, a późniejsze poszukiwania przyczyn dlaczego coś nie działa stają się nużące i w rezultacie z pomysłu – nici.


Dobry nawyk to rozbicie procesu powstawania urządzenia na kolejne etapy. Niektóre z nich wręcz w ogóle nie będą elementem finałowego dzieła i posłużą nam wyłącznie do weryfikacji etapu krytycznego. Ale najlepiej to wszystko obserwować na konkretach, dlatego czas wziąć się do roboty.

Bohaterem najbliższych rozważań będzie prosty termostat, czyli urządzenie, które może sterować na przykład grzejnikiem elektrycznym, włączając go, gdy temperatura otoczenia spadnie poniżej zadanej i wyłączając – gdy odpowiednio wzrośnie. Do jego budowy użyję Arduino Uno oraz płytki edukacyjnej TME, na której siedzi wyświetlacz, termometr, potencjometr, przyciski, a także replikator gniazda, w które mogę wstawić płytkę z przekaźnikami. To wszystko oczywiście można podłączyć na piechotę jako niezależne elementy i będę o tym wspominał, omawiając kolejne etapy. Zacznijmy więc od etapu pierwszego, czyli nawiązania współpracy z wyświetlaczem.

Wyświetlacz na mojej płytce to klasyczny HD44780 sprzężony z ekspanderem I2C, dzięki czemu do rozmów potrzebuje tylko dwóch linii, a nie sześciu. Ekspandery takie produkuje wiele firm i wiele też możemy znaleźć konfiguracji. MCP23008 oferuje osiem linii pracujących w dowolną stronę, z możliwością polaryzacji wejścia i generowania przerwań. Układ może przyjmować jeden z ośmiu adresów, więc kostek takich można posadzić obok siebie osiem. Pisałem o nim w artykule o magistrali I2C i tam zapraszam po szczegóły, a także opis jak to wszystko ze sobą połączyć.

#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze 44780
#include <hd44780ioClass/hd44780_I2Cexp.h>                             // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD

void setup() {
  lcd.begin(16, 2);           // Inicjuj wyświetlacz: 16 kolumn, 2 wiersze
  lcd.setCursor(2, 0);        // Ustaw kursor na wybranej pozycji wyświetlacza.
  lcd.print("Dzien dobry!");  // Wyświetl napis.
}

void loop() {
}

Nasz pierwszy szkic nawiąże współpracę z wyświetlaczem. Do tego będziemy potrzebować: biblioteki obsługującej magistralę Wire.h, sam wyświetlacz po tejże hd44780.h, oraz dodatkowy element związany z układem MCP23008, bo jak mówiłem – jest ich więcej. Na początku zadeklarujemy też sposób połączenia wyświetlacza z ekspanderem – nóżka po nóżce.

Program właściwy to prawie nic. Deklarujemy wymiary wyświetlacza – szesnaście znaków w dwóch wierszach, ustawiamy kursor na trzeciej pozycji pierwszego wiersza, pamiętając, że pozycje liczymy od zerowej i wyświetlamy napis Dzień dobry! Po co? Żeby wiedzieć, że wyświetlacz działa i mamy nad nim władzę. I to jest właśnie ten element, o którym wspominałem: z pozoru zbędna czynność wyeliminuje ryzyko, że w gotowym projekcie będzie ciemno i tak naprawdę nie wiadomo co będzie temu winne.

Dodam jeszcze, że wcale nie mamy obowiązku używania wyświetlaczy z ekspanderem. Można z powodzeniem użyć takiego, który wymaga sześciu linii, łącząc go bezpośrednio z wolnymi pinami. O tym także kiedyś już pisałem i tam po szczegóły zapraszam. Skoro ktoś nas tu przywitał, można pójść dalej. Zainteresujmy się termometrem.

Na płytce TME osadzono analogowy termometr, czyli pozbawiony magistrali, a oferujący napięcie zależne od temperatury. MPC9701 jest tak naprawdę liniowym termistorem i by móc odczytać temperaturę, trzeba mierzyć napięcie na jego wyjściu za pomocą wbudowanego w mikrokontroler przetwornika. Połączono go do pinu A2, dodatkowo jeszcze przez separujący wzmacniacz operacyjny, ale przy oczekiwanej dokładności nie jest on niezbędny.

#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze 44780
#include <hd44780ioClass/hd44780_I2Cexp.h>                             // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD

const byte termometr = A2;   // Adres czujnika temperatury.
float temperaturaZmierzona;  // Temperatura zmierzona w jednostkach rzeczywistych - stopniach Celsiusza.

void setup() {
  lcd.begin(16, 2);  // Inicjuj wyświetlacz: 16 kolumn, 2 wiersze
}

void loop() {
  temperaturaZmierzona = (analogRead(termometr) * 0.125 - 22.0);  // Zmierz temperaturę i przenieś ją do zmiennej temperaturaZmierzona.
  lcd.setCursor(1, 0);                                            // Ustaw kursor na początku wyświetlacza.
  lcd.print("Temp: ");                                            // Wyświetl napis "Temp: ".
  lcd.print(temperaturaZmierzona, 1);                             // Wyświetl temperaturę z dokładnością do jednego miejsca po przecinku.
  lcd.print(" ");                                                 // Wyświetl spację.
  lcd.write(223);                                                 // Wyświetl znak stopnia.
  lcd.print("C  ");                                               // Wyświetl literę C i dwie spacje.
  delay(250);                                                     // Pętla opóźniająca.
}

Temperaturę będziemy przechowywać w zmiennej zmiennoprzecinkowej temperaturaZmierzona, bo przyjąłem operować z dokładnością do dziesiątej części stopnia. Co prawda w wymaganym przedziale – zakładam od 10 do 30 stopni, z dokładnością 1/10 stopnia, mamy dwieście pozycji, więc wystarczyłaby zmienna ośmiobitowa, ale wolę operować jednostkami ludzkimi, czyli stopniami Celsiusza, a nie jakimś dziwolągiem wymagającym ciągłego przeliczania.

Dlatego też pierwszą instrukcją po odczytaniu napięcia z termometru będzie operacja matematyczna według nieco zawiłego wzoru pobranego z dokumentacji układu termometru, która zgrabnie przeliczy nam napięcie na temperaturę. Tę, jak wspominałem, umieścimy w zmiennej temperaturaZmierzona. Teraz, już w pętli ciągłej, będziemy ustawiać się prawie na początku wyświetlacza, wysyłać napis Temp: – skrót od temperatury, bo cały wyraz z jednostkami nie zmieści się, temperaturę – jak widać, ograniczoną do jednego miejsca po przecinku oraz dodatkowe znaki, przy czym znak stopnia będziemy mogli uzyskać wysyłając na wyświetlacz jego kod o wartości 223. W niektórych wyświetlaczach może być on inny. Przypomnę przy okazji, że cyfra w linii lcd.print(temperaturaZmierzona, 1); oznacza ilość miejsc po przecinku, a jej brak przyjmie wartość domyślną – dwóch miejsc. Zwróćmy uwagę, że wynik został tu sformatowany i zaokrąglony, ale w pamięci przechowuje się go z dokładnością typową dla zmiennej float. Na końcu siedzi sobie pętla opóźniająca, żeby wynik nie latał jak oszalały. Po kompilacji powinniśmy ujrzeć taki termometr.

Skoro udało się dotrzeć do tego etapu, skądinąd już użytecznego, czas zbudować termostat właściwy. Też etapami. Ale o tym napiszę w kolejnym artykule.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2025 arduino.pl