IoT Beispiel: ESP8266 nodeMCU für Website zur Überwachung und Steuerung

Atmel, PIC, VEX, Fischertechnik

Moderator: Moderatoren

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5396
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

IoT Beispiel: ESP8266 nodeMCU für Website zur Überwachung und Steuerung

Beitragvon HaWe » 23. Jun 2017 15:05

IoT Beispiel: ESP8266 nodeMCU für Website zur Überwachung und Steuerung

NodeMCU Board ESP-12E oder 12F:
NodeMCU-pinbelegung.png

Quelle: http://www.mikrocontroller-elektronik.de/wp-content/uploads/2017/01/NodeMCU-pinbelegung.png
http://www.mikrocontroller-elektronik.d ... duino-ide/

Der ESP8266-12E/F nodeMCU besitzt eine 32-bit cpu, 80MHz cpu-Takt, 64kB RAM , eingebautes Wifi-Modul
Er hat daher etwa 30x soviel Speicher zur Programmierung wie ein Arduino Uno, Micro oder Nano, 8x soviel Speicher wie ein Arduino Mega, und eine 5x so schnelle Taktfrequenz, und liegt demnach speicher- und leistungsmäßig zwischen einem Arduino M0/Zero und einem Arduino Due, aber eben inklusive zusätzlich eingebautem WFi-Modul.
Programmierbar ebenfalls über die Arduino-IDE.
GPIO pins:

Code: Alles auswählen

11 digitale Pins (optional auch pwm):
--------------------------
D.Nr.  GPIO  PROG 
D0      16   WAKE
D1       5   I2C SCL
D2       4   I2C SDA
D3       0   FLASH
D4       2   TX1
D5      14   SPI SCK
D6      12   SPI MISO
D7      13   SPI MOSI
D8      15   MTD0 PWM
D9       3   UART RX0
D10      1   UART TX0

1 analoger Pin (ADC):
--------------------------
A0      ADC(10-bit)

die übrigen pins sind offenbar nur für internen Gebrauch, nicht für Programmierzwecke.
Preis: etwa 3-8 EUR (Amazon, Ebay)

wer zusätzliche digitale oder analoge Pins benötigt, kann dies über I2C oder SPI Port-Expander erreichen
(MCP23017, MCP23S17, MCP3008, PCF8574, PCF8591, ADS1115), alternativ auch einen weiteren Arduino als I2C-Slave oder per UART.

weitere Infos zu Hardware, Libs und Installation des ESP8266 nodeMCU Boards hier:
viewtopic.php?f=78&t=8491#p66189
viewtopic.php?f=78&t=8953&p=70985#p70985
http://www.instructables.com/id/Quick-S ... duino-IDE/
https://github.com/esp8266/Arduino
https://github.com/esp8266/Arduino/tree ... /libraries
IoT Libs:
die meisten libs werden schon bei der Board-Installation oder anschließend über den Arduino IDE Bibliothek-Manager installiert
(ESP8266WiFi, Time, TimelLib, TimeZone, Ethernet, WiFiUdp,...); s.a.:
https://github.com/esp8266/Arduino/tree ... /libraries
https://github.com/esp8266/Arduino/tree ... 66WiFi/src
https://github.com/PaulStoffregen/Time
https://github.com/afch/NixieClock/blob ... 66WiFi.ino
DHT:
viewtopic.php?f=78&t=8491&p=70084#p70987
https://github.com/adafruit/DHT-sensor-library
OLED:
https://learn.adafruit.com/monochrome-o ... d-examples
https://github.com/somhi/ESP_SSD1306

zusätzlich angeschlossen:
ein OLED Display, 1 I2C-Steckerbuchse (wie Quick2Wire), 2 LEDs, DHT Sensoren, einige Taster zu Testzwecken, weitere IOs folgen.
noeMCU_IoT Server.jpg


Beispiel-Code:
Quelle: u.a. http://www.instructables.com/id/Quick-S ... duino-IDE/
zeigt Datum und Uhrzeit nach CEST/CET (mitteleurop. Sommer/Winterzeit, per Internet-Time Server)
zeigt ein paar überwachte Sensorwerte (z.B. Temp., Luftfeuchte, Bodenfeuchte folgt)
und kann 2 Verbraucher per Website-Buttons übers Internet steuern (als Demo: 2 LEDs, per Relais oder Motor-H-Brücken aber auch Motoren für Ventilatoren, Fensteröffner, Jalousien oder Bewässerungspumpen)



Nur als Demo und als Anregung und Basis für eigene Ideen:

Code: Alles auswählen

/*  Beispiel
 *  "WLAN CLient und Web Server mit OLED und Seriell Ausgabe"
 *  Ref.: http://www.instructables.com/id/Quick-Start-to-Nodemcu-ESP8266-on-Arduino-IDE/,
 *  verändert und ergänzt
 *  ver 0.3.4 (neu verkabelt!)
 */

//----------------------------------------------------------------------------
#include <Wire.h>
// #include <SPI.h>

#include <ESP_SSD1306.h>    // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h>   // Needs a little change in original Adafruit library (See README.txt file)

#define ESPSDA D2   //GPIO4 SDA
#define ESPSCL D1   //GPIO5 SCL

#define OLED_RESET    D0    // pin reset signal; altern.: try 10 instead of D0

ESP_SSD1306 display(OLED_RESET);


//----------------------------------------------------------------------------
#include <DHT.h>
// DHT sensor defs
#define DHT_1_PIN     D5       // Datenleitung des Sensors
#define DHT_2_PIN     D7       // Datenleitung des Sensors

DHT  DHT_1(DHT_1_PIN, DHT11),  // 1.DHT Typ definieren
     DHT_2(DHT_2_PIN, DHT22);  // 2.DHT Typ definieren
     
char tempc1[20];
char humid1[20];
char tempc2[20];
char humid2[20];


//----------------------------------------------------------------------------
// actuators (LED, relays, motors)

#define  LED1         D3      //  LED Pin
#define  LED2         D4      //  LED Pin




//----------------------------------------------------------------------------
#include <ESP8266WiFi.h>

// WiFi settings

const char* ssid = "WiFi-ssd";       // WiFi-Name einsetzen! <<<<<<<<<<<<<<<<<
const char* password = "WiFi-pwd";   // WiFi-Passwort einsetzen! <<<<<<<<<<<<<
IPAddress ip(192,168,111,211);       // IoT ESP8266 Server IP wählen! <<<<<<<<
IPAddress gateway(192,168,111,222);  // Internet Gateway IP einsetzen! <<<<<<<
IPAddress subnet(255,255,255,0);     // Subnet Mask <<<<<<<<<<<<<<<<<<<<<<<<<<

WiFiServer   server(80);

//----------------------------------------------------------------------------

#include <TimeLib.h>
#include <Timezone.h>
#include <WiFiUdp.h>

//----------------------------------------------------------------------------
// NTP Servers
// NIST Internet Time Servers: http://tf.nist.gov/tf-cgi/servers.cgi
// IPAddress timeServer(129, 6, 15, 28); // 129.6.15.28 NIST, Gaithersburg, Maryland
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov


WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets


// manual time zone settings
const int timeZone = 0;     // UTC=GMT, auto mode (CE, CET, CEST via timezone lib)
//const int timeZone =  1;  // Central European Time (Berlin, Paris)
//const int timeZone = -4;  // Eastern Daylight Time (USA)
//const int timeZone = -5;  // Eastern Standard Time (USA)
//const int timeZone = -6;  // Central Standard Time (USA)
//const int timeZone = -7;  // Pacific Daylight Time (USA)
//const int timeZone = -8;  // Pacific Standard Time (USA)

//Timezone
//Central European Time (Berlin, Frankfurt, Paris)
TimeChangeRule CEST = { "CEST", Last, Sun, Mar, 2, 120 };     //Central European Summer Time
TimeChangeRule CET = { "CET ", Last, Sun, Oct, 3, 60 };       //Central European Standard Time
Timezone CE(CEST, CET);
TimeChangeRule *tcr;        //pointer to the time change rule, use to get the TZ abbrev


//----------------------------------------------------------------------------
// strings and symbols for IO display

String timestr= "--:--:--", datestr="--.--.----";
#define CHR_DEGREE (unsigned char)247               // ° symbol for OLED font
char    STR_DEGREE[] = {247, 0, 0};                 // ° OLED font specimen (°,°C,°F,K)



//----------------------------------------------------------------------------
char * sprintDouble(char* s, double val, int width, int prec, bool sign)  {   
   char sbuf[20] ="\0";
   strcpy(s, "\0");
   dtostrf(val, width, prec, s);

   if(sign && val>0) {
     for (int i=width-1; i>=0; i--) {
       if(s[i]==' ') {s[i]='+'; break;}
     }
   }
   return s;
}

//----------------------------------------------------------------------------

void dashboard(int mode) {
 
  if(digitalRead(D0)==HIGH) display.setRotation(2);
  else display.setRotation(0);
  display.clearDisplay();
 
  if(mode==1) {     
       //String cx_oled = "WiFi connected: " + (String)WiFi.RSSI() + " dBm";
       //display.drawString( 0, 0, cx_oled );   
       String gw_oled= "Gtw: " + (String)WiFi.gatewayIP()[0] + "." + (String)WiFi.gatewayIP()[1]
                            + "."  + (String)WiFi.gatewayIP()[2] + "." + (String)WiFi.gatewayIP()[3]
                            + "-"  + (String)WiFi.RSSI() ;
 
       display.setCursor( 0, 0);  display.print(gw_oled );
       // Print the IP address
       String lip_oled = "http://" + (String)WiFi.localIP()[0] + "." + (String)WiFi.localIP()[1]
                             + "." + (String)WiFi.localIP()[2] + "." + (String)WiFi.localIP()[3] + "/";
       display.setCursor( 0,10);  display.print( lip_oled);
       display.setCursor( 0,20);  display.print( timestr+"   "+datestr );
       display.setCursor( 0,30);  display.print("1." + (String)tempc1 + STR_DEGREE + "C");       
       display.setCursor(78,30);  display.print("F:"+(String)humid1 );
       display.setCursor( 0,40);  display.print("2." + (String)tempc2 + STR_DEGREE + "C" );       
       display.setCursor(78,40);  display.print("F:"+(String)humid2 );
   
       display.display();
  }
}

//----------------------------------------------------------------------------


void buildDateTimeString(){
  char sbuf[20];
  // digital clock display of the time
  timestr ="";
  sprintf(sbuf, "%02d:%02d:%02d", (int)hour(),(int)minute(),(int)second());
  timestr = sbuf;
  //Serial.println(timestr);

  datestr="";
  sprintf(sbuf, "%02d.%02d.%4d", (int)day(),(int)month(),(int)year());
  datestr = sbuf;
  //Serial.println(datestr);
  //Serial.println();
 
}


     
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------


void setup() {
 
  int progress = 0;
  strcpy(tempc1, "------");
  strcpy(humid1, " --");
  strcpy(tempc2, "------");
  strcpy(humid2, " --");

 
  Serial.begin(115200);
  delay(10);

  pinMode(D0, INPUT_PULLUP);
 
 
  pinMode(LED1, OUTPUT);
  digitalWrite(LED1, LOW);
  pinMode(LED2, OUTPUT);
  digitalWrite(LED2, LOW);

  // OLED + I2C
  Wire.begin(ESPSDA,ESPSCL);
  delay(10);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  if(digitalRead(D0)==HIGH) display.setRotation(2);
  else display.setRotation(0);
 
  display.setFont();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setCursor( 0, 0);  display.print("OLED TEST OK");
  display.display();

 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);   // feste IP
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");       

    display.clearDisplay();
    display.setCursor( 0,20);  display.print(" WiFi connecting...");
    drawHorizontalBargraph( 0,30, (int16_t) display.width(),10,1, progress);
    display.setCursor( 0,50);  display.print(progress);
    if(progress>=98) progress=80;
    display.display();
 
    if(progress<10) progress+=5;
    else
    if(progress<50) progress+=2;
    else
    if(progress<98) progress+=1;
  }
  display.clearDisplay();
    progress = 100;
    display.setCursor( 0,20);  display.print(" WiFi connecting...");
    drawHorizontalBargraph( 0,30, (int16_t) display.width(), 10, 1, progress);
    display.setCursor( 0,50);  display.print(progress);
 
  display.display();
  delay(500);
 
  Serial.println("");
  Serial.print("WiFi connected: ");
  Serial.println(WiFi.gatewayIP());
   
  // Start the server
  server.begin();
  Serial.println("Server started");
   
  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  // Start UDP
  Serial.println("Starting UDP");
  Udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(Udp.localPort());
  Serial.println("waiting for sync");
 
  setSyncProvider(getNtpTime);
 
  dashboard(1);
}

 
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
 
void loop() {
 
  static float t, h;
  static unsigned long tms=0;
  static unsigned long dtms=0, dt_t1=0, dt_h1=0, dt_t2=0, dt_h2=0;

  if ( millis() - dtms >= 1000 ) {     
     dtms=millis();
     
     //---------------------------------------
     // build date + time strings
     buildDateTimeString();       
     Serial.println(timestr+"   "+datestr);
     
     //---------------------------------------
     // read DHT Sensor
     
     if(millis()-dt_t1>60000) strcpy(tempc1, "------");  // 60sec timeout string reset
     if(millis()-dt_h1>60000) strcpy(humid1, " --");
     if(millis()-dt_t2>60000) strcpy(tempc2, "------");
     if(millis()-dt_h2>60000) strcpy(humid2, " --");
     
     delay(1);   
     t = DHT_1.readTemperature();       // 1. Temperatur auslesen (Celsius)
     delay(1);
     if (!(isnan(t))) {
        sprintDouble(tempc1,t,6,1,true);   // Temperatur mit 2 Nachkommastellen in String konvertieren
        dt_t1=millis();   
     }       
         
     h = DHT_1.readHumidity();           // 1. Feuchtigkeit auslesen (Prozent)
     delay(1);
     if (!(isnan(h)))  {
        sprintDouble(humid1,h,3,0,false);  // Feuchtigkeit ohne Nachkommastelle in String konvertieren
        strcat(humid1," %");               //String mit %-Zeichen ergänzen
        dt_h1=millis();
     }
     
     t = DHT_2.readTemperature();        // 2. Temperatur auslesen (Celsius)
     delay(1);
      if (!(isnan(t)))  {
        sprintDouble(tempc2,t,6,1,true);   // Temperatur mit 2 Nachkommastellen in String konvertieren
        dt_t2=millis();
     }   
     
     h = DHT_2.readHumidity();           // 2. Feuchtigkeit auslesen (Prozent)
     delay(1);
     if (!(isnan(h))) {
        sprintDouble(humid2,h,3,0,false);  //Feuchtigkeit ohne Nachkommastelle in String konvertieren
        strcat(humid2," %");               //String mit %-Zeichen ergänzen
        dt_h2=millis();
     }
     
     Serial.print("DHT Sensor 1: ");
     Serial.print(tempc1);   Serial.print("   ");  Serial.print(humid1); Serial.println(" rH");
     Serial.print("DHT Sensor 2: ");
     Serial.print(tempc2);   Serial.print("   ");  Serial.print(humid2); Serial.println(" rH");

     
     //---------------------------------------
     // display on OLED
     dashboard(1);
  }

 
  //---------------------------------------
  // Check if a client has connected
  // Read the request:
   
  handleWebsite();
  delay(1);
 
  //Serial.println("Client disconnected");
  //Serial.println("");
 
}

//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

void drawHorizontalBargraph(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color, uint16_t percent)
{
  uint16_t hsize;

  // Create rectangle
  display.drawRect(x,y, w, h, color)  ;

  // Do not do stupid job
  if ( h>2 && w>2 )
  {
    // calculate pixel size of bargraph
    hsize = ( ( w - 2) * percent ) / 100  ;

    // Fill it from left (0%) to right (100%)
    display.fillRect(x+1 , y+1 , hsize, h - 2, color);
  }
}




//----------------------------------------------------------------------------

void handleWebsite(){
  volatile static int valD7=-1, valD8=-1;     
 
  //---------------------------------------
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  //---------------------------------------
  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
 
  // Match the request
  if (request.indexOf("/LED1=ON") != -1)  {
    digitalWrite(LED1, HIGH);
    valD7 = HIGH;
  }
  if (request.indexOf("/LED1=OFF") != -1)  {
    digitalWrite(LED1, LOW);
    valD7 = LOW;
  }

  if (request.indexOf("/LED2=ON") != -1)  {
    digitalWrite(LED2, HIGH);
    valD8 = HIGH;
  }
  if (request.indexOf("/LED2=OFF") != -1)  {
    digitalWrite(LED2, LOW);
    valD8 = LOW;
  }
 
  //---------------------------------------
  // Return the response

 
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.println("<head>");

  // autom. Aktualisierung alle 30 sec.
  client.println("<meta http-equiv=\"refresh\" content=\"30; URL=http://192.168.xxx.yyy\">");
  // utf-8 für "°" Zeichen
  client.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
  client.println("<title>mysite</title>");
  client.println("</head>");   
 
  client.println("<body>");
  client.println("<h1><p style=""color:rgb(255,0,191);""> hello World!</p> </h1>");
  client.println("<h1><p style=""color:rgb(255,0,191);""> Welcome to my IoT website! </p> </h1>");

  client.print("<h2><p style=""color:rgb(0,204,102);""> ");
  client.print(datestr + " &nbsp; <wbr> <wbr> <wbr> " + timestr + "</p> </h2>");
  client.println("<br><br>");
  client.print("LED1 is now: ");
  if(valD7 == HIGH) { client.print("On &nbsp; <wbr> <wbr> <wbr> "); }
  else {  client.print("Off &nbsp; <wbr> <wbr> <wbr> ");  }
 
  client.println("<a href=\" /LED1=ON\"\"><button>Turn On </button></a>");
  client.println("<a href=\" /LED1=OFF\"\"><button>Turn Off </button></a><br />");
 
  client.println("<br><br>");
  client.print("LED2 is now: ");
  if(valD8 == HIGH) { client.print("On &nbsp; <wbr> <wbr> <wbr> "); }
  else {  client.print("Off &nbsp; <wbr> <wbr> <wbr> ");  }
  client.println("<a href=\" /LED2=ON\"\"><button>Turn On </button></a>");
  client.println("<a href=\" /LED2=OFF\"\"><button>Turn Off </button></a><br />");
 
  client.println("<br><br>");     
  client.println("<p><font face=""courier"">");
  client.print("<h2>DHT Sensor 1: Temperat.: "+(String)tempc1 + "°C ");
  client.println("&nbsp; <wbr> <wbr> <wbr>   Feuchtigk.: "+(String)humid1+" </h2>");

  client.print("<h2>DHT Sensor 2: Temperat.: "+(String)tempc2  + "°C ");
  client.println("&nbsp; <wbr> <wbr> <wbr>   Feuchtigk.: "+(String)humid2+" </h2>");

  client.println("</font></p>");
 
  client.println("<body>");
  client.println("</html>");
 
}


//----------------------------------------------------------------------------

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets


time_t getNtpTime()
{
  time_t timebuf;
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
 
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      timebuf = secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;  // timezone=0 for auto sync (CEST)
      timebuf = CE.toLocal(timebuf, &tcr);
      return timebuf;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}






// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

//----------------------------------------------------------------------------
// END OF FILE
//----------------------------------------------------------------------------


wer Fragen dazu hat: bitte gern einen eigenen Thread dazu aufmachen und dann dort diskutieren!
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Zurück zu „allgemeine / Nicht-Lego-Robotik und Elektronik“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 12 Gäste

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss