Hallo liebe Leute,
ich muss schon wieder euer Wissen in Anspruch nehmen :-/
Es geht um folgendes:
ein uC misst alle 500us einen Wert. Dieser wird noch einigen
Berechnungen unterworfen und dann per UART in einem größeren Block (500
Bytes) verschickt.
Die Daten werden dauerhaft gesendet, sobald der Befehl dazu gegeben
wurde. Einfach deswegen, weil ich sonst dauerhaft die Daten anfordern
müsste und ich eventuell Datenblöcke verlieren könnte.
Alle Befehle werden durch den uC bestätigt um eventuelle Fehler
auszuschließen. Bisher wurde das über die selbe Schnittstelle gemacht,
die auch die Datensätze verschickt. Auf dem PC, der den uC ansteuert
läuft matlab, die Kommunikation sieht in etwa so aus:
1
s = serial('/dev/ttyUSB1','BaudRate',115200,'DataBits',8,'StopBits',1,'TimeOut',2,'InputBufferSize',4096);
2
fopen(s);
3
fwrite(s,Befehl);
4
answer = fread(s,16);
5
fclose(s)
Ich denke das Prinzip wird klar - Ich schicke den Befehl und empfange
danach direkt, um die Antwort zu erhalten.
Dieses Prinzip funktioniert aber nicht mehr, wenn ich die Datenblöcke
"parallel" verschicke. Zwar wird in einer ISR der Rx Buffer gefüllt und
eine Flag gesetzt, die ausgelesen wird, bevor die Datensätze geschickt
werden (beides in der main), aber da der Zeitpunkt, an dem ein neuer
Befehl gesendet wird, nicht konstant ist kann ich z.B. den unglücklichen
Moment treffen, dass gerade Daten geschickt werden (gar nicht so
unwahrscheinlich..). Damit "rupfe" ich also 16 Byte aus meinen
eigentlichen Daten heraus, obwohl ich nur die Antwort auf meinen Befehl
checken möchte.
Wie kann ich dieses Problem beheben, wie kann ich sicher sein, dass die
eingehenden 16 Bytes die Antwort ist? Kann ich vermutlich gar nicht.
Welche anderen Möglichkeiten gibt es hier, außer einer zweiten UART?
Ps, sowohl die Datenblöcke, als auch die Befehle sind in einem Frame
(inkl Checksum) eingebettet. Aber einen großen Puffer zu nehmen, alle zu
empfangenen Daten da reinzuschreiben und hinterher (möglichst schnell,
also möglichst "Echtzeit") zu filtern ist recht mühselig.
Habt ihr andere Ideen?
Vielen lieben Dank :)
Jan K. schrieb:> Welche anderen Möglichkeiten gibt es hier, außer einer zweiten UART?
Ein Datenprotokoll, beim dem die Blöcke nach ihrem Typ (Daten, Quittung)
gekennzeichnet sind. Eine Quittung muß warten, bis ein Datenblock
beendet ist - mach die Datenblöcke also nicht zu lang.
>wenn ich die Datenblöcke "parallel" verschicke
Unglücklich ausgedrückt. Du meinst, daß die Befehlsübermittlung in die
Datenübermittlung reintrifft?
Du brauchst, wie oben schon angedeutet, ein kleines Protokoll, daß für
den empfangenden PC unterscheidbar macht, was gerade gesendet wird, wann
ein gesendeter Datensatz oder eine gesendete Befehlsresponse beginnen
und zu Ende sind.
Überleg Dir einfach wie eine menschliche Kommunikation ablaufen könnte,
das hilft.
Danke für eure Antworten!
Der Reihe nach:
Michael A. schrieb:> Ein Datenprotokoll, beim dem die Blöcke nach ihrem Typ (Daten, Quittung)> gekennzeichnet sind. Eine Quittung muß warten, bis ein Datenblock> beendet ist - mach die Datenblöcke also nicht zu lang.
Ich kann ja die Blöcke unterscheiden zwischen Daten + Quittung. Im
Controller ist die Reihenfolge korrekt. Das Problem ist wohl eher auf PC
Seite zu suchen, weil dort in nicht definierten Zeiten neue Befehle
geschickt werden können..
einmal schrieb:> das Uart wird einmal geoeffnet, underst am Schluss wieder geschlossen,> nicht nach jedem Block. Und blockierend sollte man auch nicht arbeiten.
So mache ich es auch, ich schließe die uart nicht nach jedem
Schreiben/Lesen, da hab' ich mich wohl falsch ausgedrückt sorry.
Die Uart wird geöffnet, ein Befehl wird geschrieben (z.B. Logging an),
der wird, falls er verstanden wird quittiert:
1
...
2
fwrite(s,Befehl);
3
answer = fread(s,16)
4
...
Jetzt ist also der Logging Modus an und schickt dauerhaft 500 Byte (+16
Byte Header bzw Frame) Daten raus.
Die empfange ich z.b so:
1
data = [];
2
for i=0:1:9
3
data = [data; fread(s,516)]
4
end
5
...
Das funktioniert auch wunderbar. Aber möchte ich jetzt den Logging Modus
wieder ausschalten, schreibe ich
1
...
2
fwrite(s,LogOff)
3
answer = fread(s,16)
4
...
. Das funktioniert, wenn nicht in diesem Moment noch Daten kommen. Das
passiert aber häufig. Da liegt ja der Hund begraben ..
Jetzt am Ende wird die UART erst wieder geschlossen.
1
...
2
fclose(s)
3
delete(s)
spontan schrieb:> Unglücklich ausgedrückt. Du meinst, daß die Befehlsübermittlung in die> Datenübermittlung reintrifft?>
Ja parallel geht natürlich nicht wirklich.
> Du brauchst, wie oben schon angedeutet, ein kleines Protokoll, daß für> den empfangenden PC unterscheidbar macht, was gerade gesendet wird, wann> ein gesendeter Datensatz oder eine gesendete Befehlsresponse beginnen> und zu Ende sind.
Habe ich ja.
> Überleg Dir einfach wie eine menschliche Kommunikation ablaufen könnte,> das hilft.
Ich frage jmd etwas, ob ich was haben kann. Er sagt ja und fängt an zu
plappern. Dann sage ich irgendwann "stop". Er plappert aber
möglicherweise noch weiter, weil er es noch nicht gehört hat (oder noch
nicht "verarbeitet" hat). Ich warte aber nur noch auf "ok ich höre auf
zu plappern", weiß aber nicht wann das kommt und müsste so die ganze
Zeit darauf warten. Genau das letzte bereitet nunmal Probleme ;)
Eine Quittung kann erst nach einem 500Byte-Paket kommen.
Wenn Dir das zu lange dauert, mache eben die Pakete kürzer.
Bei CAN ist z.B. die maximale Paketlänge 8 Byte.
Dadurch ist es echtzeitfähig.
Peter
Den Befehl "fwrite(s,LogOff)" nur schicken wenn ein komplettes Paket
bzw. Frame Vollständig ist. Du mußt halt in LabView auch das Protokol
implementieren wie im µC.
Jan schrieb:
>Habe ich ja.
Das Protokoll war gemeint.
Dann muß ich sagen, daß das Protokoll nix taugt, es erfüllt ja die
Aufgabe nicht.
Wenn ein Befehl des PC in die Datenübertragung reintrifft, was soll dann
passieren? Was macht das Protokoll wirklich?
Deine letzten Sätze hab ich so verstanden, daß der µC die
Datenübertragung abbrechen soll und auf den PC-Befehl antworten soll.
Dann muß das das Protokoll auch machen (bzw. die Software natürlich).
Macht sie das auch?
Denke nein. Sonst gäbs die Probleme ja nicht.
Also verbessere das Protokoll, Software-Handshake, wie immer Du die
Prozedur zum Datenaustausch nennst. Sonst gehts nicht.
@ Uwe + Peter
Da werde ich ansetzen, dann lese ich halt noch ein komplettes Paket à
500 Bytes ein.
Das dauert mir nicht zu lange, hab' gerade mal nachgerechnet, es kommt
nicht auf jede Millisekunde an.
Danke!
Uwe schrieb:>> Uart - Daten + Steuersignale trennen?> Dafür ist ja das Protokoll da !
Hehe ja. Man muss es halt "nur" am PC auch vernünftig umsetzen..
@ Spontan:
Nein, der uC soll nicht zwischendrin die Übertragung abbrechen, dazu
müsste ja in der ISR auch schon der einkommende Befehl ausgewertet
werden. Die Übertragung soll ausgeschaltet werden, ja das stimmt. Aber
erst, wenn alle 500 Bytes verschickt wurden.
Und nein, das Protokoll taugt halt noch nichts, deswegen frage ich ja
hier nach ;) Möchte es ja verbessern.
Danke + schöne Grüße
spontan schrieb:> Überleg Dir einfach wie eine menschliche Kommunikation ablaufen könnte,> das hilft.
Nicht wirklich, dazu musst du bloss die üblichen Talkshows sehen wie
Anne Will usw. Es reden immer mehrere gleichzeitig und keiner antwortet
auf die letzte Frage. Wie bei der beschriebenen Software.
Gruss Reinhard