ESP32 Seltsame Ausgabe im seriellen Monitor

Hallo, ich schon wieder.

ich habe ein ziemlich seltsames Phänomen mit dem seriellen Monitor.
Obwohl in meinem Sketch nirgendwo eine Ausgabe auf der seriellen Schnittstelle stattfindet, sehe ich im seriellen Monitor seltsame Zeichen (Kästchen, Tilden und >).

Ich wollte mit seriellen Ausgaben einen Logikfehler finden und habe deshalb die Ausgaben ins Programm eingebaut. Aber statt Texten und Werten nur eben diese Zeichen erhalten, die man auch bekommt, wenn die Baudrate im seriellen Monitor falsch eingestellt ist.

Selbst, als ich dann meine drei Seriel.print herausgenommen und sogar Serial.begin() auskommentiert habe, habe ich noch diese Zeichen bekommen.
Ich habe auch mal alle Baudraten im Monitor durchgeklickt, aber nichts sinnvolles zu sehen bekommen.

Seltsam ist dabei auch, daß diese Zeichen einmal pro Sekunde kommen.
Mein Verdacht war, daß das Debuginformationen des ESP sind, aber im Menu Werkzeuge ist der core debug level auf "keine" eingestellt.

Mein Verdacht ist ja, daß ich irgendwo einen Speicherüberlauf habe oder der Stack zu klein ist. Den kann ich aber anscheinend nirgendwo einstellen. Und eigentlich kann ich mir das bei 23% verbrauchtem Programmspeicher und 6% Arbeitsspeicher irgendwie nicht wirklich vorstellen.

Ein testweise aufgespieltes Beispielprogramm funktioniert, also muss das Problem wohl irgendwo in meinem Code stecken.

Allerdings ist der Code vermutlich ziemlich unübersichtlich. Ich hänge ihn trotzdem mal an:




// I/Os
#define in_encA  27             // Encoder A
#define in_encB  26             // Encoder B
#define in_encBt  14            // Encoder button

#define in_BtSt  13             // Taster "Start"
#define out_BtLED  12           // LED Starttaster
#define out_WLED  15            // WSD-LEDs
#define in_1Khz  16             // 1Khz Signal

#define ai_5V  33               // Analogeingang 5V
#define ai_12V  4               // Analogeingang 12V

#define in_TAKT  36             // Eingang Takt
#define in_MOVE  39             // Eingang Bewegung
#define in_DIR   34             // Eingang Richtung
#define in_TRIGSENS  35         // Eingang Auslösersensor
#define out_TRIG  32            // Ausgang Auslöser

#define free1  17               // I/O frei
#define free2  25               // I/O frei

// Arduino Standardlibs
#include <Arduino.h>

// I2C
#include <Wire.h>

// SPI
#include <SPI.h>

// Display
#include <U8x8lib.h>
U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI u8x8(/* cs=*/ 17, /* dc=*/ 1, /* reset=*/ 3);

// Encoder
#include <SimpleRotary.h>
SimpleRotary rotary(in_encA, in_encB, in_encBt);

// WS2812-LEDS
#include <FastLED.h>
CRGB leds[2];   // 2 LEDs


// RTC
#include <DS3231.h>
DS3231 myRTC;

// PCNT Hardwarecounter (2 stück)
#include "my-pcnt.h"
/*  pcnt_init_time();           // Counter für Zeit initialisieren und starten
    pcnt_init_speed();          // Counter für Geschwindigkeit initialisieren und starten
    pcnt_get_time(&cnt_time);   // Anzahl der Pulse für Zeit auslesen (&count = Zeiger auf Variable int16_t)
    pcnt_get_speed(&cnt_speed); // Anzahl der Pulse für Geschwindigkeit auslesen (&count = Zeiger auf Variable int16_t)
    pcnt_clear_time();          // Counter für Zeit löschen
    pcnt_clear_speed();         // Counter für Geschwindigkeit löschen
  // Maximale Messzeit für Zeit : 32 Sekunden, sonst Überlauf des Hardwarecounters
*/

// Variablendeklarationen

//byte encRot = 0;
//byte num = 0;
//byte num_alt = 1;

// Variablen für 200ms takt
unsigned long currentMillis;        // aktuelle Millisekunden
unsigned long previousMillis = 0;   // alte Millisekunden



// Variablen für Uhr
bool rtcErrorOsc = false;           // Fehler Oszillator RTC
bool rtcErrorTemp = false;          // Fehler Temperatur RTC
bool rtcErrorTime = false;          // Fehler der Uhrzeit
float rtcTempRaw = -9999;           // Temperatur der RTC
unsigned int rtcTemp;               // Temperatur der RTC
byte clkSec;                        // aktuelle Sekunde
byte clkSecPrev = 99;               // letzte Sekunde
byte clkMin;                        // aktuelle Minute
byte clkMinPrev = 99;               // letzte Minunte
byte clkHour;                       // aktuelle Stunde
byte clkHourPrev = 99;              // letzte Stunde
byte clkDow;                        // Wochentag
byte clkDay;                        // aktueller Tag im Monat
byte clkMonth;                      // aktueller Monat
byte clkYear;                       // aktuelles Jahr
String DOWS[7] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"};   // wochentage, brauchen wir die?
bool h12Flag;                       // 12/24 Stunden flag - - Scheiß englischen Zeiten
bool pmFlag;                        // am/pm flag
bool centuryFlag;                   // Schaltjahr         - - Scheiß Schaltjahre
bool newDay = true;                 // Tageswechsel

// Variablen für Messwerte
int16_t cnt_time;                   // Zählwert für Pulse Zeit
int16_t cnt_speed;                  // Zählwert für Pulse Geschwindigkeit

// Systemvariablen
bool ticSec = true;                 // Sekundentakt
byte sysErrorLvl = 0;               // Fehlerlevel Gesamtsystem
bool Error = false;                 // ein Fehler ist aufgetreten
bool sysMessen = false;             // Messung findet statt
int sysMagnetfeld;                  // Magnetfeldstärke   (Wird das überhaupt benötigt?)
unsigned int ai5V;                  // Analoger Eingangswert 5V
unsigned int ai12V;                 // Analoger Eingangswert 12V
unsigned int ar5V[11];              // Array für floating average 5V
unsigned int ar12V[11];             // Array für floating average 12V
byte ptarSpg = 1;                   // Zeiger auf Array Mittelwert beide Spannungen
unsigned int aix10_5V;              // analoger Eingangswert 5V * 10   (Eingangswerte werden mit 10 multipliziert, um einstellige
unsigned int aix10_12V;             // Analoger Eingangswert 12V * 10  Nachkommastellen zu erhalten)
float U5V;                          // Spannung 5V mit 1 Nachkommastelle
float U12V;                         // Spannung 12V mit 1 Nachkommastelle



byte SysState = 1;                  // Systemstatus (0=Fehler, 1=Menü, 2=Messung bereit, 3=Messung manuell starten
// 4=Messung automatisch starten, 5=messung starten, 6=Messung läuft,
// 7=Messung beendet, 8=Messdaten anzeigen, 9=Messdaten speichern,

// Variablen für Menüführung
byte sysMenu = 10;                  // Menüebene (0=Fehler, 11=Hauptmenu, 21=Messen, 31=BWS-Setup, 41=Sensorsetup
// 51=Kalibrieren, 61=Status, 71=Selbsttest, 81=Fehleranzeige, 91= Messwerte)
// (X0=Menütext, X1=Manüaktion)
byte menuLineMax;                   // Anzahl der Menüpunkte
byte menuLineStart;                 // Zeile des ersten Menüpunkts
byte cursorY = 0;                   // Cursorposition
byte cursorYalt = 10;               // Cursorposition alt
byte encRot = 0;                    // Encoder rotation (1=runter, 2=rauf)

byte lut11[8] = {11, 11, 11, 11, 11, 11, 11, 60};     // Lookuptable für Hauptmenü (11)
byte lut61[8] = {10, 10, 10, 10, 10, 10, 10, 10};     // Lookuptable für Status (61)

//Variablen für Menü und Bildschirmausgabe
byte posX;                          // X-Position
byte posY;                          // Y-Position


// *************
// **  SETUP  **
// *************
void setup() {
  delay(1000);        // Dummheitsdelay

  // I2C
  Wire.begin();
  Wire.setClock(400000L);

  // Serielle Schnittstelle
  Serial.begin(115200);

  // Pinsetup
  pinMode (2, OUTPUT);
  pinMode (in_encA, INPUT);
  pinMode (in_encB, INPUT);
  pinMode (in_encBt, INPUT);

  pinMode (in_BtSt, INPUT_PULLUP);
  pinMode (out_BtLED, OUTPUT);
  pinMode (out_WLED, OUTPUT);
  pinMode (in_1Khz, INPUT);

  pinMode (in_TAKT, INPUT);
  pinMode (in_MOVE, INPUT);
  pinMode (in_DIR, INPUT);
  pinMode (in_TRIGSENS, INPUT);
  pinMode (out_TRIG, OUTPUT);

  // Encoder
  rotary.setTrigger(LOW);

  // LEDs
  FastLED.addLeds<WS2812B, 15, GRB>(leds, 2);   // GRB ordering is typical

  // RTC
  myRTC.enableOscillator(true, false, 1);       // Oszillator einschalten (ein, bei Batteriebetrieb aus, 1024Hz)
  rtcErrorOsc = myRTC.oscillatorCheck();        // Oszillator der RTC überprüfen
  rtcTempRaw = myRTC.getTemperature();          // Temperatur der RTC auslesen
  if ((rtcTempRaw < 0) || (rtcTempRaw > 40)) {  // Fehler wenn Temperaturbereich nicht eingehalten ist
    rtcErrorTemp = true;
  }
  clkYear = myRTC.getYear();
  if ((clkYear == 72) || (clkYear <= 24)) {
    rtcErrorTime = true;
  }


  // Display initialisieren
  u8x8.begin();
  u8x8.setFont(u8x8_font_5x7_f);

  // Auflösung der Analogeingänge (12bit/4096 Stufen)
  analogReadResolution(12);
}
// Setup Ende ------------------------------------------------------------------


// ************
// **  LOOP  **
// ************
void loop() {


  // Sekundentakt erzeugen und regelmässig ausgeführte Funktionen
  clkSec = myRTC.getSecond();
  if (clkSec != clkSecPrev) {
    clkSecPrev = clkSec;
    ticSec = true;
    //    rtcErrorOsc = myRTC.oscillatorCheck();        // Oszillator der RTC überprüfen
    //    rtcTempRaw = myRTC.getTemperature();          // Temperatur der RTC auslesen
    //    if ((rtcTempRaw < 0) || (rtcTempRaw > 40)) {  // Fehler wenn Temperaturbereich nicht eingehalten ist
    //      rtcErrorTemp = true;
    //    }
    //    rtcTemp = (unsigned int) rtcTempRaw;
    //    sysMagnetfeld = hallRead();
    rtcRead();
  }   // Ende Sekundentakt --------------------------------------


  // 200ms Takt für gleitenden Mittelwert Spannungsmessung
  if (currentMillis - previousMillis >= 200) {
    previousMillis = currentMillis;

    ar5V[ptarSpg] = analogRead(33);
    ar12V[ptarSpg] = analogRead(4);
    ptarSpg ++; // Zeiger auf Array erhöhen
    if (ptarSpg > 10) {
      ptarSpg = 1;
    }
    aix10_5V = 0;
    aix10_12V = 0;
    for (byte i = 1; i < 11; i++) {
      aix10_5V = aix10_5V + ar5V[i];
      aix10_12V = aix10_12V + ar12V[i];
    }
    aix10_5V = map(aix10_5V, 27520, 37890, 45, 55);
    aix10_12V = map(aix10_12V, 25910, 38250, 111, 144);

    U5V = float(aix10_5V) / 10;
    U12V = float(aix10_12V) / 10;
  }   // Ende gleitender Mittelwert Spannungsmessungen



  // **********
  // *  Menü  *
  // **********
  switch (sysMenu) {
    case 0 :  // Fehler
      break;

    case 10 : // Hauptmenü Texte
      u8x8.clear();
      u8x8.setCursor(0, 0);
      u8x8.println(" BWST924");
      u8x8.println();
      u8x8.println(" messen");
      u8x8.println(" BWS");
      u8x8.println(" Sensor");
      u8x8.println(" Setup");
      u8x8.println(" Kalibrieren");
      u8x8.print(" Status");
      menuLineStart = 2;
      menuLineMax = 7;
      sysMenu = 11;
      cursorY = menuLineStart;
      drawCursor(0);
      printTime(11, 0, false, true);
      break;

    case 11 : // Hauptmenü
      encRot = rotary.rotate();
      if (encRot > 0) {
        drawCursor(encRot);
        u8x8.setCursor(15, 7);
        u8x8.print(cursorY);
      }
      if (rotary.push() == 1) {
        sysMenu = lut11[cursorY];
      }
      if (ticSec) {
        printTime(11, 0, false, false);
      }
      break;

    case 20 : // Menü Messen Texte
      sysMenu = 21;
      break;

    case 21 : // Menü messen
      break;

    case 30 : // Menü BWS Texte
      sysMenu = 31;
      break;

    case 31 : // Menü BWS
      break;

    case 40 : // Menü Sensor Texte
      sysMenu = 41;
      break;

    case 41 : // Manü Sensor
      break;

    case 50 : // Kalibrieren Texte
      sysMenu = 51;
      break;

    case 51 : // Kalibrieren
      break;

    case 60 : // Status Texte
      u8x8.clear();
      u8x8.setCursor(0, 0);
      u8x8.println(" STATUS");
      u8x8.println();
      u8x8.println(" 5V");
      u8x8.println(" 12V");
      u8x8.println(" temp.");
      u8x8.println(" Takt");
      u8x8.println(" magn.");
      u8x8.print(" <-");
      menuLineStart = 7;
      menuLineMax = 7;
      cursorY = menuLineStart;
      drawCursor(0);
      sysMenu = 61;
      break;

    case 61 : // Status
      if (rotary.push() == 1) {
        sysMenu = lut61[cursorY];
      }

      if (ticSec) {
        rtcTempRaw = myRTC.getTemperature();
        sysMagnetfeld = hallRead();
        u8x8.setCursor(8, 2);
        u8x8.print(analogRead(33));
        u8x8.print("V");
        u8x8.setCursor(8, 3);
        u8x8.print(analogRead(4));
        u8x8.print("V");
        u8x8.setCursor(8, 4);
        u8x8.print(rtcTempRaw);
        u8x8.print("'C");
        u8x8.setCursor(8, 5);
        u8x8.print("--/s");
        u8x8.setCursor(8, 6);
        u8x8.print(sysMagnetfeld);
        u8x8.print("mT");
      }


      break;

    case 70 : // Selbsttest Texte
      sysMenu = 71;
      break;

    case 71 : // Selbsttest
      break;

    case 80 : // Hauptmenü Texte
      sysMenu = 81;
      break;

    case 81 : // Haputmenü
      break;

    case 90 : // Messwerte Texte
      sysMenu = 91;
      break;

    case 91 : // Messwerte
      break;
  }

  // Ende Menü ----------------------------------------------------------------




  ticSec = false;   // Sekundentick löschen
}   // Loop ende ------------------------------------------------------------




// Fehlererkennung
byte ErrorLevel() {
  byte erl = 0;
  // Fehlerstufe 1 (leichter Fehler)
  if ((rtcErrorTemp) || (rtcErrorTime)) {
    erl = 1;
  }

  // Fehlerstufe 2 (mittelschwerer Fehler

  // Fehlerstude 3 (kritischer Fehler)
  if (rtcErrorOsc) {
    erl = 3;
  }

  return erl;
}


// RTC auslesen
void rtcRead() {
  clkMin = myRTC.getMinute();
  clkHour = myRTC.getHour(h12Flag, pmFlag);
  if (((clkMin == 0) && (clkHour == 0) && (clkSec == 0)) || (newDay)) {
    clkDay = myRTC.getDate();
    clkDow = myRTC.getDoW();
    clkMonth = myRTC.getMonth(centuryFlag);
    clkYear = myRTC.getYear();
    newDay = true;
  }
}


// Datum anzeigen (X, Y, Wochentag anzeigen)
void printDate (byte ptX, byte ptY, byte ptDoW) {             // Funktion Datum anzeigen
  if (newDay == true) {                                       // byte X, Y Position
    // Wochentag                                              // bool Wochentag anzeigen
    u8x8.setCursor(ptX, ptY);
    if (ptDoW == 1) {
      u8x8.print(DOWS[clkDow]);
      u8x8.print(" ");
    }
    // Datum
    if (clkDay < 10) {
      u8x8.print("0");
    }
    u8x8.print(clkDay);
    u8x8.print(".");

    // Monat
    if (clkMonth < 10) {
      u8x8.print("0");
    }
    u8x8.print(clkMonth);
    u8x8.print(".");

    // Jahr
    u8x8.print(clkYear);
    if (clkSec > 5) {
      newDay = false;
    }
  }
}


// Uhrzeit anzeigen (X, Y, Sekunde anzeigen, refresh)
void printTime (byte ptX, byte ptY, bool showsec, bool ref) {

  if (ref) {
    clkHourPrev = 99;
    clkMinPrev = 99;

  }

  // Stunde
  if (clkHour != clkHourPrev) {
    clkHourPrev = clkHour;
    printDT2(ptX, ptY, clkHour, '0');
    u8x8.print(":");
  }

  // Minute
  if (clkMin != clkMinPrev) {
    clkMinPrev = clkMin;
    printDT2(ptX + 3, ptY, clkMin, '0');
  }

  // Sekunde oder blinkender Doppelpunkt
  if (showsec) {
    u8x8.print(":");
    u8x8.setCursor(ptX + 6, ptY);
    if (clkSec < 10) {
      u8x8.print("0");
    }
    u8x8.print(clkSec);
  }
  else {
    u8x8.setCursor(ptX + 2, ptY);
    u8x8.print(":");
    if (clkSec % 2 > 0) {
      u8x8.setCursor(ptX + 2, ptY);
      u8x8.print(" ");
    }

  }
}

// Datenausgabe zweistellig (X, Y, Wert, Leerzeichen)
void printDT2(byte ptX, byte ptY, int value, char lz) {
  u8x8.setCursor(ptX, ptY);
  if (value < 10) {
    u8x8.print(lz);
  }
  u8x8.print(value);
}


// Cursorposition berechnen und Cursor zeichnen (Richtung : 1=nach unten, 2=nach oben)
void drawCursor(byte dir) {
  if (dir == 1) {   // runter
    cursorY ++;
    if (cursorY > menuLineMax) {
      cursorY = menuLineStart;
    }
  }
  if (dir == 2) {
    if (cursorY <= menuLineStart) {
      cursorY = menuLineMax + 1;
    }
    cursorY --;
  }
  u8x8.setCursor(0, cursorYalt);
  u8x8.print(" ");
  u8x8.setCursor(0, cursorY);
  u8x8.print(">");
  cursorYalt = cursorY;
}



//  u8x8.inverse();
//  u8x8.noInverse();
//  u8x8.setCursor(0,1);
//  u8x8.setFont(u8x8_font_chroma48medium8_r);
//  u8x8.print(" U8x8 Library ");   // Wie Arduino/C++ Print
//  u8x8.clear();
//  (https://github.com/olikraus/u8g2/)

// RGB-LED Ausgabe:
//      leds[0] = CRGB::Red;
//      FastLED.show();
//    leds[0] : BatterieLED
//              leer    : Red
//              halb    : Yellow
//              voll    : Green
//              laden   : Blue
//
//    leds[1] : Zustandsled
//              nicht bereit    : Yellow
//              Bewegung        : Green
//              Aktor bereit    : Blue
//              Bereit          : Turquoise (Bewegung und Aktor bereit) (LED an Starttaster ein)
//              Messung läuft   : Pink
//              Fehler          : Red
/* SECTION: Summary
 *  
 * Use PCNT module to count rising edges generated externally or internally by ESP32 LEDC module.
 *
 * Functionality of relevant GPIOs:
 *   - GPIO18 - output pin of internal 1 Hz pulse generator.
 *   - GPIO4 - pulse input pin,
 *   - GPIO5 - control input pin.
 *
 * Upload example, open the serial monitor to view the message printed on your screen.
 * You may need to unplug and replug the USB after uploading to view in the serial monitor
 *
 * To do this test, you should connect GPIO18 with GPIO4 or connect an external pulse generator to GPIO4.
 * GPIO5 is the control signal, you can leave it floating with internal pull up,
 * or connect it to ground. If left floating, the count value will be increasing.
 * If you connect GPIO5 to GND, the count value will be decreasing.
 *
 * An interrupt will be triggered when the counter value:
 *   - reaches 'thresh1' or 'thresh0' value,
 *   - reaches 'l_lim' value or 'h_lim' value,
 *   - will be reset to zero.
 */

/* SECTION: Pulse Counter Libraries & Definitions */
#include "driver/pcnt.h"

#define PCNT_TEST_UNIT_0    PCNT_UNIT_0
#define PCNT_TEST_UNIT_1    PCNT_UNIT_1
#define PCNT_H_LIM_VAL      32767         // Max count value
#define PCNT_L_LIM_VAL     -32767
#define PCNT_THRESH1_VAL    1             // Trigger an interrupt after this many counts
#define PCNT_THRESH0_VAL   -1
#define PCNT_INPUT_SIG_TI   16            // Pulse Input Time
#define PCNT_INPUT_SIG_SP   36            // Pulse Input Speed
#define PCNT_INPUT_CTRL_IO  17             // Control GPIO HIGH=count up, LOW=count down
// #define PCNT_RUN_DURATION   100  //  For how long do you want to count pulses?

typedef struct {      // Sample structure to pass events from PCNT interrupt handler to main program
    int unit;         // the PCNT unit that originated an interrupt
    uint32_t status;  // information on the event type that caused the interrupt
} pcnt_evt_t;

/* SECTION: pcnt_init function */
/* Initialize PCNT functions:
 *  - configure and initialize PCNT
 *  - set up the input filter
 *  - set up the counter events to watch
 */
static void pcnt_init_time(void)
{
    /* Prepare configuration for the PCNT unit */
    pcnt_config_t pcnt_config_0;
    // Set PCNT input signal and control GPIOs
    pcnt_config_0.pulse_gpio_num = PCNT_INPUT_SIG_TI;
//    pcnt_config_0.ctrl_gpio_num  = PCNT_INPUT_CTRL_IO;
    pcnt_config_0.channel        = PCNT_CHANNEL_0;
    pcnt_config_0.unit           = PCNT_TEST_UNIT_0;
    // What to do on the positive / negative edge of pulse input?
    pcnt_config_0.pos_mode       = PCNT_COUNT_INC;   // Count up on the positive edge
    pcnt_config_0.neg_mode       = PCNT_COUNT_DIS;   // Keep the counter value on the negative edge
    // What to do when control input is low or high?
    pcnt_config_0.lctrl_mode     = PCNT_MODE_REVERSE; // Reverse counting direction if low
    pcnt_config_0.hctrl_mode     = PCNT_MODE_KEEP;    // Keep the primary counter mode if high
    // Set the maximum and minimum limit values to watch
    pcnt_config_0.counter_h_lim  = PCNT_H_LIM_VAL;
    pcnt_config_0.counter_l_lim  = PCNT_L_LIM_VAL;

    /* Initialize PCNT unit */
    pcnt_unit_config(&pcnt_config_0);

    /* [Optional] Configure and enable the input filter (to filter glitches */
    //pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
    //pcnt_filter_enable(PCNT_TEST_UNIT);

    /* [Optional] Set threshold 0 and 1 values and enable events to watch */
    pcnt_set_event_value(PCNT_TEST_UNIT_0, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT_0, PCNT_EVT_THRES_1);
    pcnt_set_event_value(PCNT_TEST_UNIT_0, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT_0, PCNT_EVT_THRES_0);
    /* [Optional] Enable events on zero, maximum and minimum limit values */
    pcnt_event_enable(PCNT_TEST_UNIT_0, PCNT_EVT_ZERO);
    pcnt_event_enable(PCNT_TEST_UNIT_0, PCNT_EVT_H_LIM);
    pcnt_event_enable(PCNT_TEST_UNIT_0, PCNT_EVT_L_LIM);

    /* Initialize PCNT's counter */
    pcnt_counter_pause(PCNT_TEST_UNIT_0);
    pcnt_counter_clear(PCNT_TEST_UNIT_0);

    /* [Optional] Register ISR handler and enable interrupts for PCNT unit */
    //pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, &user_isr_handle);
    //pcnt_intr_enable(PCNT_TEST_UNIT);

    /* Everything is set up, now go to counting */
    pcnt_counter_resume(PCNT_TEST_UNIT_0);
}

static void pcnt_init_speed(void)
{
    /* Prepare configuration for the PCNT unit */
    pcnt_config_t pcnt_config_1;
    // Set PCNT input signal and control GPIOs
    pcnt_config_1.pulse_gpio_num = PCNT_INPUT_SIG_SP;
//    pcnt_config_1.ctrl_gpio_num  = PCNT_INPUT_CTRL_IO;
    pcnt_config_1.channel        = PCNT_CHANNEL_1;
    pcnt_config_1.unit           = PCNT_TEST_UNIT_1;
    // What to do on the positive / negative edge of pulse input?
    pcnt_config_1.pos_mode       = PCNT_COUNT_INC;   // Count up on the positive edge
    pcnt_config_1.neg_mode       = PCNT_COUNT_DIS;   // Keep the counter value on the negative edge
    // What to do when control input is low or high?
    pcnt_config_1.lctrl_mode     = PCNT_MODE_REVERSE; // Reverse counting direction if low
    pcnt_config_1.hctrl_mode     = PCNT_MODE_KEEP;    // Keep the primary counter mode if high
    // Set the maximum and minimum limit values to watch
    pcnt_config_1.counter_h_lim  = PCNT_H_LIM_VAL;
    pcnt_config_1.counter_l_lim  = PCNT_L_LIM_VAL;

    /* Initialize PCNT unit */
    pcnt_unit_config(&pcnt_config_1);

    /* [Optional] Configure and enable the input filter (to filter glitches */
    //pcnt_set_filter_value(PCNT_TEST_UNIT, 100);
    //pcnt_filter_enable(PCNT_TEST_UNIT);

    /* [Optional] Set threshold 0 and 1 values and enable events to watch */
    pcnt_set_event_value(PCNT_TEST_UNIT_1, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT_1, PCNT_EVT_THRES_1);
    pcnt_set_event_value(PCNT_TEST_UNIT_1, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL);
    pcnt_event_enable(PCNT_TEST_UNIT_1, PCNT_EVT_THRES_0);
    /* [Optional] Enable events on zero, maximum and minimum limit values */
    pcnt_event_enable(PCNT_TEST_UNIT_1, PCNT_EVT_ZERO);
    pcnt_event_enable(PCNT_TEST_UNIT_1, PCNT_EVT_H_LIM);
    pcnt_event_enable(PCNT_TEST_UNIT_1, PCNT_EVT_L_LIM);

    /* Initialize PCNT's counter */
    pcnt_counter_pause(PCNT_TEST_UNIT_1);
    pcnt_counter_clear(PCNT_TEST_UNIT_1);

    /* [Optional] Register ISR handler and enable interrupts for PCNT unit */
    //pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, &user_isr_handle);
    //pcnt_intr_enable(PCNT_TEST_UNIT);

    /* Everything is set up, now go to counting */
    pcnt_counter_resume(PCNT_TEST_UNIT_1);
}


static void pcnt_clear_time() {
          pcnt_counter_pause(PCNT_TEST_UNIT_0);
          pcnt_counter_clear(PCNT_TEST_UNIT_0);
}

static void pcnt_clear_speed() {
          pcnt_counter_pause(PCNT_TEST_UNIT_1);
          pcnt_counter_clear(PCNT_TEST_UNIT_1);
}

static int pcnt_get_time(int16_t* pcount) {
          int16_t count = pcnt_get_counter_value(PCNT_TEST_UNIT_0, pcount);
          return count;
}


static int pcnt_get_speed(int16_t* pcount) {
          int16_t count = pcnt_get_counter_value(PCNT_TEST_UNIT_1, pcount);
          return count;
}

Versorgt wird der ESP32 vom USB und als Peripherie hängt momentan nur ein Display, eine RTC, zwei WS2812 LED, ein Encoder und ein Taster mit LED an den I/Os. Und zwei Spannungsteiler, mit denen ich 5V und 12V messen will.
Der Slot für die SD-Karte ist zwar angeschlossen, aber die Karte ist raus.

Irgendwie bin ich hier gerade ziemlich ratlos.

Punkt 1:
Gilt für ESP8266/ESP32 (C3?)
26MHz crystal >>>> 74880bps
40MHz crystal >>>> 115200bps
Dann siehst du die Bootmeldungen!

Punkt 2:
Damit du die Seriellen Ausgaben auch sehen/lesen kannst, empfiehlt es sich Serial.begin() genauso zu setzen.

Punkt 3:
Den Seriellen Monitor natürlich auch so einstellen.

Ich hoffe, dass ich damit alle Klarheiten beseitigt habe.

Ich habe gerade beide Einstellungen ausprobiert und bekomme keine sinnvollen Zeichen. Bei 74880bps bekomme ich allerdings gelegentlich einige W zu sehen.

Aber von den wieder eingebauten Serial.print sehe ich nichts.

Da ich bei einem probehalber aufgespielten Programm aus den Beispielen (HallSensor), die richtigen Werte sehe und keine seltsamen Zeichen, kann es sein, daß der ESP irgendwie um Hilfe schreit, weil irgend etwas falsch läuft?

Siehst du die Boot Meldungen?

Welchen ESP32 hast du überhaupt?
Welches Board ausgewählt?
(kann sein, dass dir das alles egal ist, aber dann ....)

Nein, ich sehe Bootmeldungen, sondern eben nur die Kästchen und >

Der ESP ist der hier:

Ein NodeMCU 32S, welches auch im Boardverwalter ausgewählt ist.

Das ist total falsch, nehme ESP32 Dev Module. Die gezeigten sind stink normale ESP32 ohne S, C am Ende

Mit dieser Einstellung bekomme ich mit 115200bps die Bootmeldung, allerdings nur, wenn ich den ESP aus der Schaltung nehme. Da muss ich vermutlich noch mal genauer nachsehen, welche I/Os ich falsch beschaltet habe.

Aber selbst mit dem nackten ESP bekomme ich keine serielle Ausgabe zu sehen.

Das ist S2

Hier ist eine Liste was machen die GPIO, ESP32 hat schon eigene Eigenschaften. Ausgenomen ESP32 C3 das ist ganz andere MCU nämlich RISC V mit 1 Kern und die GPIO haben fast keine Beschränkung.

Nach genau dieser Seite habe ich die I/Os ausgewählt.

Das ist der ESP, den ich hier habe:

Bin jetzt noch mehr verwirrt, welchen ich hier vor mir habe und ich auswählen muss.
Anhand der Beschriftung auf der Unterseite gehe ich von einem ESP32 S aus

Das ist jetzt wirklich gut.
Nur wen Du saubere Boot Einträge mit meiner Einstellung hast bin komplett Verwirrt Moment, dann durfte der gar nicht hochladen mit der Einstellung ESP32 Dev Module.

Kann ich verstehen.

Über die FCC ID komme ich auf eine PDF-Datei, die enthält

At the core of the module is the ESP32-D0WD-V3 chip

Users-Manual-4684808.pdf (1,2 MB)

Ob das wohl stimmt?

Macht er anstandslos. Die Einzigen Meldungen die ich bekomme, sind Warnungen über deklarierte, aber nicht benutzte Variablen.

Aber ich habe jetzt zumindest herausbekommen, warum ich keine serielle Ausgabe bekomme. Ein klarer Hardwarefehler. Ich habe DC und Reset vom Display an TX0 und RX0 angeschlossen. Das erklärt auch die seltsamen Zeichen jede Sekunde, denn das Display wird jede Sekunde angesprochen, wenn die Uhrzeit aktualisiert wird (Doppelpunkt zwischen Stunde und Minute)
Das war ganz klar ein ziemlich dämlicher Fehler meinerseits.

Da stellt sich mir die Frage: Welcher COM-Port wird eigentlich an den USB weitergeleitet? Laut Pinout hier:

Gibt es einen UART0 und einen UART2. Daher bin ich davon ausgegangen, daß der nicht an den Pins vorhandene UART1 dafür zuständig ist, war aber wohl eine Fehlannahme.

So wie es aussieht, werde ich wohl erst mal ein paar neue Platinen bestellen und meine Pinbelegung überarbeiten müssen. Das wird dann wohl dieses Wochenende nichts mehr mit weiter programmieren. Denn ohne funktionierende Platinen kann ich zwar das Programm schreiben, aber nichts testen, ohne alles mit Jumperwires zu verdrahten. Und die helfen mir bei der externen Peripherie nicht, denn die ist über ein Rudel Optokoppler angeschlossen.

Ja.

Deine Hardware könnte mit dieser Pinbelegung (Quelle) übereinstimmen:

Dann findest Du RXD2/TXD2 an GPIO16/17, frei als Serial2 zu verwenden.
RXD1/TXD1 an GPIO9/10 wird vom Flash verwendet. Serial1 kann man nur nutzen, wenn man RXD1 und TXD1 auf andere Pins verlegt mittels Serial1.begin(Baudrate, Protocol, RXD1, TXD1);.
USB ist an RXD0/TXD0 an GPIO3/1 angeschlossen und als Serial zu verwenden.

Mein Pinout stimmt mit dem hier überein:


Sieht so ähnlich aus, aber einen UART1 hat mein ESP32 nicht, das habe ich probiert. Serial0.begin() funktionier und Serial2.begin(), aber bei Serial1.begin() bekomme ich beim Compilieren eine Fehlermeldung.
Ok, das kann auch damit zusammenhängen, daß ich den falschen ESP ausgewählt habe.

Wie hast Du das probiert?

Ich halte das für unwahrscheinlich, habe mal mit meinem ESP32 Dev Module probiert. Dazu habe ich Serial1 und Serial2 miteinander verbunden und dann von Serial2 nach Serial1 und wieder zurück die Zeit in ms geschickt:

Testprogramm
/* Verbindungen
   GPIO17 - GPIO35
   GPIO16 - GPIO32
*/
// Serielle Schnittstelle
#define RXD1 35
#define TXD1 32
#define Baudrate 9600
#define Protocol SERIAL_8N1

const uint32_t INTERVALL = 1000;
uint32_t vorhin, jetzt;

void setup()
{
  Serial.begin(115200);
  Serial1.begin(Baudrate, Protocol, RXD1, TXD1);
  Serial2.begin(Baudrate);
  delay(500);
  Serial.println(F("\r\nStart..."));
}
//
void  loop()
{
  jetzt = millis();
  if (Serial1.available())
  {
    byte inByte1 = Serial1.read();
    Serial1.write(inByte1);
  }
  if (Serial2.available())
  {
    byte inByte2 = Serial2.read();
    Serial.write(inByte2);
  }
  if (jetzt - vorhin >= INTERVALL )
  {
    vorhin = jetzt;
    Serial.printf( "Original: %lu\n", millis() );
    Serial2.printf( "    Echo: %lu\n", millis() );
  }
}
Ausgabe
09:20:51.249 -> Start...
09:20:51.249 -> Original: 1000
09:20:51.682 ->     Echo: 1000
09:20:52.666 -> Original: 2000
09:20:52.666 ->     Echo: 2000
09:20:53.669 -> Original: 3000
09:20:53.669 ->     Echo: 3000
09:20:54.682 -> Original: 4000
09:20:54.682 ->     Echo: 4000

Wie sieht das bei Dir aus?

Es ist zwar nicht das Problem, aber es scheint du behandelst deine Arrays eigenartig:

aus deinem Code:

    ar5V[ptarSpg] = analogRead(33);
    ar12V[ptarSpg] = analogRead(4);
    ptarSpg ++; // Zeiger auf Array erhöhen
    if (ptarSpg > 10) {
      ptarSpg = 1;
    }
    aix10_5V = 0;
    aix10_12V = 0;
    for (byte i = 1; i < 11; i++) {
      aix10_5V = aix10_5V + ar5V[i];
      aix10_12V = aix10_12V + ar12V[i];
    }

du hast Arrays mit 11 (!) Felder nutzt aber nur die Felder 1 - 10 also nur 10.
Das Feld 0 bleibt ungenutzt... finde ich sehr eigenartig. Ich würde 0-9 nutzen und das array auch nur mit 10 Felder anlegen.

Andere Arrays sind

byte lut11[8] = {11, 11, 11, 11, 11, 11, 11, 60};     // Lookuptable für Hauptmenü (11)
byte lut61[8] = {10, 10, 10, 10, 10, 10, 10, 10};     // Lookuptable für Status (61)

da greifst mit cursorY auf deren Inhalt zu.
du hast im Code ein

cursorY = menuLineMax + 1;

bei menuLineMax = 7;

wird also cursorY durchaus 8 was aber dann zu viel für deine Arrays ist.

Ich habe dein Testprogramm mal ausprobiert und als Ausgabe das bekommen:

Aber auch wenn ich in dem Testprogramm statt GPIO35/32 auf GPIO14/12 ändere und die Brücken entsprechend anpasse, komme ich auf das gleiche Ergebnis.
Lasse ich aber die Pindefinitionen weg und schließe die Brücken an UART1 wie im Pinout in Post#14, meldet der ESP nur jede Sekunde einen Reset vom Watchdog.
Aber mein Hauptproblem, nämlich daß die GPIO1 und 3 nicht für andere Dinge als UART0 nutzbar sind, ändert das leider auch nichts. Daher muss ich die Pinbelegung des ESP ändern und zwei Pins freischaufeln.

Ich wollte ursprünglich den Zeiger in Feld [0] speichern, habe mich dann aber anders entschieden, weil ich ja nur einen Zeiger benötige.
Nach meinen aktuellen Erkenntnissen ändere ich das aber sowieso, weil mir dadurch, daß ich die Pins von UART0 nicht für das Display nutzen kann, Pins fehlen und ich die Spannungsmessung und somit den gleitenden Mittelwert der 5V-Schiene weggelassen habe.

Das ist richtig, aber bereits 2 Zeilen später steht cursorY --;. Also kann cursorY irgend wo anders nie größer als 7 sein.
Ja, das hätte ich auch anders lösen können, indem ich cursorY = menuLineMax setze und danach ein else mit cursorY-- einsetze. So habe ich mir aber das else gespart.

  if (dir == 2) {
    if (cursorY <= menuLineStart) {
      cursorY = menuLineMax + 1;
    }
    cursorY --;
  }

Das ist gut so, denn die Standard-Pins für Serial1 kollidieren mit Flash. Das haben die Designer des Entwicklungsboards so festgelegt. Wichtig ist, zwischen dem ESP auf der kleinen Platine und dem Entwicklungsboard zu unterscheiden.

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