W tym artykule wykonamy projekt zegara takiego jak często spotykamy na basenach, będzie wyświetlał godzinę oraz aktualną temperaturę i wilgotność powietrza. Godzinę będziemy pobierać z modułu RTC DS3231, jego obsługę opisujemy w osobnym artykule do przeczytania tutaj:
Jak podłączyć RTC DS3231 do Arduino
Wykorzystanie czujników DHT11 i DHT22 również opisywaliśmy we wcześniejszym artykule do przeczytania na naszym blogu tutaj:
Odczytywanie temperatury i wilgotności DHT11 i DHT22 Arduino poradnik
Teraz czas dołożyć wyświetlacz MAX7219 8×32, połączyć wiedzę i przekuć to w jeden użyteczny projekt. Każdy segment tego wyświetlacza składa się z punktów na matrycy 8×8. Do komunikacji wykorzystamy protokół SPI i zasilimy wyświetlacz na potrzeby tego projektu z pinu 5V naszego Arduino. Należy mieć na uwadze, że jeśli nie potrzebujemy pokazywać wilgotności to możemy wykorzystać do pomiaru temperatury wbudowany czujnik w naszym RTC jednak ze względów edukacyjnych wykorzystamy w tym projekcie DHT.
Lista modułów wykorzystanych w projekcie z linkami do sklepu:
- Arduino UNO R3 wymienny procesor z kablem
- Zegar czasu rzeczywistego RTC DS3231
- Płytka stykowa uniwersalna MB-102
- Czujnik wilgotności i temperatury DHT11 lub
- Czujnik wilgotności i temperatury DHT22
- Przewody połączeniowe kable Arduino męsko-męskie 20 cm 40 sztuk
Schemat połączenia całości będzie wyglądać następująco:
Modyfikacje jakie można wprowadzić, to podpiąć RTC pod gniazdo zasilania 5V ponieważ toleruje on zarówno 5V jak i 3.3V. Również czujniki DHT pozwalają na odczyt bez rezystora podciągającego ale robiąc wszystko książkowo powinno się go zastosować. Zegar RTC łączymy przy pomocy magistrali I2C SDA z SDA i SCL z SCL.
Podsumowując wszystko zasilamy z 5V dodatkowo łączymy:
- (MAX7219) CLK <-> 11 (Arduino)
- (MAX7219) CS <-> 10 (Arduino)
- (MAX7219) DIN <-> 12 (Arduino)
- (DS3231) SDA <-> SDA (Arduino)
- (DS3231) SCL <-> SCL (Arduino)
- (DHT) Data (2) <-> 2 (Arduino)
Po połączeniu modułów uruchamiamy Arduino IDE i instalujemy biblioteki:
- MD_MAX72XX
- MA_MAXPanel
- MD_PAROLA
- DHT sensor library
- RTC obsługujemy z biblioteki do pobrania tutaj >klik<
Przechodzimy do pisania kodu, początkowo dodajemy potrzebne biblioteki:
//import bibliotek
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <DHT.h>
//zegar RTC
#include <DS3231.h>
#include <Wire.h>
DS3231 rtc(SDA,SCL);
// definiujemy piny dla DHT i wyświetlacza
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW //FC16_HW - model sprzedawanego u nas modułu
#define MAX_DEVICES 4 //ilość podpiętych w szeregu wyświetlaczy
#define CS_PIN 10
DHT dht(2,DHT11); //ustawiamy pin dla czujnika i jego model jeśli wykorzystujesz DHT22 to taki podaj
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES); //deklarujemy obiekt mx
MD_Parola mojWyswietlacz = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); //deklarujemy obiekt mojWyswietlacz
Teraz przychodzi kolej na sekcje void setup() , w niej zainicjalizujemy wykorzystane wcześniej biblioteki:
Serial.begin(9600); //inicjalizujemy serial monitor
dht.begin(); //inicjalizujemy czujnik DHT
rtc.begin(); //inicjalizujemy zegar RTC
mojWyswietlacz.begin(); //inicjalizujemy wyswietlacz
mojWyswietlacz.setIntensity(0); //ustawiamy jasnosc wyswietlacza z zakresu 0 do 15
mojWyswietlacz.displayClear(); //czyscimy wyswietlacz
Kolejno w sekcji void loop() piszemy właściwy wykonywany w pętli kod:
//zapisujemy temperature i wilgotnosc z dht do zmiennych
String temp = String(dht.readTemperature()); //konwertujemy odczyt temperatury i wilgotnosci na String
String hum =String(dht.readHumidity());
//zapisujemy godzine i date do zmiennych
String godzina = rtc.getTimeStr(1);
String data = rtc.getDateStr(FORMAT_SHORT,FORMAT_LITTLEENDIAN);
data.remove(5,6); //skracamy date z formatu dd.mm.yyy do dd.mm
//funkcja remove wycina 6 znaków zaczynajac od 5 pozycji
temp.remove(2,6); //usuwamy miejsca po przecinku
hum.remove(2,6); //usuwamy miejsca po przecinku
// PONIŻSZA CZĘŚĆ KODU WYŚWIETLA W ZADANYCH ODSTĘPACH CZASOWYCH
mojWyswietlacz.setTextAlignment(PA_CENTER);//ustawia text na srodku
mojWyswietlacz.print(godzina); //wyswietla godzine
delay(4000); //czeka 4 sekundy
mojWyswietlacz.setTextAlignment(PA_LEFT);
mojWyswietlacz.print("T: " + temp);
delay(2000);
mojWyswietlacz.setTextAlignment(PA_RIGHT);
mojWyswietlacz.print("H: " + hum + "%");
delay(2000);
mojWyswietlacz.setTextAlignment(PA_CENTER);
mojWyswietlacz.print(data);
delay(2000);
}
Musimy pamiętać, że w tym wypadku funkcja print wyświetlacza wymaga od nas podania danych w formie tekstowej String dlatego musimy konwertować dane aby poprawnie się wyświetliły. Kompletny plik z kodem do pobrania znajdziesz na końcu artykułu.
Wyświetlanie z animacją
Teraz weźmiemy się za bardziej zaawansowaną technikę wyświetlania danych animując je. Biblioteka Parola przygotowała dla nas szereg gotowych animacji. Możemy również pisać swoje funkcje animacji, w nowszych wersjach biblioteki dodane zostało również animowanie poszczególnych stref, więc możemy obsługiwać każdy segment w indywidualny sposób.
Poniżej podaję listę dostępnych animacji:
PA_PRINT,
PA_SCAN_HORIZ,
PA_SCROLL_LEFT,
PA_WIPE,
PA_SCROLL_UP_LEFT,
PA_SCROLL_UP,
PA_OPENING_CURSOR,
PA_GROW_UP,
PA_MESH,
PA_SCROLL_UP_RIGHT,
PA_BLINDS,
PA_CLOSING,
PA_RANDOM,
PA_GROW_DOWN,
PA_SCAN_VERT,
PA_SCROLL_DOWN_LEFT,
PA_WIPE_CURSOR,
PA_DISSOLVE,
PA_OPENING,
PA_CLOSING_CURSOR,
PA_SCROLL_DOWN_RIGHT,
PA_SCROLL_RIGHT,
PA_SLICE,
PA_SCROLL_DOWN
Funkcja pozwalająca animować to co chcemy wypisać na wyświetlacz składa się z następujących argumentów:
mojWyswietlacz.displayText(dane do wyświetlenia const char, wyrownanie tekstu, szybkosc animacji, pauza, efekt animacji wejsciowy, efekt animacji wejsciowy);
przykładowo:
mojWyswietlacz.displayText(temp.c_str(), PA_CENTER, 50, 5000, PA_SCROLL_UP, PA_CLOSING);
Ponieważ wymagane jest przekazanie tekstu do wyświetlenia w formie const char, będziemy wykorzystywać z funkcji konwersji c_str().
Animacja wykonuje się w pętli:
if(mojWyswietlacz.displayAnimate()){
mojWyswietlacz.displayText(temp.c_str(), PA_CENTER, 50, 5000, PA_SCROLL_UP, PA_CLOSING);
// mojWyswietlacz.displayReset();
}
Do przełączania między animacjami wykorzystamy pętle switch, dla przypomnienia ma ona następującą strukturę:
switch (var) {
case etykieta1:
// kod do wykonania
break;
case etykieta2:
// kod do wykonania
break;
}
Efekt jaki uzyskamy z naszym kodem można zobaczyć w poniższym gifie 😉
Kod programu przedstawia się następująco:
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <DHT.h>
//zegar RTC
#include <DS3231.h>
#include <Wire.h>
DS3231 rtc(SDA,SCL);
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 10
DHT dht(2,DHT11);
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
MD_Parola mojWyswietlacz = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
int var= 1;
void setup() {
Serial.begin(9600);
dht.begin();
rtc.begin(); //zegar
mojWyswietlacz.begin();
mojWyswietlacz.setIntensity(2);
mojWyswietlacz.displayClear();
}
void loop() {
String temp = String(dht.readTemperature());
String godzina = rtc.getTimeStr(1);
temp.remove(2,5);
temp += " C";
switch (var){
case 1:
if(mojWyswietlacz.displayAnimate()){
mojWyswietlacz.displayText(temp.c_str(), PA_CENTER, 50, 5000, PA_SCROLL_UP, PA_CLOSING);
mojWyswietlacz.displayReset();
var = 2;
break;
}
case 2:
if(mojWyswietlacz.displayAnimate()){
mojWyswietlacz.displayText(godzina.c_str(), PA_CENTER, 50, 5000, PA_SCROLL_UP, PA_SCROLL_DOWN);
var=1;
mojWyswietlacz.displayReset();
break;
}
}
}
Mam nadzieję, że dzięki temu wpisowi wykorzystacie potencjał biblioteki do animacji i zbudujecie na tej podstawie budziki, zegary basenowy, zegar sklepowy albo reklamę świetlną. Czekamy na komentarze, pytania i sugestie. Pomysły na kolejne wpisy również mile widziane!
Jak zawsze zachęcamy do zapisania się do newslettera korzyści Elektroweb, każdy zapisany dostaje co jakiś czas kody promocyjne na zakupy w naszym sklepie internetowym oraz informację o nowościach!
Zapisz się pod tym linkiem: http://elektroweb.pl/newsletter.php
Plik z kodem bez animacji: >klik<
Plik z kodem z animacją: >klik<