[095] Budujemy termostat - cz. 3
![[095] Budujemy termostat - cz. 3](/_next/image?url=https%3A%2F%2Farduino.pl%2Fimgproxy%2F8Qen9rVuGqdv-qS3q8Ay4yaf_d_fhqDX7tHLn4tnRis%2Ff%3Awebp%2Fw%3A1200%2FbG9jYWw6Ly8vaW1hZ2VzLzBjLTY3L2JjZDM3LzY3YjQ4LzBjLTY3YmNkMzc2N2I0OGQzMDIyMzI4MjUucG5n.webp&w=3840&q=75)
Żeby nie było – nie jest tak, że nie nadaje się bezwzględnie, ale sprawia problemy natury logicznej. Ale od początku. W poprzednim artykule stworzyliśmy termostat ustawiany za pomocą potencjometru – jak to zwykle bywa w przypadku grzejników, choć formalnie tam najczęściej nie używa się potencjometrów, ale z zewnątrz wygląda to tak samo. Jest to wygodne i intuicyjne, ale ma jedną wadę. Jest egoistyczne – to znaczy, że nie da się nastaw dokonywanych potencjometrem dokonywać równocześnie jeszcze w inny sposób. Dlaczego? Nie mamy władzy nad gałką, którą można przestawiać tylko ręką. Owszem, istnieją potencjometry z silnikiem, które można aktualizować niezależnie, ale to zbyt drogie rozwiązanie do takich zadań. Cokolwiek nastawimy za pomocą potencjometru, musi takim pozostać, bo żadna siła nie przekręci jego gałki, gdy jakiś alternatywny czynnik wpłynie na zmianę nastawionej wartości. Dlatego powstały enkodery. Zachowują się – logicznie – jak potencjometry, ale nie mają wskaźnika, obracają się dookoła i ich położenie rzeczywiste nic nie oznacza. Wykorzystuje się tam fakt relatywnych zmian tylko podczas kręcenia. Nastawy dokonywane za pomocą enkodera można uzupełniać innymi źródłami.
Na płytce TME nie mamy jednak enkodera, a klawiaturkę. W przypadku termostatu klawiatura będzie równie dobra.

Te dwa przyciski na dole i na górze będą zmieniać temperaturę termostatu, jeden będzie ją zwiększał o pół stopnia, drugi – zmniejszał. Pół stopnia to akurat w sam raz do takich celów, lecz jeśli ktoś zechce, będzie sobie mógł przedział zmienić. Przemeblujmy więc program.
#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 w jednostkach rzeczywistych - stopniach Celsiusza.
const byte plus = 3; // Adres przycisku zwiększającego wartość oczekiwanej temperatury.
const byte minus = 2; // Adres przycisku zmniejszającego wartość oczekiwanej temperatury.
float temperaturaNastawiona = 20; // Temperatura w jednostkach rzeczywistych - stopniach Celsiusza.
const byte przekaznik = 4; // Adres przekaźnika.
void setup() {
lcd.begin(16, 2); // Inicjuj wyświetlacz: 16 kolumn, 2 wiersze
pinMode(plus, INPUT_PULLUP); // Deklaruj pin plus jako wejście.
pinMode(minus, INPUT_PULLUP); // Deklaruj pin minus jako wejście.
pinMode(przekaznik, OUTPUT); // Deklaruj pin przekaźnika jako wyjście.
wyswietlTermostat(); // Wyświetl wartość termostatu.
}
void loop() {
temperaturaZmierzona = (analogRead(termometr) * 0.125 - 22.0); // Zmierz temperaturę i przenieś ją do zmiennej temperaturaZmierzona.
lcd.setCursor(0, 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.
wyswietlJednostke(); // Wyświetl znak stopnia.
if (digitalRead(plus) == HIGH && temperaturaNastawiona < 30) { // Jeśli wciśnięto plus i temperatura nastawiona jest niższa od 30 stopni...
temperaturaNastawiona = temperaturaNastawiona + 0.5; // Zwiększ temperaturę termostatu o pół stopnia.
wyswietlTermostat(); // Wyświetl temperaturę termostatu.
while (digitalRead(plus) == HIGH) {} // Czekaj na zwolnienie przycisku.
}
if (digitalRead(minus) == HIGH && temperaturaNastawiona > 10) { // Jeśli wciśnięto minus i temperatura nastawiona jest wyższa od 10 stopni...
temperaturaNastawiona = temperaturaNastawiona - 0.5; // Zwiększ temperaturę termostatu o pół stopnia.
wyswietlTermostat(); // Wyświetl temperaturę termostatu.
while (digitalRead(minus) == HIGH) {} // Czekaj na zwolnienie przycisku.
}
if (temperaturaZmierzona < (temperaturaNastawiona - 0.5)) { // Jeśli temperatura zmierzona jest mniejsza o pół stopnia od nastawionej, to...
digitalWrite(przekaznik, HIGH); // Włącz przekaźnik.
lcd.setCursor(15, 0); // Ustaw kursor na końcu wyświetlacza.
lcd.print("*"); // Wyświetl gwiazdkę.
}
if (temperaturaZmierzona > (temperaturaNastawiona + 0.5)) { // Jeśli temperatura zmierzona jest większa o pół stopnia od nastawionej, to...
digitalWrite(przekaznik, LOW); // Wyłącz przekaźnik.
lcd.setCursor(15, 0); // Ustaw kursor na końcu wyświetlacza.
lcd.print(" "); // Wygaś gwiazdkę.
}
delay(100); // Pętla opóźniająca.
}
void wyswietlTermostat() {
lcd.setCursor(0, 1); // Ustaw kursor na początku wyświetlacza.
lcd.print("Term: "); // Wyświetl napis "Term: "
lcd.print(temperaturaNastawiona, 1); // Wyświetl temperaturę z dokładnością do jednego miejsca po przecinku.
wyswietlJednostke(); // Wyświetl znak stopnia.
}
void wyswietlJednostke() {
lcd.print(" "); // Wyświetl spację.
lcd.write(223); // Wyświetl znak stopnia.
lcd.print("C "); // Wyświetl literę C i dwie spacje.
}
Usuńmy wszystkie wpisy związane z potencjometrem i powołajmy do życia dwa przyciski: minus i plus. Nieszczęśliwie ich adresy wchodzą w konflikt z adresami przekaźników. Na szczęście na płytce umieszczono krosownicę, więc przeniosłem przyciski pod piny 2 i 3.

Wymienimy blok zmieniający temperaturę termostatu. Będzie się składał z dwóch bliźniaków:
if (digitalRead(plus) == HIGH && temperaturaNastawiona < 30) { // Jeśli wciśnięto plus i temperatura nastawiona jest niższa od 30 stopni...
temperaturaNastawiona = temperaturaNastawiona + 0.5; // Zwiększ temperaturę termostatu o pół stopnia.
wyswietlTermostat(); // Wyświetl temperaturę termostatu.
while (digitalRead(plus) == HIGH) {} // Czekaj na zwolnienie przycisku.
}
if (digitalRead(minus) == HIGH && temperaturaNastawiona > 10) { // Jeśli wciśnięto minus i temperatura nastawiona jest wyższa od 10 stopni...
temperaturaNastawiona = temperaturaNastawiona - 0.5; // Zwiększ temperaturę termostatu o pół stopnia.
wyswietlTermostat(); // Wyświetl temperaturę termostatu.
while (digitalRead(minus) == HIGH) {} // Czekaj na zwolnienie przycisku.
}
Każdorazowe wciśnięcie wybranego przycisku zwiększy bądź zmniejszy zmienną temperaturaNastawiona o wybrany interwał – tu: pół stopnia. Ale to nie wszystko, w warunkach jest jeszcze drugi człon, który sprawdza, czy nie przekroczyliśmy założonego przedziału od 10 do 30 stopni. Jeśli znajdziemy się na którymś z progów, dalsze zmiany będą niemożliwe. Oczywiście te wartości także można zmienić według upodobań.
Reszta programu jest podobna, jak to było w wersji z potencjometrem, z tym że teraz co się dało, przeniosłem do podprogramów. Ponieważ uaktualnianie wartości termostatu następuje wyłącznie po wciśnięciu przycisku, w pętli setup trzeba wymusić jednorazowe wejście w procedurę druku wartości termostatu zaraz po resecie. Tę zresztą należy zadeklarować w definicjach i ja tu wstawiłem wartość dwudziestu stopni.
Po kompilacji otrzymamy bliźniaczy projekt przekaźnika, który teraz używa klawiatury zamiast gałki. Trzeba pamiętać o jednej ważnej sprawie: po resecie temperatura będzie zawsze zerowana do pozycji zadeklarowanej w programie, czyli tutaj: 20 stopni. Jeśli chcielibyśmy ją pamiętać, należałoby zatrudnić pamięć nieulotną znajdującą się w mikrokontrolerze. Ale ten projekt ma służyć czemuś innemu, więc to nie będzie konieczne.

Zanim opuścimy nasz projekt, wymieńmy stare dobre Arduino Uno na wersję R4 z WiFi na pokładzie, która pasuje do płytki TME, będąc z nią w pełni kompatybilną. Dla pewności skompilujmy projekt ponownie, patrząc czy zachowa się tak samo.
W kolejnym artykule opuścimy na chwilę naszą płytkę i skierujmy się do arduinowej chmury. Pisałem o niej ponad rok temu i wracając tam ponownie, zauważyłem że sporo spraw jest już nieaktualnych – trzeba będzie więc kilka rzeczy przypomnieć sobie.