Kuriose Kommunikation

Hallo,

ich schreibe gerade an einem Testprogramm, um größere Datenmengen vom PC zum Arduino (Uno) per USB zu übertragen. Um zu testen, ob auch das richtige ankommt, sende ich es sofort wieder zurück:

void setup(){
	Serial.begin(115200);
}

char buffer[60];

void loop(){
}

void serialEvent(){	
	if(Serial.available() >= 60){
		Serial.readBytes(buffer, 60);
		Serial.write((uint8_t*) buffer, 60);
	}
}

Sobald die 60 Bytes vom PC gesendet wurden, wird darauf gewartet, dass 60 zurückkommen und der nächste 60er Block wird übertragen.

Nun zum Kuriosen:

Wenn ich zuerst mein Programm starte, dann den Arduino starte und die Daten übertrage, funktioniert alles bestens. Wenn ich aber ERST den Arduino starte und DANN mein Programm starte und übertrage, scheint alles etwas nach hinten verschoben zu sein:

Hat vllt jemand von euch eine Erklärung oder eine Idee? Ich suche natürlich auch PC-seitig nach dem Problem, aber mein Programm sendet nur in 60er Blocks, es sieht aber so aus, als würden da manchmal nur ganz am Anfang ein paar Bits zu viel geschrieben…

Das Programm in C# habe ich angehängt.

Gruß Metti

Neu Textdokument.txt (1.83 KB)

Ich verstehe Deinen Sketch nicht.
Du rufst nirgens die Funktion zur seriellen Übertragung auf.
Ich weiß jetzt nicht wie groß der Buffer der Seriellen Schnittstelle im Arduino ist. Wenn dieser kleiner als 64 Byte ist dann verlierst Du Daten.
Grüße Uwe

Ich habe gelesen, der Puffer hätte 64Byte, deshalb nehme ich die 60 Byte Blockgröße.

SerialEvent() habe ich laut Reference als den seriellen Interrupt des Arduinos verstanden. Es soll bei jedem Empfangen geprüft aerden, ob 60 Byte im Puffer sind. Falls ja werden 60 in der Variable gepuffert und gleich wieder ausgegeben.

Metti:
Ich habe gelesen, der Puffer hätte 64Byte, deshalb nehme ich die 60 Byte Blockgröße.

SerialEvent() habe ich laut Reference als den seriellen Interrupt des Arduinos verstanden. Es soll bei jedem Empfangen geprüft aerden, ob 60 Byte im Puffer sind. Falls ja werden 60 in der Variable gepuffert und gleich wieder ausgegeben.

Der Puffer hat 64 Bytes Größe und kann (prinzipbedingt) maximal 63 Bytes aufnehmen.

Wenn Du Deine Funktion nach 60 Bytes triggerst, hast Du also 3 Bytes Reserve, bis zu deren eintreffen die Funktion laufen muß. Bei 115200 Baud kommen ca. 11520 Zeichen pro Sekunde, Du hast also maximal 3/11520 = 0,00026 Sekunden Zeit, bis nach Erreichen des Füllstands die Funktion ablaufen muß. Es gibt sowohl Library-Funktionen als auch typische Aktionen auf einem Mikrocontroller wie ein simples "lcd.clear()", die bereits einzeln für sich viel mehr Zeit als 0,25 ms benötigen. Und dann läuft Dein Puffer intern über, bevor er gesendet wird, und es gehen Zeichen verloren.

An ein Zeitproblem hatte ich auch gedacht und eine Blockgröße von 8 Byte mit 9600Bd versucht, allerdings mit dem selben Ergebnis :-/

Ich hatte gehofft es wär sowas wie das Bit am Ende eines Strings, das unbemerkt mitübertragen würde, aber ich schicke ja keinen String sondern die Bytes wie sie im Array stehen. Dem empangenem Bild nach sieht es für mich aber aus, als würde VOR den richtigen Daten noch irgendetwas verschickt...

Metti:
An ein Zeitproblem hatte ich auch gedacht und eine Blockgröße von 8 Byte mit 9600Bd versucht, allerdings mit dem selben Ergebnis :-/

Du schreibst, dass Du einen UNO verwendest, um die Übertragung zu machen.
Ein UNO hat nur eine einzige serielle Schnittstelle.

Erkläre mal grob, wie Du das machst, auf einem UNO zwei serielle Schnittstellen gleichzeitig zu verwenden!

Und sagt jetzt nicht, eine davon ist eine Schnittstelle, die Du mit der "SoftwareSerial" Library realisierst, die mit der Arduino-Software mitgeliefert wird! Oder doch?

Hab ich nicht, ich habe den Sketch und mein C# Programm geändert und jeweils die Baudrate und die Blockgröße angepasst.

Vllt verstehe ich aber auch deine Frage falsch, wie kommst du auf 2 Schnittstellen?

Metti:
Vllt verstehe ich aber auch deine Frage falsch, wie kommst du auf 2 Schnittstellen?

Ich war davon ausgegangen, dass Du die Daten auf einer Schnittstelle empfängst und auf einer anderen zurücksendest, daher die Frage. Wenn das nicht der Fall ist und Du sendest auf derselben Schnittstelle zurück, vergiß die Frage!

Irgendwas mit der Synchronisierung zwischen Senden und Empfangen scheint nicht zu stimmen.
Setzt Dein PC-Programm vor dem Start der Aussendung alle Empfangsvariablen auf Null zurück?

Stimmt, das habe ich ursprünglich nicht! Habe es jetzt aber an jeder erdenklichen Stelle hinzugefügt, hilft aber nicht :-/

Metti:
Habe es jetzt aber an jeder erdenklichen Stelle hinzugefügt, hilft aber nicht :-/

Dann müßtest Du Dir eine Debug-Routine für den PC schreiben.

Der PC weiß ja, was er sendet.
Damit ist für den PC auch klar, was ankommen muß.

Jetzt brauchst Du auf dem PC nur noch vergleichen, an welcher Stelle im Datenstrom das was ankommt von dem abweicht, was gesendet wird, und dann weißt Du, wo es hakt.

Ich habe mir mal alles, was ankommt direkt nach dem Speichern im Puffer auf einer Listbox anzeigen lassen und stelle fest:

Der Mist kommt aus meinem C#-Programm :frowning:

Sobald ich den Port PC-Seitig öffne, schickt das Programm dem Arduino ein Minus, also die Zahl 240. Manchmal garnicht, manchmal bis zu 3 mal. Das passiert, auch wenn ich erstmal keine Daten übertrage, ich muss nur den Port öffnen. Habt ihr eine Idee, woher diese Daten kommen?

240 ist 0xF0, ( das ist zwar kein '-', aber egal ).
Kann daran liegen, dass vor dem Open das Datensignal auf 0 war und erst spät auf HIGH ( = idle = stopbit ) geht.
Seriell wird immer zunächst ein Startbit (0), dann das LSB, und zum Schluss mindestens ein Bit lang 1 ( Stopbit ) gesendet.
Wenn nichts gesendet wird, ist das Rx am Arduino HIGH.
Eine einzelne Flanke von Dauer-0 nach 1 sollte eigentlich, wenn überhaupt, als 0x00 - Zeichen interpretiert werden...
( Aber warum nicht auch als irgendwas zwichen 0x80, 0xC0, ... 0xFF )
Du nutzt wohl das DTR nicht, damit der Arduino beim Open am PC kein Reset macht ?

Stimmt, das Minus ist Quatsch, hab wohl ne blöde Quelle genutzt: http://www.tcp-ip-info.de/tcp_ip_und_internet/ascii.htm

Wenn ich DTR im C#-Programm aktiviere oder deaktiviere ändert sich nichts, ich habe es beim Standard (aus) gelassen.

Wenn es aber ein zufällig auftretender Fehler durch das Ändern des Potentials der Datenleitung ist, würde mich aber wundern, dass ich immer genau 240 bekomme. Vor allem manchmal auch mehrmals direkt hintereinander, manchmal garnicht :-/.