ESP now Bitte um Hilfe

Hallo,
ich bitte um Hilfe zu ESP now :
Ich habe eine funktionierende Verbindung mit ESP now mit 2 Transmittern und einem Receiver aufgebaut. Nun möchte ich im Receiver erkennen ob ein T sich abgehängt hat. Ein Lifebit im struct der Daten nützt nichts da das ( nenne es mal so ) Empfangspuffer den letzten Wert einfriert. Die Funktion peer exist ist statisch.
Ich komme da nicht weiter - hat jemand bitte eine Idee ?
Weiterhin habe ich ein grundsätzliches Problem das die Abfrage und die Ausgaben sich alle im void setup befinden - es dürfte somit nur einmal aufgerufen werden??.

Danke und Gruss Olmuk

Hallo,

setup() wird einmalig nach Reset abgearbeitet.
loop() ist die Hauptschleife und wird ständig wiederholt durchlaufen.

Bei ESP kann ich dir nicht helfen, aber damit dir jemand überhaupt helfen kann wäre dein Sketch von Vorteil. Wenn zu groß als Dateianhang, ansonsten in Code Tags einbetten. Siehe hier wo du schreibst im Editor Menü der Code Tags Button.

Lies mal Getting Started with ESP-NOW (ESP32 with Arduino IDE), ob da was steht.

Danke für die Hinweise, aber genau das ist mein Problem mit dem setup

Die Funktion onDataRecv wird im setup aufgerufen und liefert trotzdem ständig die Daten
der T mit MAC - wie kann das sein ?

//*********************************************************************** 
// Funktion ESP now
//***********************************************************************
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) 
{
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData)); 
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id-1].id = myData.id;
  boardsStruct[myData.id-1].val1 = myData.val1;
  boardsStruct[myData.id-1].val2 = myData.val2;
  Serial.printf("Board: %d \n", boardsStruct[myData.id-1].id);
  Serial.printf("x value: %d \n", boardsStruct[myData.id-1].val1);
  Serial.printf("y value: %d \n", boardsStruct[myData.id-1].val2);
  Serial.println();  

}
 
void setup() 
{
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

//*** ESP-NOW initialisieren
  if (esp_now_init() != ESP_OK) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);


}//*** Loop Setup

@agmue : ich habe das gemäß der Tutorials ( auch Santos ) aufgebaut und es läuft ja.

Nur das Einbauen der Funktion "esp_now_is_peer_exist" in setup oder loop bringt nichts.

Wie kann man denn die gelesenen Daten ablöschen vor einer erneuten Abfrage ?`

Merk dir die Zeit, wenn du ein Paket empfängst (für jeden Transmitter einzeln).
Wenn der letzte Empfang zu lange her ist, hast du die Verbindung verloren.

1 Like

Hallo,

ist das der komplette Sketch?
Weil die loop() fehlt. Ist die leer? Leere loop() sollte man nicht weglassen, denke ich.
Das Verhalten eines ESP kenne ich nicht.
Füge einmal nach Serial.begin() ein
Serial.println("ESP Reset");
hinzu. Nicht das er sich ständig resetet. Könnte ja sein.

Hier der gesamte code

// *** ESP32_BDE_Receiver_V203_130923_1
// *** Hardware : 

#include <esp_now.h>
#include <WiFi.h>

//*********************************************************************** 
// Variablen
//***********************************************************************
  int board1id;
  int board2id;
  int board3id;
  int board4id;
  int board5id;
  int board1_val1;
  int board1_val2;
  int board2_val1;
  int board2_val2;
  int board3_val1;
  int board3_val2;
  int board4_val1;
  int board4_val2;
  int board5_val1;
  int board5_val2;

//*********************************************************************** 
// Inhalt Tabelle
//*********************************************************************** 
  String header;
  String Temp11;
  String Temp12;
  String Temp13;
  String Temp21;
  String Temp22;
  String Temp23;
  String Temp31;
  String Temp32;
  String Temp41;
  String Temp42;
  String Temp43;
  String Temp51;
  String Temp52;
  String Temp53;
  String Temp33;
  String M11 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >MASCHINE OK</td>";
  String M12 ="<td align=center table width=20% height=55 border bgcolor=#DF0101 style=\"color: white;\">ERROR</td>";
  String M21 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >PROGRAMM RUN</td>";
  String M22 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">PROGRAMM STOP</td>";
  String M31 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\">BELADUNG AKTIV</td>";
  String M32 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">BELADUNG INAKTIV</td>";
  String M41 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >ANTRIEBE EIN</td>";
  String M42 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">ANTRIEBE AUS</td>";
  String M51 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >ANTRIEBE EIN</td>";
  String M52 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">ANTRIEBE AUS</td>";
  String M61 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >LASER EIN</td>";
  String M62 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">LASER AUS</td>";
  String M71 ="<td align=center table width=20% height=55 border bgcolor=#31B404 style=\"color: white;\" >HV EIN</td>";
  String M72 ="<td align=center table width=20% height=55 border bgcolor=#DF7401 style=\"color: white;\">HV AUS</td>";


//*** Struktur Empfangsdaten
typedef struct struct_message 
{
  int id;                   // Id Board
  int val1;                 // Wert Status
  int val2;                 // Wert Reserve
}
struct_message;

//*** Message erstellen
struct_message myData;

//*** Struktur Daten Boards
 struct_message board1;
 struct_message board2;
 struct_message board3;
 struct_message board4;
 struct_message board5;

//*** Array für Board Daten
struct_message boardsStruct[5] = {board1, board2, board3, board4, board5};

//*********************************************************************** 
// Funktion ESP now
//***********************************************************************
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) 
{
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData)); 
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id-1].id = myData.id;
  boardsStruct[myData.id-1].val1 = myData.val1;
  boardsStruct[myData.id-1].val2 = myData.val2;
  Serial.printf("Board: %d \n", boardsStruct[myData.id-1].id);
  Serial.printf("x value: %d \n", boardsStruct[myData.id-1].val1);
  Serial.printf("y value: %d \n", boardsStruct[myData.id-1].val2);
  Serial.println();  

}
 
void setup() 
{
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

//*** ESP-NOW initialisieren
  if (esp_now_init() != ESP_OK) 
  {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);


}//*** Loop Setup
 
void loop() 
{

// if ((millis() - lastTime) > timerDelay) {
// lastTime = millis();


  board1id = boardsStruct[0].id;
  board2id = boardsStruct[1].id;
  board3id = boardsStruct[2].id;
  board4id = boardsStruct[3].id;
  board5id = boardsStruct[4].id;
  board1_val1 = boardsStruct[0].val1;
  board1_val2 = boardsStruct[0].val2;
  board2_val1 = boardsStruct[1].val1;
  board2_val2 = boardsStruct[1].val2;
  board3_val1 = boardsStruct[2].val1;
  board3_val2 = boardsStruct[2].val2;
  board4_val1 = boardsStruct[3].val1;
  board4_val2 = boardsStruct[3].val2;
  board5_val1 = boardsStruct[4].val1;
  board5_val2 = boardsStruct[4].val2;



    Serial.print(board1id);
    Serial.print(board1_val1);
    Serial.println(board1_val2);
    Serial.print(board2id);
    Serial.print(board2_val1);
    Serial.println(board2_val2);
    Serial.print(board3id);
    Serial.print(board3_val1);
    Serial.println(board3_val2);

    /*
    Serial.print(board4id);
    Serial.print(board4_val1);
    Serial.println(board4_val2);
    Serial.print(board5id);
    Serial.print(board5_val1);
    Serial.println(board5_val2);
    */


  if(board1id != 1)
  Serial.println("Board1 keine Verbindung");

  if(board2id != 2)
  Serial.println("Board2 keine Verbindung");


//************************************************************************************************
//*** Auswertelogik
//************************************************************************************************

          // Maschine 1            
            // Logik Anzeige In 1 
            if(board1_val1 == 1)
            Temp11 = M11;
            else
            Temp11 = M12;

            // Logik Anzeige In 2
            if(board1_val1 == 2)
            Temp12 = M21;
            else
            Temp12 = M22;
            
            // Logik Anzeige In 3
            if(board1_val1 == 4)
            Temp13 = M31;
            else
            Temp13 = M32;

// Maschine 2
            // Logik Anzeige In 1 
            if(board2_val1 == 1)
            Temp21 = M11;
            else
            Temp21 = M12;

            // Logik Anzeige In 2
            if(board2_val1 == 2)
            Temp22 = M21;
            else
            Temp22 = M22;
            
            // Logik Anzeige In 3
            if(board2_val1 == 4)
            Temp23 = M31;
            else
            Temp23 = M32;

// Maschine 3
            // Logik Anzeige In 1 
            if(board3_val1 == 1)
            Temp31 = M41;
            else
            Temp31 = M42;

            // Logik Anzeige In 2
            if(board3_val1 == 2)
            Temp32 = M51;
            else
            Temp32 = M52;
            
            // Logik Anzeige In 3
            if(board3_val1 == 4)
            Temp33 = M31;
            else
            Temp33 = M32;

  // Maschine 4
            // Logik Anzeige In 1 
            if(board4_val1 == 1)
            Temp41 = M41;
            else
            Temp41 = M42;

            // Logik Anzeige In 2
            if(board4_val1 == 2)
            Temp42 = M51;
            else
            Temp42 = M52;
            
            // Logik Anzeige In 3
            if(board4_val1 == 4)
            Temp43 = M31;
            else
            Temp43 = M32;          

  // Maschine 5
            // Logik Anzeige In 1 
            if(board5_val1 == 1)
            Temp31 = M41;
            else
            Temp31 = M42;

            // Logik Anzeige In 2
            if(board5_val1 == 2)
            Temp32 = M51;
            else
            Temp32 = M52;
            
            // Logik Anzeige In 3
            if(board5_val1 == 4)
            Temp33 = M31;
            else
            Temp33 = M32;    

 // delay(1000); 



}

Hallo,
wenn Du schon ein lifebit nutzen willst dann eventuell so: Der Sender muss das Bit toggeln bei jeden senden. Der Empfänger überprüft ob sich das empfangene Bit in einer gewissen Zeit geändert hat. Wenn nicht ist die Verbindung weg.

@Rentner war schneller :slightly_smiling_face:
Ich hätte auch togglen vorgeschlagen. Wird oft auch in industriesteuerungen so gemacht mit identischem anwendungsfall um z.b. zu überwachen ob ein peripherie modul "eingefroren" bzw abgehängt ist. Wenn sich der zustand vom lifebit nicht x sekunden geändert hat => alarm etc.

Lifebit Abfragen sind Standard in der SPS Welt wo ich herkomme, danke.
Es wird in keiner Beschreibung der ESP now Funktion auf eine Abfrage der Transmitter eingegangen was ich als sehr wichtig ertrachte. Beim Abhängen frieren ja auch die Daten ein.

Und bitte an die Spezialisten : wie wird die zyklische Abfrage im setup realisiert bei nur dem einen Durchlauf nach Reset ?

Das es funktioniert ist ja toll, aber ich will auch gerne wissen wie

Damit gibst Du die function an die dann aufgerufen wird wenn was vom Sender angekommen ist. In der Function kannst Du dann die Auswertung des Lifebits oder der Zeit machen. Die Funktion selbst wird vom ESP dann im Hintergrund aufgerufen.

Wenn Du Dich mit Lifebits auskennst warum fragst Du dann ?
Eventuell gibt es innerhalb der ESP Now Funktionalität eine andere Möglichkeit , mit ESP Now kenne ich mich nicht so wirklich aus.
Heinz

Schicken die Transmitter regelmäßig Daten *)? Dann soll es doch ein leichtes sein sich bei eintreffen der Nachricht die millis() zu merken und im loop zu prüfen ob ein Intervall überschritten wurde.

Also eigentich genau so wie es @Whandall schon vorgeschlagen hat.

*) Wenn sie noch nicht regelmäßig senden - dann lass sie regelmäßig senden.

Das ist nur ein Missverständnis deinerseits.
Du hast im setup die callbackfunktion für den Event "recv" bekanntgegeben. Damit weis die Library im Hintergrund nun, was sie bei eintreffen einer Nachricht machen soll. Nämlich die Funktion OnDataRecv ausführen.

Hallo,

Langsam wird es komisch. Wenn es zyklisch sein soll musst du es in der loop() behandeln.
Das setup() nur einmal abgearbeitet wird sollte nun klar sein.
Siehe Antwort von Whandall und noiasca.

Letztlich halte ich das auch für die einfachste Lösung, da muss der Sender gar nichts machen , nur der Empfänger prüft ob Daten im richtigen Zeitraster angekommen sind. Voraussetzung ist natürlich das es ein mehr oder weniger festes Zeitraster gibt. Aber wenn nicht macht auch ein Lifebit wenig Sinn.

Erst mal vielen Dank für die Hilfe an alle.
Ich verwende leider Begriffe die vll. nicht immer in die uC Welt passen.

Mit dem setup ist es genau mein Verständnisproblem. Ich habe mich strikt an die Vorlagen Santos und Wolle gehalten, sie machen den Aufruf identisch.
Laut dem code kann ja das nur im Hintergrund laufen da ja die Funktion nur einmal aufgerufen wird.
Die Vorlagen der Transmitter benutzen in allen Vorlagen einen Zyklus mit delay.
Das ist für mich bei dieser tollen Funktion widersprüchlich und ich hatte gehofft das mir da jemand auf die Sprünge helfen kann.

Es gab ja schon Denkanstöße die immer hilfreich sind.

noiasca hatte den richtigen Ansatz, habe es aber leider überlesen.
Hatte noch einen Beitrag gefunden der etwas darauf eingeht : mit dem Aufruf im setup wird wohl
sie Funktion durch die ESP now Funktion mit Daten gefüttert.
Ich werde mal probieren den Parameter über die Abfrage der peers mit Leben zu füllen.

Nochmal danke an alle, wenn aber jemand etwas weiss bitte übermitteln

Nein die function wird durch den Aufruf

  esp_now_register_recv_cb(OnDataRecv);

NICHT mit Daten gefüttert.

die function

void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) 

wird als sogenannte CALLBACK-function registriert.
// Once ESPNow is successfully Init, we will register for recv CB to

  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);

Die Registrierung der callback-function muss nur einmal im setup-gemacht werden
call-back bedeutet:

jedesmal wenn Daten empfangen werden wird die CALLBACK-function aufgerufen.
ESP-NOW ist ein ziemlich großes Programmpaket was da im Hintergrund läuft.
Der Empfang von WiFi-Daten ist ziemlich komplex. Das bekommt man mit pollendem Abfragen in loop() wahrscheinlich gar nicht hin.

Mit dem registrieren der CALLBACK-function machst du als Programmierer
Hallo ESP-NOW-Funktionen immer dann wenn Daten empfangen wurden dann rufe
OnDataRecv() auf.

Das kannst du dir so ähnlich vorstellen wie
du baust dir einen Sensor und eine Kamera in deinen Briefkasten ein.
Aus dem dass der Sensor und die Kamera im Briefkasten eingebaut sind (=Registrierung der call-back-function)
hast du noch keine Daten.

Daten gibt es erst dann wenn der Sensor das Einwerfen (=Datenpaket empfangen) eines Briefes in den Briefkasten detektiert
und darauf hin die Kamera einschaltet und die Kamera ein Bild vom eingeworfenen Brief überträgt.

Das entspricht dem Aufrufen der callback-function.

Einmal Sensor und Kamera einbauen (= callback-function registrieren)
tausende mal ein Bild gesendet bekommen (= callback-function ausführen)

vgs

Da ist er der Bescheid weiss, super!
Vielen Dank !
Müsste ich dann die Abfrage ob die peers vorhanden sind in OnDataRcv einbinden ?

Gut erklärt