I dette eksempelet skal vi se på hvordan vi kan bruke en Wemos D1 Mini med innebygd WiFi (basert på ESP8266) til å måle temperatur (og evt. luftfuktighet) og både sende dette til Thingspeak og lagre verdiene i en database på en egen webserver.

Vi skal se på to populære moduler for å måle temperatur: DHT22 og DS18B20. 

 

Du kan finne mye informasjon om ESP8266 på denne siden: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html 

                            Bildet viser en D1 mini pro
Wemos_D1_mini_pro.png

 

Oppsett

Installere støtte for ESP8266

For å installere støtte for ESP8266-kortene i Arduino IDE må du først lime inn følgende link i feltet "Flere  'Boards Manager' URLer" :
https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json 

Dette angir hvor programmet skal laste ned støtte både for standard ESP8266-kort og ESP32-kortene (32-bits versjoner)

Gå inn på Fil -> Innstillinger:  (Engelsk versjon File -> Preferences)

Støtte for ESP8266


Neste steg er å installere modulene under "Kort Administrasjon". Dette valget finner du øverst under menyen "Verktøy -> Kort". 
Søk etter "ESP8266", så kommer riktig modul opp:

Installere kort

Når dette er utført vil du få opp veldig mange kort i menyen. Det vi er ute etter i dette eksempelet heter LOLIN(WEMOS) D1 R2 & mini


Det siste steget er å velge riktig port under Verktøy->Port, på samme måte som med de andre Arduino-kortene.

 

Teste WiFi-tilkobling

For å teste at vi får koblet til det trådløse nettverket kan vi bruke eksempel-kode fra siden som er nevnt i ingressen.
Her må du selvsagt sette inn navnet og passordet for ditt eget trådløse nett. Hvis alt er i orden, skal du etter hvert få skrevet til serie-monitoren "Connected, IP address:" og den IP-adressen du har fått tildelt. 

Erfaringsvis er det en del routere som ikke fungerer sammen med ESP8266-modulene, slik at du ikke får koblet til. I så fall kan det være greit å ta et Google-søk med ESP8266 og navnet på routeren din.

#include <ESP8266WiFi.h>

void setup(){
  Serial.begin(115200);
  Serial.println();

  WiFi.begin("network-name", "pass-to-network");

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.print("Connected, IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {}
 

DHT22

Her skal vi bruke modulen DHT22, som vist på bildet under, til å måle temperatur og relativ luftfuktighet. Dette er en modul som er veldig mye brukt, og det finnes mange fungerende biblioteker for Arduino for den. Det ligger en egen side om denne sensoren her: DHT22

Her bruker vi biblioteket SimpleDHT. Dette biblioteket er godt dokumentert og har flere enkle eksempler som vi kan ta utgangspunkt i. Bibliotek SimpleDHT

 



Tilkoblingen av sensoren er veldig enkel. Alt vi trenger er GND, VCC (bruker 3,3V) og en datapinne. Eksempelet fra SimpleDHT bruker Arduino-pinne 2, og på D1 mini tilsvarer dette D4.  Koden under er satt sammen av ett eksempel fra SimpleDHT og eksempelet under ESP8266HTTPClient->BasicHttpClient. Koden kommuniserer med min private webserver, som for anledningen er satt opp med et lite PHP-script som leser målingene. Har oversatt det meste til norsk og lagt til en del kommentarer.

// Denne koden basert på eksempelet under ESP8266HTTPClient->BasicHttpClient
#include <Arduino.h> // Standard Arduino-bibliotek
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

// Oppsett for DHT22, VCC: 5V or 3V GND: GND DATA: 2
#include <SimpleDHT.h>
int pinDHT22 = 2; //Arduino pinne 2 tilsvarer D4 på D1 mini
SimpleDHT22 dht22(pinDHT22);

ESP8266WiFiMulti WiFiMulti;

void setup() {
Serial.begin(115200);
Serial.print("\n\n\n\n");

for (int t = 4;t > 0;t--) {
Serial.printf("[SETUP] Vent litt %d...\n", t);
Serial.flush(); //Venter på at sending skal bli ferdig
delay(1000);
}

WiFi.mode(WIFI_STA);
WiFiMulti.addAP("Din_SSID", "Ditt_passord");
}

void loop() {
if ((WiFiMulti.run() == WL_CONNECTED)) { // Venter på WiFi-tilkobling
//Leser temperatur
float temperatur = 0;
float fuktighet = 0;
int err = SimpleDHTErrSuccess;
if ((err = dht22.read2(&temperatur, &fuktighet, NULL)) != SimpleDHTErrSuccess) {
Serial.print("Read DHT22 failed, err="); Serial.println(err);delay(2000);
return;
}
Serial.print("Sample OK: ");
Serial.print((float)temperatur); Serial.print(" *C, ");
Serial.print((float)fuktighet); Serial.println(" RH%"); //Lager en tekststreng med linken vi skal bruke
char streng[100];
sprintf(streng,"http://2en.lilleholt.no/2en.php?klient=PerSi&temp=%.2f&fuktighet=%.2f&debug=1",temperatur, fuktighet);

WiFiClient client;

HTTPClient http;

Serial.print("[HTTP] begin...\n");
if (http.begin(client, streng)) { // Her brukes linken vi lagde over
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();

// httpCode vil være negativ ved feilmelding
if (httpCode > 0) {
// HTTP header har blitt sendt og vi har håndtert responsen fra serveren
Serial.printf("[HTTP] GET... code: %d\n", httpCode);

// filen ble funnet på serveren. Responsen skrives ut
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}

http.end();
} else {
Serial.printf("[HTTP] Kunne ikke koble til\n");
}
}
//Venter i 20 sekunder før vi sender neste temperatur.
delay(20000);
}
 

DS18B20

En annen mye brukt komponent er DS18B20 fra Dallas. Denne måler bare temperatur og bruker en "OneWire"-buss. Sensoren finnes i mange forskjellige innplakninger, men den vi bruker her er i en TO-92 pakke, og er til forveksling lik en transistor. Bildet under viser sensorens størrelse i forhold til en mynt og en motstand. 

Dallas DS18B20

Også her er det mange biblioteker å velge i, men vi bruker det som heter DallasTemperature, sammen med OneWire.

Bibliotek DallasTemperature

Bibliotek OneWire

 



Tilkoblingen av sensoren er veldig enkel. Alt vi trenger er GND, VCC (bruker 3,3V) og en datapinne. Eksempelet fra SimpleDHT bruker Arduino-pinne 2, og på D1 mini tilsvarer dette D4.  Koden under er satt sammen av ett eksempel fra SimpleDHT og eksempelet under ESP8266HTTPClient->BasicHttpClient. Koden kommuniserer med min private webserver, som for anledningen er satt opp med et lite PHP-script som leser målingene. Har oversatt det meste til norsk og lagt til en del kommentarer.

// Denne koden basert på eksempelet under ESP8266HTTPClient->BasicHttpClient
#include <Arduino.h> //Standard Arduino-bibliotek

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

// Biblioteker for DS18B20
#include <OneWire.h>
#include <DallasTemperature.h>

// Arduino pinne 2 tilsvarer D4 på D1 mini
#define ONE_WIRE_BUS 2

// Sensoren kommuniserer med "oneWire"-buss
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

ESP8266WiFiMulti WiFiMulti;

void setup() {
Serial.begin(115200);
Serial.print("\n\n\n\n");

for (int t = 4; t > 0; t--) {
Serial.printf("[SETUP] Vent litt %d...\n", t);
Serial.flush(); //Venter på at sending skal bli ferdig
delay(1000);
}

WiFi.mode(WIFI_STA);
WiFiMulti.addAP("Din_SSID", "Ditt_passord");

//For DS18B20
sensors.begin();
}

void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
//Les av temperatur
Serial.print("Leser av temperaturer...");
sensors.requestTemperatures(); // Sender kommando for å lese temperatur
Serial.println("Ferdig");
// Når vi har fått temperaturen, skriver vi dem ut her
// Koden kan bruke flere sensorer, men her brukes bare sensor med indeks 0
Serial.print("Temperatur for enhet 1 (index 0) er: ");
float temperature=sensors.getTempCByIndex(0);
Serial.println(temperature);

//Lager en tekststreng med linken vi skal bruke
char streng[100];
sprintf(streng,"http://iot.lilleholt.no/2en.php?klient=PerSi&temp=%.2f&debug=1",temperature);

WiFiClient client;
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if (http.begin(client, streng)) { // Her brukes linken vi lagde over
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();

// httpCode vil være negativ ved feilmelding
if (httpCode > 0) {
// HTTP header har blitt sendt og vi har håndtert responsen fra serveren
Serial.printf("[HTTP] GET... kode: %d\n", httpCode);
// filen ble funnet på serveren. Responsen skrives ut.
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
}
} else {
//Noe gikk galt. Feilmelding skrives ut.
Serial.printf("[HTTP] GET... feilet, feilmelding: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP] Kunne ikke koble til\n");
}
} else {
Serial.printf("Ikke koblet til nett\n");
}
//Venter i 20 sekunder før vi sender neste temperatur.
delay(20000);
}
 

Server-kode:

Koden som skal ta i mot målingene er skrevet i script-språket PHP.

Så langt leses bare verdiene fra lenken, og returneres til klienten, vel og merke hvis debug-parameteren er satt.

Parameterene vi sender med via linken hentes ut via den "hyper-globale" variabelen $_GET  (referanse: https://topic.alibabacloud.com/a/php-hyper-global-array_1_34_10115588.html )

<?php
$temp=$_GET['temp'];
$hum=$_GET['humidity'];
if($_GET['debug']==1) $debug=1; else $debug=0;

if($debug){
printf("<h1>Hallo der sensor!</h1>");
printf("\nTemperatur: %s",$temp);
printf("\nFuktighet: %s",$hum);
}
?>

 

Oppgaver:

Vi avslutter denne bolken med et par enkle oppgaver:

Kommer...