zondag 17 april 2016

ESP8266 en DHT22

UPDATE: Ik was vergeten erbij te zetten dat je een library nodig hebt om makkelijk met de DHT22 te kunnen werken, ik heb dit nu toegevoegd, voor de sketch.

Nu de ESP8266 werkt, gaan we verder en ga ik de DHT22 aansluiten om te zien of ik dat ook werkend krijg.

Ik heb de DHT22 aangesloten op het ESP8266 Yellow-board.

DHT22     ESP8266
Pin 1         VCC
Pin 2         GPIO2
Pin 3         -
Pin 4         GND

In de Arduino IDE de volgende Sketch gemaakt (Aangepast op de versie van Adafruit) Heb uiteraard de OTA update mogelijkheid weer toegevoegd, dat werk lekker makkelijk en snel, tevens heb ik de temperaturr van Fahrenheit aangepast zodat hij Celcius en Fahrenheit weergeeft.

Arduino IDE

om makkelijk met de DHT22 (of DHT11) te kunnen werken in Arduino, is er door Adafruit een library gemaakt.
Als je de Aduino IDE hebt draaien sluit deze dan nu eerst af.
Deze kun je downloaden op https://github.com/adafruit/DHT-sensor-library, rechts op de pagina boven de bestanden staat een knop [Download ZIP]
Vervolgens pak je de map en bestanden in de zip uit naar de map arduino\libraries\ welke je kan vinden in je Documenten map (normaal geproken "Mijn Documenten" of "Documenten" geheten)
Nu kan je de Arduino IDE weer opstarten en de volgende sketch maken.

Sketch

/* DHTServer - ESP8266 Webserver with a DHT sensor as an input
   Based on ESP8266Webserver, DHTexample, and BlinkWithoutDelay (thank you)
   Version 1.0  5/3/2014  Version 1.0   Mike Barela for Adafruit Industries
*/
#include <esp8266wifi.h>
#include <wificlient.h>
#include <esp8266webserver.h>
#include <arduinoota.h>
#include <wifiudp.h>
#include <dht.h>
#define DHTTYPE DHT22
#define DHTPIN  2
 
const char* ssid = "SSID";
const char* password = "SSID_PASSWORD";

ESP8266WebServer server(80);
 
// Initialize DHT sensor 
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01 
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
 
float humidity, temp_f, temp_c;  // Values read from sensor
String webString="";     // String to display
String webString1="";     // String to display
String webString2="";     // String to display
// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 2000;              // interval at which to read sensor
 
void handle_root() {
  webString= "Hello from the weather esp8266, read from /temp or /humidity";
  server.send(200, "text/plain", webString);
  delay(100);
}
 
void setup(void)
{

  // You can open the Arduino IDE Serial Monitor window to see what the code is doing
  Serial.begin(115200);  // Serial connection from ESP-01 via 3.3v console cable
  dht.begin();           // initialize temperature sensor
 
  // Connect to WiFi network
  WiFi.begin(ssid, password);
  Serial.print("\n\r \n\rWorking to connect");
 
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("DHT Weather Reading Server");
  Serial.println("Versie: " + versie);
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
   
  server.on("/", handle_root);
  
  server.on("/temp", [](){  // if you add this subdirectory to your webserver call, you get text below :)
    gettemperature();       // read sensor
//    webString1="Temperature: "+String((int)temp_f)+" F";   // Arduino has a hard time with float to string
//    webString2="Temperature: "+String((int)temp_c)+" C";   // Arduino has a hard time with float to string
    webString1="Temperature: "+String(temp_f)+" F";   // Arduino has a hard time with float to string
    webString2="Temperature: "+String(temp_c)+" C";   // Arduino has a hard time with float to string
    webString=webString1 + "\n" + webString2;
    server.send(200, "text/plain", webString);            // send to someones browser when asked
  });
 
  server.on("/humidity", [](){  // if you add this subdirectory to your webserver call, you get text below :)
    gettemperature();           // read sensor
//    webString="Humidity: "+String((int)humidity)+"%";
    webString="Humidity: "+String(humidity)+"%";
    server.send(200, "text/plain", webString);               // send to someones browser when asked
  });
  
  server.begin();
  Serial.println("HTTP server started");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
    for (int i=0;i<30;i++)
      {
        analogWrite(12,(i*100) % 1001);
        delay(150);
        analogWrite(12, 0);
        analogWrite(13,(i*100) % 1001);
        delay(150);
        analogWrite(13, 0);
        analogWrite(15,(i*100) % 1001);
        delay(150);
        analogWrite(15, 0);
      }
    Serial.println("\nRebooting....");
    delay(50);
  });

  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
  pinMode(0, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  digitalWrite(0, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
  digitalWrite(14, HIGH);
  digitalWrite(15, LOW);
  digitalWrite(16, HIGH);

}
 
void loop(void)
{
  server.handleClient();
  ArduinoOTA.handle();
} 
 
void gettemperature() {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor  
    previousMillis = currentMillis;   
 
    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
    humidity = dht.readHumidity();          // Read humidity (percent)
    temp_f = dht.readTemperature(true);     // Read temperature as Fahrenheit
    temp_c = dht.convertFtoC(temp_f);
    // Check if any reads failed and exit early (to try again).
    Serial.println(String(temp_c) + " C   " + String(humidity) + " %   " + String(temp_f) + "F");
    if (isnan(humidity) || isnan(temp_f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
  }
}
Als deze sketch geüpload is (hoe je OTA je sketch kan uploaden kan je lezen in mijn blog bericht :
ESP8266), kan je eventueel met een FTDI-kabel en Putty zien welk IP-adres de ESP8266 heeft gekregen (Je zou ook FING - Network Tools  kunnen gebruiken op je smartphone of tablet).

Als je nu vervolgens een browser opent en gaat naar het IP-adres van de ESP8266, zie je de volgende regel "Hello from the weather esp8266, read from /temp or /humidity".
Als je nu naar IP-adres/temp of IP-adres/humidity gaat, zal je de gemeten temperatuur (Fahrenheit en Celsius) of luchtvochtigheid zien (Omdat de sketch iedere 2 seconden de waarden uitleest uit de DHT22, kan je iedere 2 seconden de pagina verversen om de nieuwe waarden te zien.


maandag 11 april 2016

ESP8266

ESP8266-12F
Ik wil graag weten hoe warm het in ieder vertrek in mijn huis is en zocht daarvoor een handige methode. Op internet kwam ik steeds meer tegen over de ESP8266, die onder andere met Arduino te programmeren is dus henb ik er maar eens een paar aangeschaft, samen met een paar DHT11's en andere onderdelen om het aan de praat te krijgen op een batterij.
Breakoutbordje

Naast een aantal standaard ESP8266-12F modules met 4MB flash heb ik tevens een breakoutbordje voor deze module en een ontwikkelbordje met batterijvoeding besteld. Toen ik het pakket binnenkreeg eerst maar eens gaan spelen met het ontwikkelbordje.

Ontwikkelbordje met batterijvoeding
Ondanks dat er op internet veel over het bordje te vinden is, was niets dat ik vond compleet, dus ga ik hier maar eens alles samenvatten en completeren.

ESP8266 (AI-Thinker of Yellow bord)


Het bordje komt met daarop ai-thinker vooraf geladen. en kan je er direct mee gaan spelen met je telefoon of tablet (voor Android hier te vinden).
(GPIO) aansluitingen
Het bordje is uitgerust met een batterijhouder voor 3 AA-batterijen, 1 blauwe (voeding) led, 6 rode leds (op GPIO 0, 2, 4, 5, 14 en 16, let op de eerst 2 zijn gedraaid, dus de eerste led zit op GPIO2 en de tweede op GPIO0), en RGB-led (op GPIO12 (groen of rood), GPIO13 (Blauw), en GPIO15 (Rood of Groen) en een LDR op de ADC (A0).

AI-Thinker

Om er nu mee te gaan spelen zet je de jumper op het bordje open en stopt 3 AA-batterijen in de houder.
Hierna zoek je op je telefoon/tablet naar een nieuw wifi-netwerk met de naam AI-THINKER_XXXXXX (waarbij XXXXXX een deel van het mac-adres is), als je hiermee verbind heb je een wachtwoord nodig (dat is dus "ai-thinker").

Hierna kan je met de app de led's aansturen en kan je de wifi instellingen wijzigen zodat het bordje verbind met jouw eigen wifi-netwerk (eventueel kan je ook de rode en groene aansturing van de RGB-led omwisselen, omdat deze bij sommige bordjes ook gewisseld is.

Dit werkt uitstekend, binnen 5 minuten had is dit wel gezien, op naar de volgende stap, Het bordje programeren met Arduino.

Arduino IDE (Serieel)


Nieuwe software op het bordje plaatsen kan met een FTDI-kabel aangesloten op de TXD, RXD, en GND pennen naast de aansluiting van de batterij.

Ik heb gebruik gemaakt van de Arduino software (versie 1.6.8 momenteel).
Na installatie en opstarten, moeten we eerst nog wat dingen aanpassen, willen we kunnen werken met de ESP8266.

We beginnen met in het menu te kiezen voor Bestand, dan Voorkeuren, in het scherm wat zich nu opent, vullen we achter "Additionele Bordenbeheerder URLs" de volgende URL in:
http://arduino.esp8266.com/versions/2.1.0/package_esp8266com_index.json.

Mocht er al wat ingevuld staan, klik dan eerst op het icoontje wat rechts van het invoerveld staat, er opend dan een groter edit-venster, waarbij je op iedere regel een URL kan invullen. We bevestigen daarna met [OK] (2x als je de grotere edit geopend had).
Nu openen we het menu Hulpmiddelen, Board: "Huidig geselecteerd bord"Bordenbeheerder....
In het venster "Bordenbeheerder" wat zich nu opent, typ je in Filter je zoekresultaten... "ESP8266" (Uiteraard zonder de quootjes), Nu staat er in het venster "esp8266 by ESP8266 Community", selecteer de door er met de muis op te klikken en kies [Installeren].
Als deze geïnstalleerd is, kan je het venster sluiten en kunnen we de juiste instellingen voor ons bord maken.

Kies wederom voor Hulpmiddelen, Board: "Huidig geselecteerd bord", scrol eventueel naar beneden en kies onder ESP8266 Modules ,voor de "Generic ESP8266 Module", als je nu weer Hulpmiddelen opent, zal je zien dat er veel meer opties staan.
We maken hier (in mijn geval) de volgende instellingen:
Upload using: Serial(De eerste keer zullen we in ieder geval de sketch via de FTDI-kabel moeten laden.
Flash Size: 4M (1M SPIFFS)(dit is de grootte van het Flashgeheugen van de module, deze MOET goed staan wil je ook OTA (Over The Air, via wifi dus) de sketch kunnen updaten).
Upload Speed: 115200Hierover hieronder meer.
Poort: ComXSelecteer de poort waarop de FTDI kabel is aangesloten.
Nu kan je via Bestand, Voorbeelden, ArduinoOTA, het voorbeeld BasicOTA laden. Pas regels 6 en 7 aan zodat jouw eigen ssid en wachtwoord daar staan ingevuld op de plaats van de puntjes.

Nu kan je in principe de uploaden op het bordje, bij mij mislukte dat steeds door 2 redenen:
  1. De snelheid van de seriele poort was niet goed.
  2. Ik deed de reset van het bordje niet goed.
Om de ze punten op te lossen dien je het volgende te doen:
  1. In apparaatbeheer moet je de Seriele poort opzoeken die de FTDI-kabel heeft, daar stel je de snelheid in op 115200 bits. Bij mij moest dit althans gebeuren, anders kreeg ik niets geupload naar de ESP8266.
  2. Om het bordje te resetten voor het uploaden van een sketch, trek je 1 batterij los, sluit de jumper. Nu sluit je de batterij weer aan en haal je vervolgens de jumper los.
 Nu kan je de sketch uploaden naar de ESP8266.

Als dit allemaal goed is gegaan kan je met bv Putty een verbinding opzetten naar de ESP8266 om zo de output van de seriële monitor te zien.
Hiervoor kies je in Putty voor Connection Type: "Serial", Serial Line: "ComX" en de Speed: "115200".
Als je nu de port opent en de ESP8266 even reset (door een batterij los te halen en er weer in te zetten, zal je nu als het goed is een IP adres zien verschijnen in Putty.

Als dit allemaal werkt heb je je eerste sketch geladen op de ESP8266.

Arduino IDE (OTA)

Maar nu gaan we een stapje verder, via OTA de sketch laden.
Wijzig bij Hulpmiddelen, Upload Using in "OTA" en Poort in "esp8266-[ChipID] at IP-adres (Generic ESP8266 Module)", mocht deze poort er niet tussen staat, sluit dan de Arduino software af en start hem opnieuw op (zorg wel dat de ESP8266 AAN staat), nu zal de poort er als het goed is wel tussen staan.

Om een sketch via OTA te kunnen laden moet er vrije ruimte op de ESP8266 zijn om de nieuwe sketch op te slaan naast de oude sketch, de ruimte gereserveerd voor sketches wordt aangegeven in de SPIFFS, bij mij dus 3MB, de oude en de nieuwe sketch kunnen beide dus 1,5 MB groot zijn maximaal.

Nu is het heel simpel, kies upload in de Arduino en de sketch zal geladen worden, dit kan je ook volgen in Putty als je die nog open hebt staan.

Bestudeer zelf de BasicOTA sketch maar om te zien hoe het 1 en ander werkt en wat je nog kan instellen / aanpassen.
Zelf heb ik via OTA de volgende aangepaste BasicOTA sketch geladen:

Sketch

#include <esp8266wifi.h>
#include <esp8266mdns.h>
#include <wifiudp.h>
#include <arduinoota.h>

const char* ssid = "SSID";
const char* password = "SSID_PASSWORD";
int val = 0;
int analog = A0;

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("MyEsp8266");

  // No authentication by default
//  ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
  pinMode(0, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
}

void loop() {
  ArduinoOTA.handle();
  Serial.print("Led 1 -");
  digitalWrite(2, LOW);
  delay(750);
  digitalWrite(2, HIGH);
  Serial.print(" Led 2 -");
  digitalWrite(0, LOW);
  delay(750);
  digitalWrite(0, HIGH);
  Serial.print(" Led 3 -");
  digitalWrite(4, LOW);
  delay(750);
  digitalWrite(4, HIGH);
  Serial.print(" Led 4 -");
  digitalWrite(5, LOW);
  delay(750);
  digitalWrite(5, HIGH);
  Serial.print(" Led 5 -");
  digitalWrite(14, LOW);
  delay(750);
  digitalWrite(14, HIGH);
  Serial.print(" Led 6 -");
  digitalWrite(16, LOW);
  delay(750);
  digitalWrite(16, HIGH);
  Serial.print(" Led Green -");
  digitalWrite(12, HIGH);
  delay(750);
  digitalWrite(12, LOW);
  Serial.print(" Led Blue -");
  digitalWrite(13, HIGH);
  delay(750);
  digitalWrite(13, LOW);
  Serial.print(" Led Red =");
  digitalWrite(15, HIGH);
  delay(750);
  digitalWrite(15, LOW);
  delay(500); 
  val = analogRead(analog); 
  Serial.print(" LDR value: ");
  Serial.println(val);

  ArduinoOTA.handle();

  Serial.print("Led 1 -");
  digitalWrite(2, LOW);
  delay(500);
  Serial.print(" Led 2 -");
  digitalWrite(0, LOW);
  delay(500);
  Serial.print(" Led 3 -");
  digitalWrite(4, LOW);
  delay(500);
  Serial.print(" Led 4 -");
  digitalWrite(5, LOW);
  delay(500);
  Serial.print(" Led 5 -");
  digitalWrite(14, LOW);
  delay(500);
  Serial.print(" Led 6 -");
  digitalWrite(16, LOW);
  delay(500);
  Serial.print(" Led Green -");
  digitalWrite(12, HIGH);
  delay(500);
  Serial.print(" Led Blue -");
  digitalWrite(13, HIGH);
  delay(500);
  Serial.print(" Led Red =");
  digitalWrite(15, HIGH);
  delay(500);  
  digitalWrite(2, HIGH);
  delay(150);  
  digitalWrite(0, HIGH);
  delay(150);  
  digitalWrite(4, HIGH);
  delay(150);  
  digitalWrite(5, HIGH);
  delay(150);  
  digitalWrite(14, HIGH);
  delay(150);  
  digitalWrite(16, HIGH);
  delay(150);
  digitalWrite(12, LOW);
  delay(150);
  digitalWrite(13, LOW);
  delay(150);
  digitalWrite(15, LOW);
  delay(150);
  val = analogRead(analog); 
  Serial.print(" LDR value: ");
  Serial.println(val);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Sketch size: ");
  Serial.println(ESP.getSketchSize());
  Serial.print("Free size: ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.print("Chip size: ");
  Serial.println(ESP.getFlashChipSize());
}
De leds zullen nu om de beurt oplichten (met melding in Putty) en tevens zal in Putty de waarde van de LDR getoond worden.

Zoals je kan zien heb ik (nog) geen wachtwoord ingesteld op regel 29, dit omdat ik dat nog niet aan de praat heb gekregen, Arduino vraagt netjes om het wachtwoord, echter hij accepteert het ingegeven wachtwoord daarna niet.

In het volgende blog meer over het uitlezen van de DHT11 met de ESP8266.