Zegar Basenowy, Godzina, data, temperatura i wilgotność przy użyciu wyświetlacza MAX7219, DHT11, RTC DS321

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:

Schemat połączenia całości będzie wyglądać następująco:

Schemat połączenia zegar basenowy

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 😉

Animacja MAX7219

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<

Odpowiedz

Twój adres e-mail nie zostanie opublikowany