Arduino und ESP miteinander kommunizieren lassen. Suche Stichwörter

Hallo Leute, ich möchte erstmal hier nichts geschenkt haben sondern brauche nur die Begrifflichkeiten damit ich weiter googlen kann. Ich will niemanden die Zeit rauben.

Es geht darum das ich einen Wassertank habe dessen Stand und Temperatur ich auf einem LCD haben will.
Zudem will ich noch 8 Eingänge abfragen. Das sind aber 2 verschieden Räumlichkeiten.

Wassertank HC-SR04 und DS18b20 und einem ESP8266
Digitale Eingänge Arduino micro und ESP8266
Arduino micro und ein LCD2004, ESP8266 und mp3 modul

Die sollen untereinander kommunizieren,

Das LCD soll mir den Tankstand und Wassertemperatur anzeigen.
Zudem will ich halt 8 Eingänge angezeigt bekommen.

Wäre UDP richtig? Also ESP8266->UDP->ESP8266->Seriell->Arduino?

Schau mal hier

Esp mit Esp

Gruß Fips

Warum machst du das nicht mit 2 Wemos D1mini, da sparst du die Arduinos.

Wie groß ist der Wassertank ?
Du wirst mit den HC-SR04 sicher Probleme bekommen, da die nicht Wasserdicht sind. Die oxydieren sehr schnell.
Du kannst aber einen Wasserdichten US-Sensor nehmen.
Der hat allerdings einen kleinen Nachteil, der misst erst ab ca. 20 cm.

Udp ist hervorragend dafür geeignet. Die Kommunikation wird wie die serielle implementiert.

Wenn die "Sensoren" broadcasten, also auf die x.x.x.255 senden, bist du flexibler, wenn du z.B. Mehrere Displays im Haus verteilen willst.

Eine Studie für ESP zu ESP über UDP habe ich hier mal vorgestellt. (#32 und später).

Für ESP - Arduino würde ich I2C vorschlagen. Hier ist ein Beispiel dazu.

Gruß Tommy

So ich bin jetzt einen Schritt weiter, als HMI benutze ich Serialcominstruments.
Ich habe den ESP8266 genommen und schicke die Daten vom DS18b20 und dem Ultraschallsensor an den PC.

Das habe ich irgendwie mit frickeln, kopieren etc. hingekriegt das es funktioniert. Jetzt möchte ich aber einen Ausgang schalten vom Rechner aus.

Das Programm Serialcominstruments schickt als Beispiel per UDP folgendes #20M1<
Kann mir jemand in Grundzügen beschreiben wie ich da am ESP vorgehen muss?

Puffer erstellen, einlesen und auswerten? Ist doch so richtig?

//Libs
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <OneWire.h>

WiFiUDP Client;
OneWire  ds(2);
int zulauf = 13;
byte serdata=0;
byte fromserver=0;
#define TRIGGER 5
#define ECHO    4


void setup()
{

  Serial.begin(9600);
  WiFi.mode(WIFI_STA); 
  WiFi.begin("CinoRBD2","retrobit");
  
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi... ");
  
  pinMode(TRIGGER, OUTPUT);
  pinMode(ECHO, INPUT);
  pinMode(BUILTIN_LED, OUTPUT);
  pinMode(zulauf,INPUT_PULLUP);
    
  while(WiFi.status() != WL_CONNECTED) 
  {
    Serial.print(".");
        delay(500);
  }
     Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());   
    Client.begin(81);

}

void loop()
{

  hoeheudp();
  tempudp();
  if (digitalRead(zulauf)==HIGH){
    zulaufaus();
  } else {
    zulaufan();
  }
  
   

}

void hoeheudp()

{
const char ip[]="192.168.0.104";


    
     long duration, distance;
     long distance1;
  digitalWrite(TRIGGER, LOW);  
  delayMicroseconds(2); 
  
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10); 
  
  digitalWrite(TRIGGER, LOW);
  duration = pulseIn(ECHO, HIGH);
  distance = (duration/2) / 29.1;
  
  Serial.print(distance);
  Serial.println("Centimeter:");
  distance1 = map(distance, 1, 200, 100, 1);
  Client.beginPacket(ip,6001);
  Client.print("#41M");
  Client.print(distance1);
  Client.print("<");
  Client.endPacket();
}

void tempudp()
{
const char ip[]="192.168.0.104";
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return;
}

Serial.print("ROM =");
for ( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}

if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();

// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println("  Chip = DS18S20");  // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println("  Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println("  Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(1000);
  ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(1000);     // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad

Serial.print("  Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) {           // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();

int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print("  Temperature = ");
  Client.beginPacket(ip,6001);
  Client.print("#40M");
  Client.print(celsius);
  Client.print("<");
  Client.endPacket();
  delay(1000);
}

void zulaufan()
{
  const char ip[]="192.168.0.104";
  Client.beginPacket(ip,6001);
  Client.print("#42M");
  Client.print("231");
  Client.print("<");
  Client.endPacket();
}

void zulaufaus()
{
  const char ip[]="192.168.0.104";
  Client.beginPacket(ip,6001);
  Client.print("#42M");
  Client.print("310");
  Client.print("<");
  Client.endPacket();
}

https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/udp-examples.html

Also ich habe jetzt eine Stellen überfliegen die Einlese Routine nicht entdecken können. Funktioniert im Prinzip genauso wie seriell einlesen.

Ich habe das ganze schon einige Monate in Betrieb, auch mit Seriell ComInstruments, läuft wunderbar.

Hallo,

es wird bald die Zeit kommen wo dich deine harten delays in massive Probleme manövrieren. Deshalb frühzeitig gegensteuern.

Mit dem einlesen habe ich ja noch nichts. Bin froh das ich erst mit dem udp senden geschafft habe.

Wie geschrieben das ist alles absolut Neuland für mich. Momentan behelfe ich mir damit, dass ich funktionierende Sketche umschreibe. Zur Zeit sieht das für mich mit dem udp empfangen nach Bäumen aus.

Ich mache mich gleich mit einem Kaffee mal ran.
Ich kann ja in der Visualisierung die udp Adresse einstellen. Ist es die dann für den Esp die ich einstelle? Falls ja, dann kann ich ja anscheinend nur einen esp abfragen. Das wäre für meinen Fall garnicht optimal.

Wie schon weiter oben geschrieben, heißt das Zauberwort Broadcast. Oder du schickst es jeweils an die anderen gezielt raus.

Eventuell habe ich noch mal kurz Zeit, dann kann ich eine Einleseroutine für UDP raussuchen

Broadcast heisst, das UDP Paket wird ins ganze Netzwerk an einen Port geschickt oder?

Sprich wenn ich eine Nachricht Broadcaste an Port 7000 z.B. dann wird die Nachricht an alle IP adressen geschickt?

Ich habe da mal was gefunden. Würde dies so passen?
Ich schicke vom PC folgende Mitteilung. #k10M1<

ist Start < ist Ende

char c = client.read();

        if(reading && c == ' ') reading = false;
        if(c == '#') reading = true; //found the #, begin reading the info

        if(reading){
          
//schalten der Ausgänge

           switch (c) {
            
            case 'k10M1<':
            //add code here to trigger on 3
              digitalWrite(3, HIGH);
              break;
            case 'k10M0<':
            //add code here to trigger on 3
              digitalWrite(93, LOW);
              break;
            
          }

        }

        if (c == '\n' && currentLineIsBlank)  break;

        if (c == '\n') {
          currentLineIsBlank = true;
        }else if (c != '\r') {
          currentLineIsBlank = false;
        }

      }
    }

    delay(1); // pause für den Browser
    client.stop(); // Verbindung trennen

devrim:
Broadcast heisst, das UDP Paket wird ins ganze Netzwerk an einen Port geschickt oder?

Sprich wenn ich eine Nachricht Broadcaste an Port 7000 z.B. dann wird die Nachricht an alle IP adressen geschickt?

ja, genau so isses, entsprechend der Netzwerkmaske. Bei z.B. 255.255.255.0 wird das Paket von allen von x.x.x.1 bis x.x.x.254 erhalten

Danke. Ich melde mich mal für heute ab. Bin auf Geburtstag eingeladen.

Schau mal, hier kannst du dir bestimmt was abschauen.

void checkUDP()
{
  int packetSize;
  char* pos;
  memset(incomingbuffer, 0, sizeof(incomingbuffer));
  // if there's data available, read a packet
  packetSize = Udp.parsePacket();
  if (packetSize)
  {
    // read the packet into packetBufffer
    Udp.read(incomingbuffer, sizeof(incomingbuffer));
    Serial << "UDP erhalten: " << packetSize << " Zeichen  " << incomingbuffer << endl;

    pos = strstr(incomingbuffer, "#200M");
    float windAnalog;
    if (pos)
    {
      windAnalog  = atof(pos + 5);
      windSpeed = windAnalog * 0.02929 * 1024 / 971;
      //     Serial << F("Windspeed=") << windSpeed << "m/s" << endl;
    }

    pos = strstr(incomingbuffer, "#204M");
    if (pos)
    {
      windUmin = atof(pos + 5);
      //      Serial <<F("windAnalog= ") << windAnalog << "    " << F("windUmin= ") << windUmin << " U/min" << endl;
      //      Serial << F("Verhaeltnis= ") << _FLOAT(windAnalog/windUmin,1) << "  windAnalog/windUmin" << endl;
      char buf[10];
      dtostrf(windUmin, strlen(buf), 1, buf);
      Blynk.virtualWrite(V19,  buf);
    }

    pos = strstr(incomingbuffer, "#201M");
    if (pos)
    {
      dachsensor = atof(pos + 5);
      tempLuft = dachsensor;
      Serial << F("TempLuft=") << tempLuft << " C" << endl;
    }

    pos = strstr(incomingbuffer, "#202M");
    if (pos)
    {
      tempSonneDach = atof(pos + 5);
      if (tempSonneDach > tempSonne) tempSonne = tempSonneDach;

      Serial << F("Sonne Dach=") << tempSonneDach << " C  " << "Sonne Terrasse=" << tempSonne << endl;
    }

    pos = strstr(incomingbuffer, "#203M");
    if (pos)
    {
      int fehler = atoi(pos + 5);
      if (fehler)  Serial << F("Beim ESP war eine Messung falsch, Fehler=") << fehler << endl;
    }


    if (!strncmp(incomingbuffer, "#82M", 4)) {  // Daten vom Schiebereglerinstrument 82
      Serial << "UDP erhalten: " << atoi(incomingbuffer + 4) << endl;
      eepromdaten.sollWasserStand = eepromdaten.distanzSR04 + atoi(incomingbuffer + 4);
    }

    if (!strncmp(incomingbuffer, "#74M3<", 6)) eepromdaten.Pin5ON = !eepromdaten.Pin5ON;
    if (!strncmp(incomingbuffer, "#74M2<", 6)) eepromdaten.autonivel_ausgangState = !eepromdaten.autonivel_ausgangState;
    if (!strncmp(incomingbuffer, "#74M1<", 6)) {
      eepromdaten.solarAus_AusgangState = !eepromdaten.solarAus_AusgangState;
    }
    if (!strncmp(incomingbuffer, "#74M4<", 6)) {
      EEPROM.put( 0, eepromdaten );
      Udp.beginPacket({172, 26, 255, 255}, udpport_destino);
      Udp << "#82M" << eepromdaten.sollWasserStand - eepromdaten.distanzSR04  << "<#27M" << eepromdaten.distanzSR04  << "<" <<  endl;
      Udp.endPacket();

      if (!strncmp(incomingbuffer, "#27M", 4)) {  // Daten vom Schiebereglerinstrument 27
        Serial << "UDP erhalten: " << atoi(incomingbuffer + 4) << endl;
        eepromdaten.distanzSR04 = atoi(incomingbuffer + 4);
      }

      Serial << F("Alles gespeichert!") << endl;
      Blynk.notify("blynksendenButtons is pressed!");
    }
    if (!strncmp(incomingbuffer, "#25M1<", 6)) eepromdaten.sollWasserStand -= 1;
    if (!strncmp(incomingbuffer, "#25M2<", 6)) eepromdaten.sollWasserStand += 1;
    if (!strncmp(incomingbuffer, "#25M3<", 6)) eepromdaten.sollWasserStand -= 5;
    if (!strncmp(incomingbuffer, "#25M4<", 6)) eepromdaten.sollWasserStand += 5;
    if (eepromdaten.sollWasserStand < eepromdaten.distanzSR04) eepromdaten.sollWasserStand = eepromdaten.distanzSR04;
    Blynk.virtualWrite(20, (eepromdaten.sollWasserStand - eepromdaten.distanzSR04));

    if (!strncmp(incomingbuffer, "#27M", 4)) {  // Daten vom Schiebereglerinstrument 27
      Serial << "UDP erhalten: " << atoi(incomingbuffer + 4) << endl;
      eepromdaten.distanzSR04 = atoi(incomingbuffer + 4);
    }


  }
  return;
}

Vielen Dank, es hat geklappt. Habe es bisschen umgeschrieben. Hier mal mein Code.

/******************************************************************
 Created with PROGRAMINO IDE for Arduino - 01.09.2017 13:29:38
 Project     : Frischwassertankmesser
 Libraries   : OW, Dallas, ESP8266
 Author      : Cihan Sahin
 Description : Wasserstandsmessung mittels US und Temp DS18b12 UDP
******************************************************************/

//Libs
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <OneWire.h>

WiFiUDP Client;
OneWire  ds(2);

int zulauf = 13;
byte serdata=0;
byte fromserver=0;
char incomingbuffer[255];
#define TRIGGER 5
#define ECHO    4


void setup()
{

  Serial.begin(9600);
  WiFi.mode(WIFI_STA); 
  WiFi.begin("CinoRBD2","retrobit");
  
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi... ");
  
  pinMode(TRIGGER, OUTPUT);
  pinMode(ECHO, INPUT);
  pinMode(BUILTIN_LED, OUTPUT);
  pinMode(zulauf,INPUT_PULLUP);
    
  while(WiFi.status() != WL_CONNECTED) 
  {
    Serial.print(".");
        delay(500);
  }
     Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());   
    Client.begin(6002);
    pinMode(12, OUTPUT);
    digitalWrite(12, HIGH);
    delay(500);
    digitalWrite(12, LOW);

}

void loop()
{

  hoeheudp();
  tempudp();
  checkUDP();
  
  if (digitalRead(zulauf)==HIGH){
    zulaufaus();
  } else {
    zulaufan();
  }
  
   
  
  

}

void hoeheudp()

{
const char ip[]="192.168.0.101";


    
     long duration, distance;
     long distance1;
  digitalWrite(TRIGGER, LOW);  
  delayMicroseconds(2); 
  
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10); 
  
  digitalWrite(TRIGGER, LOW);
  duration = pulseIn(ECHO, HIGH);
  distance = (duration/2) / 29.1;
  
  Serial.print(distance);
  Serial.println("Centimeter:");
  distance1 = map(distance, 1, 200, 100, 1);
  Client.beginPacket(ip,6001);
  Client.print("#41M");
  Client.print(distance1);
  Client.print("<");
  Client.endPacket();
}

void tempudp()
{
const char ip[]="192.168.0.101";
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return;
}

Serial.print("ROM =");
for ( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}

if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();

// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println("  Chip = DS18S20");  // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println("  Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println("  Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(1000);
  ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(750);     // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad

Serial.print("  Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) {           // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();

int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print("  Temperature = ");
  Client.beginPacket(ip,6001);
  Client.print("#40M");
  Client.print(celsius);
  Client.print("<");
  Client.endPacket();
  delay(1000);
}

void zulaufan()
{
  const char ip[]="192.168.0.104";
  Client.beginPacket(ip,6001);
  Client.print("#42M");
  Client.print("231");
  Client.print("<");
  Client.endPacket();
}

void zulaufaus()
{
  const char ip[]="192.168.0.104";
  Client.beginPacket(ip,6001);
  Client.print("#42M");
  Client.print("310");
  Client.print("<");
  Client.endPacket();
}

void checkUDP()
{
  int packetSize;
  char* pos;
  memset(incomingbuffer, 0, sizeof(incomingbuffer));
  packetSize = Client.parsePacket();
  if (packetSize)
  {
    // read the packet into packetBufffer
   Client.read(incomingbuffer, sizeof(incomingbuffer));
    

    pos = strstr(incomingbuffer, "#10M1<");

    if (pos)
    {
      digitalWrite(12, HIGH);
      delay(500);
      digitalWrite(12, LOW);
    }

    pos = strstr(incomingbuffer, "#10M0<");
    if (pos)
    {
      digitalWrite(12, LOW);
    }

    


  }
  return;
}

die Routinen
hoeheudp();
tempudp();

würde ich nicht bei jedem loop aufrufen, sondern nur alle paar Sekunden. Momentan wird das über die delays verzögert, das ist Mist, weil in der Zeit keine eingehenden UDP ausgewertet werden können.

Schau dir mal INTERVAL.h oder vergleichbare libs an.

INTERVAL(5000){
 hoeheudp();
  tempudp();
}

Oder halt zu Fuss mit millis();

Für den US-Sensor gefällt mir NewPing recht gut, und den DS18B20 wertet man einfacher mit der Original Lib aus. über einen endlichen Automaten kannst du sogar die Wartezeit vom Anfordern des Temperaturwertes bis zum Abfragen der eigentlichen Daten blockierungsfrei programmieren.

wird erledigt.