Serielle Schnittstelle blockiert ein Projekt - HILFE!

Guten Morgen and die Fachleute und die die es werden wollen,

ich habe hier ein Problem, wo ich nicht weiterkomme und den Wald vor lauter Bäumen nicht mehr sehe. Die Möglichkeiten sind aber vielleicht auch zu vielfältig. Ich möchte 20 Int16_t-Variablen (2 Bytes bei beiden Controllern) über eine serielle Schnittstelle zwischen einen Tennsy4.1 und einem ESP8266Wifi von Joy-it senden. Da beide mit 3,3 Volt arbeiten spare ich mir den Levelshifter. Der Code enthält ein Startbit und Endbit und sollte später auch ein Prüfbyte oder Bit enthalten. Später deswegen, weil ich erstmal das eine ans laufen bekommen will.
Der Plan war ansich, dass der ESP8266Wifi Bereit-Signal (z.b. „ S „) sendet. Sobald der Tennsy es empfängt, sendet er das Startbit + 10 Variablen + (Checkbyte) + Endbit. Wenn der ESP8266Wifi alles empfangen hat, prüft er Startbit und Endbit und ob es 20 Bytes sind (bildet die Chechsum und vergleicht diese mit dem Prüfbyte / Fehlt, um Fehlerquellen zu minimieren), wenn alles richtig ist, sendet er ein Empfangensignal (z.B. „E“) und die serielle Schnittstelle bleibt online und wartet wieder auf ein „S“ vom ESP8266Wifi. Wenn das Prüfbyte falsch ist soll er nochmals ein Startsignal senden. Wenn alle glatt gelaufen ist, soll er die int16-Bytes wieder zusammenfügen (und über Wifi in eine SQL-Datenbank geschrieben. Den Teil habe ich schon)
Ich habe nun viele Ansätze die ich hier nicht alle Posten kann. Ich nehme meinen letzen Entwurf da dieser immer läuft. Die anderen haben meist nur einmal übertragen und danach nicht mehr. Für diese Problem habe ich auch Beiträge gefunden aber die konnten mir auch nicht wiete helfen. Leider ist der Fragende meist dann auch ausgestiegen und hat halt nicht seine Lösung präsentiert….falls er eine hatte.
Der jetzige Ansatz ist nur umgedreht, da ich beim Teensy mehrere serielle Schnittstellen habe und direkt gucken konnte, ob es funktioniert. Außerdem schloss ich WLAN und SQL-Probleme aus. Auch das Prüfbyte und das Bereit-Signal sowie das End-Signal ist erstmal raus. Leider „baut“ der Code aber die Int16-Variablen nicht wieder so Zusammen wie es sein sollte.

ESP-Sender-Code

#include <Arduino.h>

const int numValues = 15;
int16_t values[numValues] = {2000, 199, 99, 50, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};

void setup() {
    Serial.begin(9600); // Initialisiere die serielle Kommunikation
}

void loop() {
    // Sende Startbit
    Serial.write(0xAA); // Beispiel für ein Startbit

    // Sende die Werte
    for (int i = 0; i < numValues; i++) {
        Serial.write((uint8_t*)&values[i], sizeof(int16_t));
    }

    // Sende Endbit
    Serial.write(0x55); // Beispiel für ein Endbit

    delay(1000); // Warte eine Sekunde vor dem nächsten Senden
}

TEENSY-Empfänger-Code

#include <Arduino.h>

const int numValues = 15;
int16_t receivedValues[numValues];
bool receiving = false;
int iindex = 0;

void setup() {
    Serial.begin(115200); // Debugging über USB
    Serial8.begin(9600); // Initialisiere die serielle Kommunikation auf Serial2
}

void loop() {
    while (Serial8.available()) {
        uint8_t byteReceived = Serial8.read();

        if (!receiving) {
            if (byteReceived == 0xAA) { // Startbit erkannt
                receiving = true;
                iindex = 0; // Setze den Index zurück
            }
        } else {
            if (iindex < numValues) {
                ((uint8_t*)receivedValues)[iindex * sizeof(int16_t)] = byteReceived; // Speichere das Byte in der richtigen Position

                if (++iindex == numValues) { 
                    receiving = false; // Alle Werte empfangen
                    Serial.println("Werte empfangen:");
                    for (int i = 0; i < numValues; i++) {
                        Serial.print(receivedValues[i]);
                        Serial.print(" ");
                    }
                    Serial.println();
                }
            } else if (byteReceived == 0x55) { // Endbit erkannt
                receiving = false; // Empfang beenden
            }

Da ich rausgefunden habe, dass ein Int nicht gleich Int ist, nutze ich Int16 damit für beide Prozessoren klar sein sollte, dass die Variable 2 Bytes hat. Kann es sein, dass dort das Problem liegt?

Der Code wurde auch schon mit einem Arduino UNO mit Levelshifter und Tennsy oder ESP8266Wifi ausprobiert. Gleiches Problem.

Den Teensy will ich nutze, weil dieser schon in einem Lautstärkemessungsprojekt draußen hängt und meist „Langeweile“ hat und dann kann er gerne noch als Wetterstation ausgebaut werden. Die Arduino IDE unterstützt auch den Tennsy und der Code sollte der gleiche sein, wenigstens habe ich darüber keine im Internet gefunden. Auch hier gerne ein Hinweis falls, doch vielleicht ist das ja der Fehler.

Ich verwende den ESP8266Wifi von Joyit, weil er kleiner ist und somit noch Platz hat in der Box. Des Weiteren steht die Verbindung zum Wifi und zur SQL-Datenbank stabil. Somit fehlt nur die Implementierung der seriellen Schnittstelle. Und in dem Code macht er es ja. Es ist halt nur die Umwandlung.

Ich habe viele Leerzeilen und -zeichen drin, damit ich besser erkenne, ob etwas fehlt. Ich denke mir schon öfters, was dazu was dann da aber nicht steht, daher mache ich das. Falls das zu Programmproblemen führt, bitte ich um einen Hinweis. Meines Wissens ist das nur „unsauber“.

Da der Fragende nicht immer wissen kann, wo der Fehler liegt und somit ggf. Infos fehlen, bitte ich euch direkt zu fragen und ggf. zu akzeptieren, dass ich nicht genau weiß wovon Ihr sprecht und somit für euch missverständliche Rückantworten kommen.

Danke erstmal. :hugs:

DAVID



const int numValues = 15;
int16_t values[numValues] = {1024, 255, -88, 50, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};

void setup() {
  Serial.begin(9600); // Initialisiere die serielle Kommunikation
}

void loop() {
  // Sende Startbit
  Serial.write(0xAA); // Beispiel für ein Startbit

  // Sende die Werte
  for (int i = 0; i < numValues; i++) {
    Serial.write(values[i] >> 8);
    Serial.write(values[i] & 0xFF);
  }

  // Sende Endbit
  Serial.write(0x55); // Beispiel für ein Endbit

  delay(1000); // Warte eine Sekunde vor dem nächsten Senden
}
const int numValues = 15;
int16_t receivedValues[numValues];
bool receiving = false;
int iindex = 0;

void setup() {
  Serial.begin(115200); // Debugging über USB
  Serial8.begin(9600); // Initialisiere die serielle Kommunikation auf Serial2
}

void loop() {
  while (Serial8.available()) {
    uint8_t byteReceived = Serial8.read();

    if (!receiving) {
      if (byteReceived == 0xAA) { // Startbit erkannt
        receiving = true;
        iindex = 0; // Setze den Index zurück
      }
    } else {
      if (iindex < numValues) {
        receivedValues[iindex] = byteReceived; // Speichere das Byte in der richtigen Position
        while (!Serial8.available());
        receivedValues[iindex] = receivedValues[iindex] << 8 | Serial8.read();
        if (++iindex == numValues) {
          receiving = false; // Alle Werte empfangen
          Serial.println("Werte empfangen:");
          for (int i = 0; i < numValues; i++) {
            Serial.print(receivedValues[i]);
            Serial.print(" ");
          }
          Serial.println();
        }
      } else if (byteReceived == 0x55) { // Endbit erkannt
        receiving = false; // Empfang beenden
      }
    }
  }
}

So richtig werde ich aus deiner Beschreibung nicht schlau. Einfach zu viel Prosa.

Beschreibe doch mal wo es genau hängt, also wo dein Problem auftritt.

Wenn dein TEENSY das empfangene nicht richtig zusammen setzt, liegt es evtl. am TEENSY-Sketch.

Kannst du das Problem in < 50 Wörtern zusammenfassen?

Ich habe mir auch mal deine Prosa und deinen Code angeschaut.

Ganz sicher keine Bit, sondern doch eher Byte!
Oder?

Die Übertragung zwischen unterschiedlichen Systeme, hier µC, ist immer mit Sorgen verbunden. Per Zufall mag da mal was klappen/passen. Aber die Regel ist das nicht.

  1. Little Endian vs. Big Endian
  2. Padding
  3. Allignment
  4. Zweier- vs, Einerkomplement
  5. Variablengröße
  6. Pegel

Zudem ist das entwerfen eines Protokolls, mit den zugehörigen Generatoren und Parsern, wahrlich kein Pappenstiel, für einen Ungeübten.
Drum gibt es auch schon einige vorgekaute/bewährte Verfahren für die Maschine zu Maschine Kommunikation,
Einige basieren auf Textueller Basis, um eben viele der eben genannten Stolperfallen zu umgehen, und so einen mitlesbaren, damit leicht überprüfbaren, Datentransport ermöglichen.
z.B. XML und JSON

Manche können binär und Text, z.B. der CMDMessenger.

Natürlich möchte ich dich nicht davon abhalten dein eigens Süppchen zu kochen.
Aber bisher sehe ich noch nicht was du falsch machst.
bzw. ist mir das zu wirr verschachtelt.

Mein erster Rat:
Entschachteln, geradliniger bauen.

1 Like

Ich habe jetzt nicht alles angeschaut, aber das kann definitv nicht funktonieren. Kannst Du erklären, was Du dir dabei geacht hast?
Mit dem iindex * sizeof(int16_t) überspringst Du im Array immer ein byte. Wenn Du die Bytes ( mittels des cast ) einzeln ansprechen willst, muss der Index weiterhin immer um 1 erhöht werden, aber das Array ist jetzt - in Byte gezählt - doppelt so lang, also der Maxwert von iindex erhöht sich entsprechen.
Eine 'geradlinigere' Lösung könnte sein, immer 2 Bytes zu empfangen, die zu einem Int16_t zusammenzusetzen, und erst dann im Array zu speichern.
Oder gleich ein ASCII-basiertes Protokoll verwenden. Da ist auch das Debugging leichter :wink:

Guten Tag alle,

ich danke euch alle für die Antworten und danke kolaha das du mir direkt einen funktionierenden Code gesandt hast, denn ich war echt dem Abbruch des Weiterforschens nahe. Ich sehe auch meinen Fehler...
Jeder hier hatte einen anderen Lösungsansatz was einen Anfänger verzweifeln läßt, weil ich hier nicht nur den Code hatte, aber immer wieder gescheitert bin. Daher Danke an alle die sich die Zeit genommen haben.

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