Pogodełko – IoT w pogodzie – część 2
Pogodełko, czyli nasza miniaturowa stacja pogodowa w kartonie spotkała się z ciepłym przyjęciem. Złożenie jej nie jest skomplikowane. Wystarczy podłączyć 10 przewodów i gotowe. Wstępnie zaprogramowana płytka NodeMCU V3 od razu pokazuje czy wszystko zostało złożone poprawnie.
W tym artykule omówimy kod źródłowy i pokażemy jak samodzielnie zmodyfikować Pogodełko. A do tej pory modyfikacji widzieliśmy sporo. Najprostszą z nich jest wymiana czujnika Bosch BMP280 na BME280. Uzyskujemy w ten sposób dodatkowy pomiar wilgotności. W następnych częściach przyjrzymy się innym modyfikacjom wartym wspomnienia – dodanie zewnętrznego czujnika temperatury DS18B20 czy czujnika pyłu zawieszonego SDS011.
Pogodełko zostało przygotowane dla osób rozpoczynających przygodę z elektroniką. Wiec w tym artykule zaczynamy od podstaw. Ale takich podstaw-podstaw :)
Przygotowania środowiska programistycznego dla ESP8266 w Arduino IDE
Zakładamy, że masz już pobrane i zainstalowane Arduino IDE. Dla przypomnienia – środowisko programistyczne można pobrać ze strony: www.arduino.cc/en/Main/Software. Wystarczy wybrać odpowiednią wersję i pobrać archiwum zip lub zainstalować. Pracować będziemy na najnowszej stabilnej wersji dostępnej na chwilę pisania tego artykułu – 1.8.5.
Zastosowana w Pogodełku płytka NodeMCU V3 oparta jest o popularny układ ESP8266. Aby móc skompilować kod i zaprogramować płytkę, będziemy potrzebować odpowiednich narzędzi. Na szczęście instalacja nie jest skomplikowana i większość procesu przebiega automatycznie.
- Dodajemy adres URL do menedżera płytek
Menu: Plik > Preferencje
W odpowiednim polu wklejamy adres URL zawierający definicję płytek ESP8266:http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Instalujemy narzędzia potrzebne do obsługi ESP8266.
Menu: Narzędzia > Płytka > Menedżer płytek
Następnie wyszukujemy frazę esp8266 i instalujemy paczkę z narzędziami. - Wybieramy płytkę, którą będziemy programować.
Z menu: Narzędzia > Płytka wybieramy pozycję NodeMCU 1.0 (ESP-12E Module)
- Wybieramy odpowiedni port szeregowy
Z menu: Narzędzia > Port wybieramy odpowiedni port COM. Który dokładnie? Ten, który pojawi się po podłączeniu płytki NodeMCU V3 kablem USB do komputera.
Biblioteki
Pogodełko w podstawowej wersji wykorzystuje kilka bibliotek. Jeżeli ich nie zainstalujemy, kod źródłowy się nie skompiluje. Instalacja nie jest trudna i podobnie jak w przypadku definicji płytek przebiega pół-automatycznie. A jakich dokładnie bibliotek potrzebujemy? Wskazówką będą poniższe linie kodu źródłowego, w których są one załączane.
#include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> #include <LiquidCrystal_PCF8574.h>
Dwie pierwsze biblioteki są wbudowane w Arduino IDE i nie musimy ich instalować.
- Biblioteka Wire – potrzebna do obsługi magistrali I2C przez którą łączymy się z naszym wyświetlaczem.
- Biblioteka SPI – potrzebna do obsługi magistrari SPI przez którą komunikujemy się z czujnikiem BMP280.
Kolejne biblioteki wymagają instalacji. Menedżer bibliotek uruchomimy korzystając z menu: Szkic > Dołącz bibliotekę > Zarządzaj bibliotekami…
Wystarczy odszukać je na liście i zainstalować.
- Adafruit Unified Sensor – potrzebna do obsługi innych bibliotek od Adaruit.
- Adafruit BMP280 Library – potrzebna do obsługi czujnika BMP280.
- LiquidCrystal_PCF8574 – potrzebna do obsługi wyświetlacza 2×16 z konwerterem I2C bazującym na układzie PCF8574.
Dlaczego naraz używamy I2C i SPI?
Jeżeli masz już nieco doświadczenia zapewne zauważysz, że czujnik Bosch BMP280 obsługuje zarówno magistralę I2C jak i SPI. Dlaczego więc nie podłączyliśmy czujnika z wyświetlaczem poprzez I2C używając mniejszej ilości przewodów?
Stało się tak z dwóch powodów:
- Sprzętowego – moduł BMP280 pracuje w logice 3.3V, natomiast wyświetlacz w logice 5V. Podłączenie ich razem bez dodatkowego konwertera poziomów logicznych w pewnych sytuacjach mogłoby doprowadzić do uszkodzenia czujnika BMP280/BME280. Podłączając wyświetlacz do NodeMCU wykorzystaliśmy fakt, że układ ESP8266 chociaż zasilany napięciem 3.3V toleruje 5V na wejściach. Więc I2C pracuje w tym wypadku na 5V, zaś SPI na 3.3V. W teorii logika 5V wyświetlacza nie powinna mieć dużego znaczenia bo magistrala I2C to tzw otwarty dren, czyli komunikacja odbywa się przez podciągnięcie linii do masy – ale nie wszyscy producenci wyświetlaczy LCD to respektują.
- Dydaktycznego – chcieliśmy pokazać różnice w podłączaniu urządzeń przez dwie najpopularniejsze magistrale komunikacyjne. W następnej części pokażemy trzecią – OneWire. I w zasadzie to jest prawdziwy powód :)
Omówienie kodu
#include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> #include <LiquidCrystal_PCF8574.h>
Wspomniana wcześniej sekcja w której załączamy biblioteki wymagane do działania projektu.
#define BMP_SCK 13 #define BMP_MISO 12 #define BMP_MOSI 11 #define BMP_CS D4 //Adafruit_BMP280 bme; // I2C Adafruit_BMP280 bme(BMP_CS); // hardware SPI //Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
Dyrektywami #define przypisujemy konkretne piny używane przy podłączeniu czujnika BMP280. Można tego nie robić, ale poprawia to czytelność kodu. W zasadzie tę całą sekcję można by zastąpić jedną linijką:
Adafruit_BMP280 bme(D4);
Jest tak dlatego, że w tym przypadku korzystamy ze sprzętowej magistrali SPI, której piny MISO, MOSI i SCK są domyślnie przypisane w definicji płytki. Zwróć uwagę, że obiekt czujnika w naszym kodzie ma nazwę bme – nie ma to większego znaczenia. Kod dla BMP280 i BME280 jest praktycznie identyczny. Ale o tym później.
LiquidCrystal_PCF8574 lcd(0x27);
Obiekt lcd będzie reprezentował nasz wyświetlacz LCD 2×16 wyposażony w konwerter I2C na układzie PCF8574. W zależności od ustawień konwertera i zastosowanego układu adres może być inny. Dla PCF8574 domyślnie jest to 0x27, zaś dla PCF8574A będzie to 0x3f. W niektórych konwerterach adres I2C można ustawić za pomocą zworek A0, A1 i A2 z tyłu wyświetlacza poniżej potencjometru od regulacji kontrastu. Niemniej nie jest to regułą, bo w niektórych konwerterach zworek tych nie ma wcale. Jeżeli Twój wyświetlacz pokazuje same prostokąty to albo masz zły adres, albo źle ustawiony kontrast (niebieski potencjometr z tyłu wyświetlacza).
void setup() { Serial.begin(9600); Serial.println(F("BMP280 test")); delay(100); lcd.begin(16, 2); // initialize the lcd lcd.setBacklight(1); if (!bme.begin()) { Serial.println("Could not find a valid BMP280 sensor, check wiring!"); delay(1); lcd.print("Brak BMP280"); while (1) {delay(1000); Serial.println("TICK");}; } Serial.println("Init done"); }
W sekcji setup() na początku otwieramy port szeregowy aby móc wysyłać dane przez kabel USB do komputera. Nie jest to wymagane do działania Pogodełka, ale znacznie upraszcza wykrywanie potencjalnych problemów z wyświetlaczem. Następnie uruchamiamy wyświetlacz o wielkości 16×2 oraz włączamy jego podświetlenie. Sprawdzamy czy BMP280 działa. Jeżeli wszystko jest w porządku kończymy etap przygotowania.
W głównej pętli używamy kilku funkcji. Nie jest to nic skomplikowanego:
lcd.setCursor(0,0);
Ustawia kursor na wyświetlaczu w pozycji (kolumna,wiersz). Liczenie zaczynamy od zera, więc setCursor(3,1) da nam czwarty znak w drugim wierszu.
lcd.print("tekst");
Wyświetla na wyświetlaczu tekst zaczynając od miejsca w którym stoi kursor.
Obsługa BMP280 z wykorzystaniem biblioteki od Adafruit jest równie prosta:
bme.readTemperature(); bme.readPressure(); bme.readAltitude(1013.25);
W ten prosty sposób można odczytać temperaturę, ciśnienie i wysokość nad poziomem morza. Ta ostatnia do prawidłowego działania wymaga odpowiedniego punktu odniesienia.
Modyfikacja – Wymiana BMP280 na BME280
Jeżeli posiadasz czujnik BME280 z naszej oferty, zauważysz zapewne, że nie różni się on znacząco od BMP280 z Pogodełka. Jedyną różnicą jest fakt, iż sensor BMP280 jest prostokątny, a BME280 kwadratowy. Podłączenie również jest identyczne.
Aby użyć go w Pogodełku należy doinstalować bibliotekę Adafruit BME280 Library i załączyć ją w projekcie w miejsce BMP280:
// #include <Adafruit_BMP280.h> #include <Adafruit_BME280.h>
Pobieranie wilgotności w głównej pętli jest równie proste jak w przypadku BMP280:
bme.readHumidity();
Nasze testowe Pogodełko zapakowaliśmy w plastikowe pudełko po wizytówkach. W środku została masa wolnego miejsca. Kto wie, może w przyszłości zasilimy je ogniwami Li-Ion?
Przykładowy kod dla Pogodełka z BME280
/*************************************************************************** Pogodełko - mini stacja pogodowa https://nettigo.pl/products/pogodelko-twoja-pierwsza-stacja-pogodowa-z-wifi v 1.0 ***************************************************************************/ #include <Wire.h> #include <SPI.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> #include <LiquidCrystal_PCF8574.h> #define BME_CS D4 Adafruit_BME280 bme(BME_CS); LiquidCrystal_PCF8574 lcd(0x27); // 0x27 lub 0x3F dla wersji z PCF8574A void setup() { delay(100); lcd.begin(16, 2); lcd.setBacklight(1); lcd.setCursor(0,0); lcd.print("POGODELKO"); lcd.setCursor(0,1); lcd.print("Nettigo.pl"); delay(3000); if (!bme.begin()) { Serial.println("Nie znaleziono czujnika BME280, sprawdz kable!"); delay(1); lcd.print("Brak BME280"); while (1) {delay(1000); Serial.println("TICK");}; } Serial.println("Przygotowanie zakonczone"); } void loop() { lcd.setCursor(0,0); lcd.print(bme.readTemperature()); lcd.print(" C "); lcd.setCursor(0,1); lcd.print(bme.readPressure()/100.0F); lcd.print(" hPa "); lcd.setCursor(9,0); lcd.print(bme.readHumidity()); lcd.print(" %"); Serial.println(); delay(2000); }
Co dalej?
Mamy już BME280 w naszym Pogodełku, ale przygoda wcale nie musi się tu kończyć. Możliwości dalszych modyfikacji jest wiele. Można podłączyć więcej czujników. Wysyłać dane do Internetu, czy podmienić oprogramowanie na ESP Easy i spiąć nasze Pogodełko z systemem inteligentnego domu takim jak Domoticz.
Ale o tym będzie w kolejnych częściach pogodełkowej przygody.
by dodać odczyt czasu z internetu:
/***************************************************************************
Pogodełko – mini stacja pogodowa oraz czas
https://nettigo.pl/products/pogodelko-twoja-pierwsza-stacja-pogodowa-z-wifi
v 1.0
***************************************************************************/
// WiFi and Time
#include
#include
#include
#include
#include
#include
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS D4
// WiFi secrets
const char* ssid = ” „;
const char* password = ” „;
//Adafruit_BMP280 bme; // I2C
Adafruit_BMP280 bme(BMP_CS); // hardware SPI
//Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
#include
// CET timezone
int timezone = 1 * 3600;
int dst = 0;
LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup() {
Serial.begin(9600);
Serial.println(F(„BMP280 test”));
delay(100);
lcd.begin(16, 2); // initialize the lcd
lcd.setBacklight(1);
if (!bme.begin()) {
Serial.println(„Could not find a valid BMP280 sensor, check wiring!”);
delay(1);
lcd.print(„Brak BMP280”);
while (1) {delay(1000); Serial.println(„TICK”);};
}
Serial.println(„Init done”);
lcd.setCursor(0,0);
lcd.println(„Wifi connecting to „);
lcd.println( ssid );
WiFi.begin(ssid,password);
lcd.println(„\nConnecting”);
while( WiFi.status() != WL_CONNECTED ){
delay(500);
lcd.print(„.”);
}
lcd.setCursor(0,0);
lcd.println(„Wifi Connected!”);
lcd.print(„IP:”);
lcd.println(WiFi.localIP() );
configTime(timezone, dst, „pool.ntp.org”,”time.nist.gov”);
lcd.println(„\nWaiting for NTP…”);
while(!time(nullptr)){
Serial.print(„*”);
delay(1000);
}
lcd.println(„\nTime response….OK”);
delay(1000);
}
void loop() {
time_t now = time(nullptr);
struct tm* p_tm = localtime(&now);
Serial.print(p_tm->tm_mday);
Serial.print(„/”);
Serial.print(p_tm->tm_mon + 1);
Serial.print(„/”);
Serial.print(p_tm->tm_year + 1900);
Serial.print(” „);
Serial.print(p_tm->tm_hour);
Serial.print(„:”);
Serial.print(p_tm->tm_min);
Serial.print(„:”);
Serial.println(p_tm->tm_sec);
Serial.print(„Temperature = „);
Serial.print(bme.readTemperature());
Serial.println(” *C”);
lcd.setCursor(0,0);
lcd.print(bme.readTemperature());
lcd.print(” C „);
lcd.print(p_tm->tm_hour);
lcd.print(„:”);
if( p_tm->tm_min tm_min);
Serial.print(„Pressure = „);
Serial.print(bme.readPressure());
Serial.println(” Pa”);
lcd.setCursor(0,1);
lcd.print(bme.readPressure()/100);
lcd.print(” hPa „);
Serial.print(„Approx altitude = „);
Serial.print(bme.readAltitude(1013.25)); // this should be adjusted to your local forcase
Serial.println(” m”);
Serial.println();
delay(2000);
}
Witam, czy jest gdzieś dostępny opis do pogodełka, jak udostęniac po WiFi i prezentowac dane na stronie www?
Cześć,
Przepraszam za zwłokę w odpowiedzi, ale nie zawsze tutaj zaglądamy na bieżąco… Jeśli chodzi o pogodełko, to taki opis został zrobiony dla OpenSenseMap: http://akademia.nettigo.pl/pogodelko_wykresy/
Dziękuję za odpowiedź, temat dobrze opisany.
Kiedy planują Państwo opisać kolejne podłączenia – czujnik pyłu, i dodanie całości do Domoticz?
Szczerze mówiąc teraz wszystko co z NAMem (https://air.nettigo.pl/zbuduj/) związane ma u nas priorytet, ale Pogodełko dalej będzie rozwiajane. Jednak nie mogę nic obiecać co do terminów.