Guru Meditation Error: Core 1 panic'ed

Hallo

Ich arbeite schon länger mit Arduino, bin aber kein Programmierer!
Mein Code wertet über eine UART Kommunikation eine BMS aus
und gibt die Daten per serial aus.

void SOC_Check()                                    // Auswertung SOC
{
  memset(EmpfArray1, 0, sizeof(EmpfArray1));          // leeren des Eingangs Arrays
  Serial2.write(AkkuU_I_SOC, sizeof(AkkuU_I_SOC));  // senden anfrage U/I/SOC 
  startIndex = 0;
  delay(50);                                        // warte 50ms zum abarbeiten für die BM
ReadNext1:                                          // Sprung Adresse für Multi Zeichen Auswertung 
  while (Serial2.available())                       // Routine, wenn neue Daten an UART2 anliegen
    {
      inByte = Serial2.read();                      // das gerade empfangenen Zeichen ins inByte kopieren                                                                               
      EmpfArray1[startIndex] = inByte;              // Empfangenes Zeichen ins Array übertragen        
                                                    // startIndex = die Stelle die kopiert werden soll 
      startIndex++;                                 // hochzählen counter um dann die Position für nächstes Zeichen definieren  
   }                      
}

Der Code ist stark vereinfacht, weil ich den Fehler finden wollte
Aber immer wieder kommt ein:

Guru Meditation Error: Core 1 panic'ed (InstrFetchProhibited). Exception was unhandled.
22:13:28.652 -> Core 1 register dump:
22:13:28.652 -> PC : 0x91dc400d PS : 0x00060130 A0 : 0x800d0c90 A1 : 0x3ffb1f50
22:13:28.698 -> A2 : 0x3ffc00a4 A3 : 0x3ffbebe0 A4 : 0x0000000d A5 : 0x3ffc0098
22:13:28.698 -> A6 : 0x00000002 A7 : 0x00000000 A8 : 0x800d0e53 A9 : 0x3ffb1f30
22:13:28.698 -> A10 : 0x3ffc00a4 A11 : 0x3ffbec2c A12 : 0x3ffbebed A13 : 0x00000001
22:13:28.698 -> A14 : 0x00060d20 A15 : 0x00000000 SAR : 0x00000015 EXCCAUSE: 0x00000014
22:13:28.698 -> EXCVADDR: 0x91dc400c LBEG : 0x4000c28c LEND : 0x4000c296 LCOUNT : 0x00000000

#define RXD2 16
#define TXD2 17

byte inByte = 0;                        // byte to store the serial buffer
byte EmpfArray1[13];                    // Empfangs Array definieren für SOC

int startIndex = 0;                     // start index for start sequence search
int stopIndex = 0;                      // start index for stop sequence search
int testIndex = 0;                      // start index for test sequence search

byte LOOP = 0;                          // Fehler Counter zur ausgabe                     
byte sizeArray = 13;                    // festlegung grösse für Loop Counter Checksum Durchlauf Zahl  

float SOC = 0;
float AKU = 0;
float AKI = 0;
byte AkkuU_I_SOC[] = {0xA5, 0x40, 0x90, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D };

void setup() 
{
  Serial.begin(500000); 
  delay(500);
  Serial.println("");
  Serial.println("");
  Serial.println("Auswertung BMS DS");
  delay(500);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
    delay(500); 
}

void loop() 
{ 
delay(200);
SOC_Check();                   // auswerten SOC 
SOC = ((EmpfArray1[10]*256)+EmpfArray1[11]) / 10.0 ;           // Berechnen SOC Wert
Serial.print("SOC : ");
Serial.print(SOC); 
} 

Hast Du das mal in den Exception-Decoder eingegeben?

Gruß Tommy

Hallo

wenn ich wüsste wie das geht

es ist übrigends ein ESP32

Einfach über das Arrayende hinweg schreiben.
Gute Idee.

OK habs gefunden, werde aber nicht schlau daraus

*Decoding 6 results* 0x400d0c8d: **SOC_Check()** at C:\Empfang\BMS_Read-3/**SOC.ino** line **10** 0x400d0cb5: **loop()** at C:\Empfang\BMS_Read-3/**BMS_Read-3.ino** line **40** 0x400d16d9: **loopTask(void*)** at C:\Users\sdell\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.3\cores\esp32/**main.cpp** line **19** 0x4008a0a1: **vPortTaskWrapper** at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/**port.c** line **355 (discriminator 1)**

nur geraten:

ReadNext1:                                          // Sprung Adresse für Multi Zeichen Auswertung 
  while (Serial2.available())                       // Routine, wenn neue Daten an UART2 anliegen
    {
      inByte = Serial2.read();                      // das gerade empfangenen Zeichen ins inByte kopieren                                                                               
      EmpfArray1[startIndex] = inByte;              // Empfangenes Zeichen ins Array übertragen        
                                                    // startIndex = die Stelle die kopiert werden soll 
      startIndex++;                                 // hochzählen counter um dann die Position für nächstes Zeichen definieren

        if ( startIndex < 13 )                      // für Checksum berechnung und Loop für 0-12 Zeichen  
          {
          Wert = inByte;                            // Wert dient zur Checksum Bildung 
          Check = (Check + Wert) & 0xFF;            // zusammen addieren aller einzelnen Zeichen = Checksum muss mit 13. Zeichen übereinstimmen    
          goto ReadNext1;
          } 

beim kürzen etwas rausgenommen was wichtig war

frage warum läuft es dann 3 Minuten?

Hallo,

der Hinweis kam schon mehrfach. Überlege einmal was mit
startIndex++;
in der Schleife passiert?
Wo wird der Index auf 0 gesetzt?
Schreibe dir eine saubere Einlesefunktion und alles wird gut.

  1. Zeile wird er auf 0 gesetzt
void SOC_Check()                                    // Auswertung SOC
{
  memset(EmpfArray1, 0, sizeof(EmpfArray1));          // leeren des Eingangs Arrays
  Serial2.write(AkkuU_I_SOC, sizeof(AkkuU_I_SOC));  // senden anfrage U/I/SOC 
  *startIndex = 0;*
  delay(50);                                        // warte 50ms zum abarbeiten für die BM
ReadNext1:                                          // Sprung Adresse für Multi Zeichen Auswertung 
  while (Serial2.available())                       // Routine, wenn neue Daten an UART2 anliegen
    {
      inByte = Serial2.read();                      // das gerade empfangenen Zeichen ins inByte kopieren                                                                               
      EmpfArray1[startIndex] = inByte;              // Empfangenes Zeichen ins Array übertragen        
                                                    // startIndex = die Stelle die kopiert werden soll 
      startIndex++;                                 // hochzählen counter um dann die Position für nächstes Zeichen definieren  
   }                      
}

Hallo,

was soll das sein?
*startIndex = 0;*

Kannst du auch einmal reduzierten aber kompletten Code zeigen?
Solche Fetzen ohne Zusammenhang mag hier niemand.

die * hat die hervorheben funktion gemacht
dachte das ist klar
post 9 ist das komplette

void SOC_Check()                                    // Auswertung SOC
{
GoOnLoopSOC:
memset(EmpfArray1, 0, sizeof(EmpfArray1));          // leeren des Eingangs Arrays

  delay(100); 
  Check = 0;                                        // Reset für nächste Runde      
  Wert  = 0;
  Count = 0; 
  Serial.println("");  
  Serial.println("Anfrage SOC starten!");
  delay(5);
  
  Serial2.write(AkkuU_I_SOC, sizeof(AkkuU_I_SOC));  // senden anfrage U/I/SOC 
   
  startIndex = 0;
  delay(50);                                        // warte 50ms zum abarbeiten für die BMS
    
ReadNext1:                                          // Sprung Adresse für Multi Zeichen Auswertung 
  while (Serial2.available())                       // Routine, wenn neue Daten an UART2 anliegen
    {
      inByte = Serial2.read();                      // das gerade empfangenen Zeichen ins inByte kopieren                                                                               
      EmpfArray1[startIndex] = inByte;              // Empfangenes Zeichen ins Array übertragen        
                                                    // startIndex = die Stelle die kopiert werden soll 
      startIndex++;                                 // hochzählen counter um dann die Position für nächstes Zeichen definieren

        if ( startIndex < 13 )                      // für Checksum berechnung und Loop für 0-12 Zeichen  
          {
          Wert = inByte;                            // Wert dient zur Checksum Bildung 
          Check = (Check + Wert) & 0xFF;            // zusammen addieren aller einzelnen Zeichen = Checksum muss mit 13. Zeichen übereinstimmen    
          goto ReadNext1;
          }
          yield();
   }                                     
      for( int i = 0; i < 13; i++ )                 // zur Doku Zeichen einzeln ausgeben
         {
          Serial.print(EmpfArray1[i], HEX);         // durch for Schleife definiertes Zeichen einzeln ausgeben
          Serial.print(" ");
         }

if ( EmpfArray1[0] == 0 )
  { 
    Serial.println("LeerDaten"); 
    goto GoOnLoopSOC; 
  }
         
if ( Check == EmpfArray1[12] )
  { delay(5); }           // Checksum OK
    else 
    { 
    Serial.println("Checksum Error");               // Checksum nicht OK, neue Auswertung 
    goto GoOnLoopSOC; 
    }                       
}    

leerdaten und checksum Fehler bewirken eine neue Ausgabe und neue Auswertung

Hallo,

das Problem ist, * ist auch ein Dereferenzierungsoperator.
Sowas verwirrt nur.

Du hast aber wieder keine Kontrolle über den Index. Wenn der Empfangsbuffer von Serial2 immer gefüllt ist, zählt startIndex++ munter weiter hoch. Erstmal wenn der Buffer einmal leer sein sollte wird er bei Eintritt in die Funktion SOC_Check() auf 0 gesetzt. Es fehlt jede Kontrolle über den Index und der Länge deines Arrays zum Datenempfang. Übrigens wann soll das einlesen unter normalen Umständen beendet werden? Was wird eingelesen? Gibt es ein Protokoll?
Wie gesagt mit dem Fetzen kann man fast nichts anfangen.

Es kommen immer 13 Zeichen rein und bestimmte Stellen definieren einen Messwert

solange Startindex kleiner wie 13 ist, wird nochmal ein Zeichen eingelesen und in das EmpfArray
geschrieben

nur in der inneren Loop wird der Startindex hoch gezählt und beim Start auf 0 gesetzt

ich seh keinen Fehler, aber das ist wohl normal

PS es läuft ein paar minuten, dann mal nur 2-3 mal ???

Hallo,

du musst deinen eigenen Code Zeile für Zeile durchgehen. Wenn das zu kompliziert ist, baue dir Serielle Debugausgaben ein, damit du siehst was deine Funktion machen.

Ganz einfach gelöst:

void SOC_Check()                                    // Auswertung SOC
{
  memset(EmpfArray1, 0, sizeof(EmpfArray1));          // leeren des Eingangs Arrays
  Serial2.write(AkkuU_I_SOC, sizeof(AkkuU_I_SOC));  // senden anfrage U/I/SOC
  startIndex = 0;
  delay(50);                                        // warte 50ms zum abarbeiten für die BM
  while (Serial2.available())                       // Routine, wenn neue Daten an UART2 anliegen
  {
    inByte = Serial2.read();                      // das gerade empfangenen Zeichen ins inByte kopieren
    EmpfArray1[startIndex] = inByte;              // Empfangenes Zeichen ins Array übertragen
    // startIndex = die Stelle die kopiert werden soll
    startIndex++;                                 // hochzählen counter um dann die Position für nächstes Zeichen definieren
    if (startIndex > sizeof(EmpfArray1))
    {
      Serial.println(F("Schluß mit lustig!"));
      Serial.println(F("startindex ist voll"));
      Serial.println(F("lösche den Puffer und fange von vorn an"));
      memset(EmpfArray1, 0, sizeof(EmpfArray1));
      startIndex = 0;
    }
  }
}

Du hast 3 Annahmen, von denen ich überzeugt bin, das 2 definitiv nicht zutreffen.

  1. Die gehts ohne Wissen was Du auf der seriellen Schnittstelle an Daten bekommst immer davon aus, das Byte 10 und 11 Deine Information enthalten
  2. Du gehst immer davon aus - und das ist Dein Problem - das die Übertragung nach Byte 13 zu Ende ist, nie mehr was kommt und damit

irgendwann falsch wird.
Annahme 2 ist dann der auch Dein Problem. Denn wenn die nicht zutrifft, trifft auch Deine Annahme 3 nicht zu, das Du vor Ende des Arrays aus der Schleife raus kommst.

Verstanden?

Wie sieht denn das Telegramm aus?
Hat es einen Marker für Anfang oder Ende?

nein ist nicht ganz so!
bin gerade dabei , den Fehler zu suchen und lass mir immer den Wert vom Startindex ausgeben.
sieht so aus wie es sein sollte!
jetzt stürzt der ESP aber auch nicht mehr ab!
muss es wohl selber mit Test Ausgaben herausfinden
ich mach aber auch nur die SOC Ausgabe und Auswertung
vorher habe ich hintereinander noch 2 weitere geprüft?!?

Doch ist genau so.
Solange Du mehr als 13 bytes ohne Abbruchfunktion liest, ist Deine Routine kaputt.
Wenn der Sender mehr als 13 bytes sendet, gehts Du fälschlich davon aus, das nach 13 bytes Schluß ist.

Das dem nicht so ist hast Du mehrfach erfahren.
Du könntest es alternativ mit meinem Codeschnipsel überprüfen.
Kommt die Serielle Ausgabe nicht, liege ich falsch.
Dann ist der Fehler aber auch an einer ganz anderen Stelle...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.