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.

  1. 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
  2. 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.
  3. Wybieramy płytkę, którą będziemy programować.
    Z menu: Narzędzia > Płytka wybieramy pozycję NodeMCU 1.0 (ESP-12E Module)
  4. 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.