Problem mit Interupt

#include <WiFi.h>
#include "time.h"

const char* ssid = "Wokwi-GUEST";
const char* password = "";

const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

String serialoutput = "";

int lastStartAuto = 0;

int counter = 0;

String printDigits(int digits) {
  if (digits < 10) {
    return '0' + String(digits);
  } else {
    return String(digits);
  }
}

void printLocalTime()
{
  struct tm timeinfo;
  if(getLocalTime(&timeinfo)){
    Serial.println(&timeinfo, " %H:%M:%S");
  }
}

String getOutput(String channel) {
  struct tm timeinfo;
  if(getLocalTime(&timeinfo)){
    String time = String(millis());
    time = time.substring(time.length() - 3, time.length());
    String serial = "";
    serial += "*0000 ";
    serial += channel;
    serial += " ";
    serial += printDigits(timeinfo.tm_hour);
    serial += ":";
    serial += printDigits(timeinfo.tm_min);
    serial += ":";
    serial += printDigits(timeinfo.tm_sec);
    serial += ".";
    serial += time;
    serial += "  00\r";
    //Serial.println(timeinfo.tm_sec);
    return serial;
  }
}

void IRAM_ATTR start_auto()
{
  if ((millis() - lastStartAuto) > 1000) {
    serialoutput += getOutput("C2 ");
    //counter++;
    lastStartAuto = millis();
  }
}

void setup()
{
  //Pins definieren
  pinMode(15, INPUT_PULLUP);
  pinMode(32, OUTPUT);
  //Serielle Konsole oeffnen
  Serial.begin(115200);
  //Verbindung zum Wlan
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  }
  //Mit dem Wlan verbunden, aktuelle Zeit holen  
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  //test if time is working
  struct tm timeinfo;
  if(getLocalTime(&timeinfo)){
    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    digitalWrite(32, HIGH);
    Serial.println(getOutput("C9 "));
  }
  //Interrupts für die Lichtschranke und Handtaster setzen
  attachInterrupt(15, start_auto, RISING);
}

void loop()
{
  /*if (serialoutput.length()) {
    Serial.print(serialoutput);
    serialoutput = "";
  }*/
  Serial.println(counter);
  delay(1000);
}

Fehlermeldung ist:

abort() was called at PC 0x40084e5b on core 1 Backtrace: 0x400837da:0x3ffbf13c |<-CORRUPTED

Nach etwas Testen weiß ich, dass das Problem auftritt, beim Aufrufen von getOutput im Interupt.

Ich hoffe ihr könnt mir helfen.

Danke schonmal

Hallo,
wozu einen Interrupt ?
Und eine IRQ-Routine muss immer so kurz wie möglich sein.
Eine Ausgabe auf seriell ist da immer tötlich.

Interupt, um die Zeit möglichst schnell festustellen beim Ereignis (hohe Genauigkeit)

Serial passiert ja erst im loop wenn kein INterupt da ist

Was wäre die bessere Lösung

Im Grunde genommen muss

  1. die Zeit bei Ereignis sehr genau festgestellt werden
  2. die Daten irgendwann später seriell ausgegeben werden

Ich sehe kein getOutput im Interupt.

Aber ja!
Speicherreservierungen im Interrupt sind böse!
Weil malloc() und seine Kumpels meist nicht reentrant geschrieben sind.
Und dann knallt es halt, wie du ja auch siehst.

void IRAM_ATTR start_auto()
{
  if ((millis() - lastStartAuto) > 1000) {
    serialoutput += getOutput("C2 ");
    //counter++;
    lastStartAuto = millis();
  }
}

Nehme ich getOutput raus, läuft alles.

Wie löse ich das am besten?

OK!

Jetzt gefunden!

Lösung gefunden!
Meinen Glückwunsch!

Begründung hier:

Tipp:
String::reserve()

Vielleicht bin ich auch doof.

Habe in setup()

serialoutput.reserve(120);

Trotzdem gleicher Fehler ...

In einer ISR Speicher zu allozieren ist mindestens gefährlich.
Und deine getOutput() macht das reichlich.
Zudem die seriellen Ausgabe.

setz nur den timestamp in deiner ISR und evtl. ein flag
Keine Serielle Ausgabe im ISR.

Später ... sprich im loop wertest den Timestamp aus und schickst was auch immer an die serielle Schnittstelle.

Was veranstaltest Du noch mit serialoutput?
Die wird nirgend gebraucht.
Ansonsten hät ich evtl. mit einem volatile angefangen.
Wenn

nicht erfüllt ist, bekommst Du keinen Rückgabewert.

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