Nabend zusammen,
da ich nun schon den ein oder anderen Abend leider erfolglos damit verbracht habe meine serielle Kommunikation zwischen einem ESP8266 und einem Mega für mich nutzbar herzustellen hoffe ich hier auf Hilfe. Ich habe zwar schon einiges an kleineren Projekten mit Arduinos bewerkstelligt, aber mich dabei immer mit einem begnügen können...
Die Kommunikation zwischen den beiden erfolgt via RX/TX <-> TX1/RX1. Wenn ich Daten auf dem ESP sende, empfange ich auch etwas auf dem Mega. Somit steht die grundsätzliche Verbindung schonmal.
Zum Problem:
Ich möchte vom ESP folgendes senden:
if (deviceId == "5axxxxxxxxxxxxxxxxxxx") // Device ID
{
Serial.print("Turn on device ID: ");
Serial.println(deviceId);
und am Mega am liebsten das 5axxxxxxxxxxxxxxxxxxx wieder erhalten.
Leider bekomme ich aber nur eine Liste wieder zurück:
I received: 91
I received: 87
I received: 83
I received: 99
I received: 93
I received: 32
I received: 103
I received: 101
und so weiter...
der Code zum Abfragen auf dem Mega lautet wie im Beispiel:
int incomingByte; // for incoming serial data
void setup() {
Serial.begin(115200); // opens serial port, sets data rate to 9600 bps
Serial1.begin(115200); // opens serial port, sets data rate to 9600 bps
}
void loop() {
// send data only when you receive data:
if (Serial1.available() > 0) {
// read the incoming byte:
incomingByte = Serial1.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte);
}
}
Gib es eine möglichkeit wie ich die deviceId als Klartext zurückerhalten kann, damit ich den wert dann wieder weiterverarbeiten kann?
Quasi:
incoming ist ein INT (Byte würde hier reichen) - Das wird Dir als Zahl ausgegeben.
Du kannst das auch als Zeichen schreiben lassen mit .write(incoming);
Hier gibt es KEIN writeln - Du musst also selber einen Zeilenumbruch danach senden.
Bei Zeichen <0x21 (Steuerzeichen bzw. Space) würde ich ein Leer ausgeben, oder statt des Zeichen den Wert in HEX.
Das geht via .println(incoming,HEX);
Wenn das ,HEX zu ,DEC gemacht wird, gibt's wieder Zahlen in 10er Potenzen (also Unsere) - ,BIN macht daraus Binär (0 und 1).
Führende Nullen werden NICHT ausgegeben - gerade bei HEX und BIN sind Die aber durchaus interessant - muß man händisch machen.
Die Zahlen sind die ASCII Codes der Zeichen. Da kommen schon die Buchstaben an. Das ist nur eine Ausgabe-, bzw. Formattierungssache.
Generell schließt man Übertragungen mit einem CR oder LF ab. Dann liest man auf der Empfangsseite alle Zeichen bis zum Endzeichen in ein char Array ein und terminiert dieses danach (mit NULL). Dann hat man einen C String den man verarbeiten kann
Mache Dich mal über Zeichenketten in C schlau. Da ist auch ein Beispiel für das serielle Einlesen drin.
Vergiss auch die Pegelwandler nicht und nach meiner Meinung gibt es zu Serial1 (zumindest beim NodeMCU keinen RX1-Anschluß)
HotSystems:
Du bekommst da ein Problem mit der Spannung.
Dies ist mir durchaus bewusst. Um die unterschiedichen Spannungen zu erhalten, gibt es ja entsprechende Adapter. Aber danke für den Hinweis.
postmaster-ino:
Hi
incoming ist ein INT (Byte würde hier reichen) - Das wird Dir als Zahl ausgegeben.
Du kannst das auch als Zeichen schreiben lassen mit .write(incoming);
Hier gibt es KEIN writeln - Du musst also selber einen Zeilenumbruch danach senden.
Bei Zeichen Space) würde ich ein Leer ausgeben, oder statt des Zeichen den Wert in HEX.
Das geht via .println(incoming,HEX);
Wenn das ,HEX zu ,DEC gemacht wird, gibt's wieder Zahlen in 10er Potenzen (also Unsere) - ,BIN macht daraus Binär (0 und 1).
Führende Nullen werden NICHT ausgegeben - gerade bei HEX und BIN sind Die aber durchaus interessant - muß man händisch machen.
MfG
Vielen Dank dafür. Nun kann ich zumindest schonmal auf dem Mega lesen was am ESP ausgegeben wird aber blöd gefragt. Wie bekomme ich jetzt davon einen teil in etwas was ich weiter verarbeiten kann? So:?
char message[] = Serial.write(incomingByte);
wie Serenifly meinte?
Tommy56:
Mache Dich mal über Zeichenketten in C schlau. Da ist auch ein Beispiel für das serielle Einlesen drin.
Vergiss auch die Pegelwandler nicht und nach meiner Meinung gibt es zu Serial1 (zumindest beim NodeMCU keinen RX1-Anschluß)
Gruß Tommy
Werde ich auf jeden fall machen. Schön geschrieben.
Wenn ich das richtig verstanden habe: Sobald in dem Text eine 0 auftaucht, ist der Text für einen C String beendet?
Der RX1 ist vonseiten des Mega.
Ich glaube für heute ist meine Bastler Geduld aufgebraucht Morgen gehts dann mit all euren Tipps wieder frisch ans Werk.
Fexel:
.....
Dies ist mir durchaus bewusst. Um die unterschiedichen Spannungen zu erhalten, gibt es ja entsprechende Adapter. Aber danke für den Hinweis.
.....
Adapter nicht, aber Levelshifter.
Und das ging nicht aus deiner Beschreibung hervor.
Fexel:
Wenn ich das richtig verstanden habe: Sobald in dem Text eine 0 auftaucht, ist der Text für einen C String beendet?
Hm, Auslegungsfrage.
Wenn in der Zeichenkette eine Binäre 0 (='\0') auftaucht, wird das als Ende gewertet.
Wenn im übertragenen Text das Endezeichen (z.B. '\n' = Newline von println) auftaucht, musst Du eine '\0' (binäre 0, nicht Zeichen '0') eintragen, damit die Zeichenkette ordentlich abgeschlossen ist und von anderen Funktionen bearbeitet werden kann (damit die wissen, wo das Ende ist).
Das ist totaler Unsinn. Mit einer einzigen Anweisung geht das sowieso nicht
Wenn ich das richtig verstanden habe: Sobald in dem Text eine 0 auftaucht, ist der Text für einen C String beendet?
Hier musst du die Übertragung von der Darstellung im Speicher unterscheiden. Im Speicher steht ein NULL und String Funktionen brechen an der Stelle ab. Deshalb wird der Terminator selbst nicht übertragen. Statt dessen verwenden man i.d.R. ein Linefeed. Oder auch CR + LF (was bei println() automatisch übertragen wird) und fragt nur auf das LF ab
Serenifly:
Das ist totaler Unsinn. Mit einer einzigen Anweisung geht das sowieso nicht
Dann sei doch bitte so lieb und kläre mich auf, wie ich es richtig machen kann? Oder zumindest wo ich verständlich finde, wie ich es selbst erarbeiten kann. Danke.
@Tommy56 okay. Ich glaube, so langsam verstehe ich zumindest den ersten teil deiner Beschreibung. Wobei ich das glaube aktuell nicht benutzen kann für meinen Anwendungsfall?
Hiermit bekomme ich nun am Mega angezeigt was ich an dem ESP los sende.
byte incomingByte = 0; // for incoming serial data
void setup() {
Serial.begin(115200); // opens serial port, sets data rate to 9600 bps
Serial1.begin(115200); // opens serial port, sets data rate to 9600 bps
pinMode(2, OUTPUT);
}
void loop() {
// send data only when you receive data:
if (Serial1.available() > 0) {
// read the incoming byte:
incomingByte = Serial1.read();
Serial.write(incomingByte);
}
}
Mir erschließt sich aktuell leider nur nicht, wie ich das was jetzt raus kommt:
on
5b3253a0fb217v73f639e422
bzw.
off
5b3253a0fb217v73f639e422
abspeichere um es, dann entsprechend via if Funktion vergleichen zu können um den Ausgang HIGH oder LOW zu setzen.
Dabei ist erst Mal gar nicht klar, wie 'lang' jede der HEX-Zahlen ist.
Würde somit die Zahlen auf zwei Stellen bringen (wenn <0x10, dann eine "0" zuvor ausgeben).
Ggf. zwischen den Einzelzahlen noch ein Space, damit die Bytes lesbarer werden.
Davon ab - warum bekommst Du kleine Buchstaben zu übermittelten HEX-Zahlen?
Dabei ist erst Mal gar nicht klar, wie 'lang' jede der HEX-Zahlen ist.
Würde somit die Zahlen auf zwei Stellen bringen (wenn <0x10, dann eine "0" zuvor ausgeben).
Ggf. zwischen den Einzelzahlen noch ein Space, damit die Bytes lesbarer werden.
Davon ab - warum bekommst Du kleine Buchstaben zu übermittelten HEX-Zahlen?
MfG
Okay ich sollte das Projekt, glaube ich, zurückstellen und mir doch nochmal deutlich mehr anlesen.
Ich bekomme kleine Buchstaben da ich die am ESP auch sende.
Moment. Wenn ich dem ESP jetzt sage er sendet mir anstelle von der langen Zeichenfolge nur Nummern.
Ich sollte nicht mehr wie 18 unterschiedliche Nummern benötigen (um 9x on und 9x off befehle zu Senden) -
const int SERIAL_BUFFER_SIZE = 31;
char serialBuffer[SERIAL_BUFFER_SIZE];
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (readSerial(Serial)) //liefert true wenn das LF eingelesen wurde
{
Serial.print("Empfangen: "); Serial.println(serialBuffer);
if(strcmp(serialBuffer, "123") == 0) //mit "123" vergleichen
Serial.println("Korrekt");
else
Serial.println("Falsch");
Serial.println();
}
}
bool readSerial(Stream& stream)
{
static byte index;
while (stream.available())
{
char c = stream.read();
if (c == '\n' && index > 0) //wenn LF eingelesen und String länger als 0 ist
{
serialBuffer[index] = '\0'; //String terminieren
index = 0;
return true; //melden dass String fertig eingelesen wurde
}
else if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1) //solange noch Platz im Puffer ist
{
serialBuffer[index++] = c; //Zeichen abspeichern und Index inkrementieren
}
}
return false; //noch nicht fertig
}
Stelle den seriellen Monitor dabei so ein, dass ein Linefeed/Newline am Ende gesendet wird!
Und nicht von dem while verwirren lassen. Die serielle Übertragung ist so langsam dass i.d.R. pro Aufruf nur ein Zeichen eingelesen wird. Deshalb muss man die Funktion ständig aufrufen
while (stream.available())
{
char c = stream.read();
if (c == '\n' && index > 0) //wenn LF eingelesen und String länger als 0 ist
{
serialBuffer[index] = '\0'; //String terminieren
index = 0;
return true; //melden dass String fertig eingelesen wurde
}
else if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1) //solange noch Platz im Puffer ist
{
serialBuffer[index++] = c; //Zeichen abspeichern und Index inkrementieren
}
}
return false; //noch nicht fertig
}
Stelle den seriellen Monitor dabei so ein, dass ein Linefeed/Newline am Ende gesendet wird!
Und nicht von dem while verwirren lassen. Die serielle Übertragung ist so langsam dass i.d.R. pro Aufruf nur ein Zeichen eingelesen wird. Deshalb muss man die Funktion ständig aufrufen
Danke danke danke <3
Hiermit bekomme ich genau das, was ich benötige hin.
Ja das die Übertragung Zeichen für Zeichen passiert hatte ich auch schon festgestellt. Aber hier kommt es auch nicht auf Geschwindigkeit an.
Da der teil jetzt schonmal funktioniert gehts ans Verstehen was da passiert. Aber da komme ich jetzt auch noch Stück für Stück hinter.
Fexel:
Moment. Wenn ich dem ESP jetzt sage er sendet mir anstelle von der langen Zeichenfolge nur Nummern.
Ich sollte nicht mehr wie 18 unterschiedliche Nummern benötigen (um 9x on und 9x off befehle zu Senden) -
Wäre dieses leichter zu verarbeiten?
Das dürfte unerheblich sein. Aber es macht schon einen Zeitunterschied, wie viele Daten Du überträgst. Auch ist es ein konzeptioneller Unterschied, wo die Konkordanz deviceId zu Aktion ausgewertet wird. Auch stellt sich mir die Frage, ob der ESP8266 den Mega nicht gänzlich ersetzen könnte.
Ob diese Überlegungen relevant sein könnten, kann ich mangels Kenntmis Deines Projektes aber nicht einschätzen.
agmue:
Das dürfte unerheblich sein. Aber es macht schon einen Zeitunterschied, wie viele Daten Du überträgst. Auch ist es ein konzeptioneller Unterschied, wo die Konkordanz deviceId zu Aktion ausgewertet wird. Auch stellt sich mir die Frage, ob der ESP8266 den Mega nicht gänzlich ersetzen könnte.
Ob diese Überlegungen relevant sein könnten, kann ich mangels Kenntmis Deines Projektes aber nicht einschätzen.
Zeitlich ist es hier tatsächlich absolut unkritisch. Es gibt weder Sachen die "von Außen" über Eingänge eingehen (zumindest zur aktuellen Vorstellung) noch kommt es auf Sekunden an.
Der ESP kommt in das Projekt eigentlich nur wegen der Netzwerkanbindung (Amazon Alexa Anbindung). Leider reichen mir hier aber insgesamt die Ausgänge nicht. Deswegen dann auch der Mega.
Dieser steuert dann alles weitere an. Über Relais pumpen und Ventile, Beleuchtungen in vielen verschieden arten und und und.
In dem Sinne hatte ich das gar nicht gemeint. Sondern um den Code zu verstehen. Gerade Anfänger unterschätzen wie langsam die serielle Schnittstelle ist. Da wird dann oft versucht tatsächlich alles sofort in einer while-Schleife einzulesen. Das kann nicht funktionieren. Manchmal wird versucht eine Antwort abzufragen noch bevor die Anfrage versendet wurde. Unter anderem deshalb verwendet man ein Endzeichen.
Fexel:
Leider reichen mir hier aber insgesamt die Ausgänge nicht.
Wenn Du mit dem, wie es ist, glücklich bist, dann weiter so. Sonst wären Portexpander über I2C (MCP23017 mit Bibliothek) eine Alternative. Wollte es nur erwähnt haben.