Hallo zusammen ich bin gerade ein wenig am verzweifeln... ich habe eine ESP32 BT-Modul über die UART an einen Atmega88 angeschlossen.... Ich möchte das BT-Modul als Gateway nutzen. das heisst das BT Modul soll Daten per bluetooth empfangen und weiter an den Atmega88 schicken... Ich kann aber leider NUR EIN ZEICHEN empfangen das heisst ich komme in die beiden IF Zweige (das sehe ich da ich die LED per BT ein und ausschalten kann) aber ich bekomme als response nicht die 0x55 zurück.... hat einer eine idee woran es liegen kann? ich bin seit längere Zeit aus dem aktiven coden raus und will mich wieder einarbeiten
Das ist ein Timing-Problem. Der ESP32 sendet receive_BT_Array[1] und receive_BT_Array[2] über UART:
1 | cppSerial.write(receive_BT_Array[1]); // 0x33 |
2 | Serial.write(receive_BT_Array[2]); |
Der ATmega empfängt das in fillReceiveBuffer():
1 | while ((UCSR0A & (1<<RXC0))) // ← Problem hier! |
2 | {
|
3 | receivebuffer[indexBuffer] = UART_Receive(); |
4 | indexBuffer++; |
5 | }
|
Die while-Bedingung (UCSR0A & (1<<RXC0)) prüft nur ob im Moment der Ausführung wenigstens ein Byte im Buffer liegt. Nach dem ersten Byte ist RXC0 dann kurz 0, bevor das zweite Byte ankommt – die Schleife bricht also zu früh ab. UART_Receive() wartet zwar intern mit while (!(UCSR0A & (1<<RXC0))), aber die äußere while-Schleife prüft das Flag bevor das nächste Byte ankam. Du musst Deinen Code umbauen, auf Timeoutgesteuerten Empfang. Oder besser gleich mit UART-Events. Bei UART ist es auch eine Protokollfrage, wann Du glaubst das eine Übertragung beendet ist.
:
Bearbeitet durch User
Tobias L. schrieb: > hat einer eine Idee, woran es liegen kann? An der falschen Dateiendung!? SCNR Dir ist schon klar, dass die serielle Schnittstelle wesentlich langsamer als der Prozessor ist, oder? Wenn da kein Zeichen in der Zwischenzeit eingegangen ist, wird die Schleife verlassen und du löscht den Puffer. Du solltest den Puffer entweder per Interrupt in der ISR füllen, oder in einer Schleife prüfen, ob ein neues Zeichen vorliegt (und es in den Puffer schreiben). Deine Statemachine habe ich mir nicht angeguckt. Du könntest natürlich auch eine Echo-Funktion zu Debugzwecken basteln, die das empfangene Zeichen über das Bluetooth-Modul (an dein BT-Terminal auf dem PC) zurücksendet.
Tobias L. schrieb: > ich habe eine ESP32 BT-Modul über die UART an einen Atmega88 > angeschlossen.... Den Atmega raus schmeißen und die Aufgaben des Atmega auch den ESP32 erledigen lassen.
Beitrag #8015843 wurde von einem Moderator gelöscht.
Beitrag #8015908 wurde von einem Moderator gelöscht.
Beitrag #8015909 wurde von einem Moderator gelöscht.
Beitrag #8015929 wurde von einem Moderator gelöscht.
Beitrag #8015961 wurde von einem Moderator gelöscht.
Beitrag #8016081 wurde von einem Moderator gelöscht.
Hey Tobias, ich würde an deiner Stelle den Code erstmal anpassen um ein "sauberes" Verhalten zu bekommen. Nutze den UART Interrupt: In diesem kopierst du lediglich das UDR in ein Empfangsbuffer und erhöhst den Index. Prüfung auf empfangenes Frame (Datenpaket): Die Prüfung führst du dann z.B. in deiner main() aus. Entweder wenn eine Mindestmenge an Daten empfangen wurde oder jedes mal wenn sich der Index erhöht hat, kommt immer dauf an was du machen möchtest. Natürlich könnte man jetzt auch noch einen Funktion hinzufügen, die z.B. alles löscht bis zu einem Startzeichen (0xAB) oder sowas. Grundsätzlich hast du damit den Empfang und die Verarbeitung getrennt und bist nicht mehr darauf angewiesen, immer auf den Empfang zu "hören/warten".
https://www.mikrocontroller.net/articles/Interrupt#UART_mit_Interrupts Das Prinzip geht so. Das Datenpaket vollständig empfangen, incl. Abschlußzeichen, meisten in einer ISR, siehe Interrupt. Geht aber im Zweifel auch ohne. Mittels Variable das Datenpaket signalisieren Eine andere Funktion / State machine wertet das Datenpaket aus Datenpaket als bearbeitet markieren Datenpaket löschen Neues Datenpaket empfangen
:
Bearbeitet durch User
Hi Die Lösung kann ein Ringpuffer sein. Dazu wird ein Speicherbereich definiert, je nach Bedarf so 5 bis 10 Telegrammlängen. Dazu brauchst du einen Schreibzeiger und einen Lesezeiger, die beim Start auf 0 gesetzt werden. Die eingehenden Daten erfasst du mit einem Interrupt und schreibst in der ISR das empfangene Byte auf die Startadresse + Schreibzeiger. Den Schreizeiger erhöhst du und prüfst die Grenze des reservierten Speicherbereiches. Hast du die Grenze erreicht, setzt du den Schreibzeiger wieder auf 0. In der Programmschleife fragst du ab ob Schreib- und Lesezeiger gleich sind. Wenn nicht, holst du dir das empfangene Byte aus dem Ringpuffer (Startadresse + Lesezeiger) in einen Arbeitsbereich und erhöhst den Lesezeiger. Es folgt die Grenzwertabfrage mit entsprechendem Rücksetzen. Anschießend wird der Inhalt des Arbeitsbereiches auf ein vollständiges Telegramm geprüft und dieses dann verarbeitet. Ein Telegramm kann zusätzlich zu den Nutzdaten einen Kopf (z.B "STRT") und eine Endekennung bekommen (z.. "ok") Auch die Nutzdatenläge kann hinter der Startkennung stehen. Inder Regel holst du dir so bei jedem Programmdurchlauf ein Byte. Das bedeutet aber auch, das du bei einer Gesamtlänge eines Telegrammes von bspw. 20 Byte 20 Programmdurchläufe brauchst, bevor du die Daten vollständig verwerten kannst Das sollte aber in Anbetracht einer relativ langsamen seriellen Übertragung kein Problem bereiten. Na dann, viel Erfolg Gruß oldmax
Martin V. schrieb: > Hi > Die Lösung kann ein Ringpuffer sein. Kann. Ist hier aber für den Anfang nicht sinnvoll und auch nicht nötig, es erhöht nur die Komplexität. Ein einfacher Puffer reicht erstmal.
Beitrag #8018766 wurde vom Autor gelöscht.
Hi Falk B. schrieb: > Kann. Ist hier aber für den Anfang nicht sinnvoll und auch nicht nötig, > es erhöht nur die Komplexität. Ein einfacher Puffer reicht erstmal. Ich halte einen Ringpuffer schon für sinnvoll. Wir wissen ja nicht, wann die Daten eintrudeln, wann und wie schnell eine Übertragung stattfindet und ob immer vollständige Datensätze ohne Fehler übertragen werden. Das allein fängt auch ein Ringpuffer nicht ab, aber in Zusammenspiel mit ein bisschen Protokoll im Telegramm (z.B. Start und Länge) lassen sich Fehler erkennen. Geht natürlich auch mit einem einfachen Puffer. Ist ein Ringpuffer erst einmal verstanden, ist er auch für andere Aufgaben nutzbar. Und so kompliziert und komplex ist er nun auch wieder nicht. Aber was auch immer, im Ergebnis zählt ein sicher funktionierendes Programm. Gruß oldmax
Martin V. schrieb: > Ich halte einen Ringpuffer schon für sinnvoll. Bei jeder Anwendung? > Wir wissen ja nicht, wann > die Daten eintrudeln, wann und wie schnell eine Übertragung stattfindet > und ob immer vollständige Datensätze ohne Fehler übertragen werden. > Das allein fängt auch ein Ringpuffer nicht ab, > aber in Zusammenspiel mit ein > bisschen Protokoll im Telegramm (z.B. Start und Länge) lassen sich > Fehler erkennen. Ein Protokoll mit einer Checksumme kann beliebig lang sein. Mein Lieblingsbesipiel dafür ist NMEA0183. > Geht natürlich auch mit einem einfachen Puffer. Gut erkannt. Wenn das Telegrammende erkannt und das Telegram geparsed wurde, setzt mal den Schreibpointer einfach wieder auf 0. > Ist ein Ringpuffer erst einmal verstanden Deswegen schrieb Falk ja auch "für den Anfang".
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.