PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : unverständliches Zeitverhalten zweier Arduinos



fredyxx
05.01.2017, 09:31
Hallo,

ich habe einen Uno (Teilnehmer B) mit einem Mega (Teilnehmer A) über ihre seirellen SS's verbunden (beim Mega die SS2). Der Mega soll, wenn er vom Uno ein "ja" empfängt, nur Pin 13 auf HIGH setzen, ein "nein" an den Uno senden und 1 s warten. Wenn er vom Uno ein "nein" empfängt, Pin 13 auf LOW setzen, ein "ja" an den Uno senden und 1 s warten.
Der Uno soll immer umgekehrt sofort mit einem Telegramm antworten. Mehr haben die zwei nicht zu tun.

Das sollte m.E. bei den an den Pin's 13 angeschlossenen LED's eine Zykluszeit von ca. 2s ergeben.
Real zeigen die aber eine von ca. 8s!!!

Versteht das jemand?

Der Sketch vom Mega ist das:



void loop() {

if (Serial2.available()) // Abfrage, ob ein Signal von Teilnehmer B verfügbar?
{

Blinken = Serial2.readStringUntil('\n'); // der String enthält vor dem gesendeeten Text ein Steuerzeichen
Blinken.replace("\r", "\0"); // ersetzt das störende Steuerzeichen durch ein Nullzeichen, wird ignoriert
// danach enthält Blinken nur den gesendeten Text
} //********************** ENDE if (Serial.available()) ****************************


if (Blinken == "ja") { // Hat Teilnehmer B ein ja gesendet, dann >>>>
digitalWrite(ausgang, HIGH);
Serial2.println("nein"); // A sendet an B ein nein
delay(1000);


} //****************** ENDE if(Blinken == "ja")

if (Blinken == "nein") { // Hat Teilnehmer B ein nein gesendet, dann >>>>
digitalWrite(ausgang, LOW);
Serial2.println("ja"); // A sendet an B ein ja
delay(1000);

} //****************** ENDE if(Blinken == "nein")



} //****************** ENDE LOOP *******************************


Der Sketch vom Uno ist das:



void loop() {

if (Serial.available()) // Abfrage, ob ein Signal von Teilnehmer A verfügbar?
{
Blinken = Serial.readStringUntil('\n'); // der String enthält vor dem gesendeeten Text ein Steuerzeichen
Blinken.replace("\r", "\0"); // ersetzt das störende Steuerzeichen durch ein Nullzeichen, wird daher ignoriert
// danach enthält Blinken nur den gesendeten Text
} //********************** ENDE if (Serial.available()) ****************************


if (Blinken == "ja") { // Hat Teilnehmer A ein ja gesendet, dann >>>>
digitalWrite(ausgang, HIGH);

Serial.println("ja"); // B sendet an A ein ja


} //****************** ENDE if(Blinken == "ja")

if (Blinken == "nein") { // Hat Teilnehmer A ein nein gesendet, dann >>>>
digitalWrite(ausgang, LOW);

Serial.println("nein"); // B sendet an A ein nein

} //****************** ENDE if(Blinken == "nein")


} // ****************************** ENDE LOOP


vG

fredyxx

Mxt
05.01.2017, 10:48
Versteht das jemand?


Ich verstehe nicht einmal die Schaltung. Beim Uno ist Serial über die Pins 0 und 1 mit dem USB-Interface Chip verbunden. Vielleicht arbeiten da zwei Microcontroller gegeneinander.

fredyxx
05.01.2017, 13:17
Ich verstehe nicht einmal die Schaltung. Beim Uno ist Serial über die Pins 0 und 1 mit dem USB-Interface Chip verbunden. Vielleicht arbeiten da zwei Microcontroller gegeneinander.

Das ist mir schon klar. Deshalb trenne ich die SS wenn ich beim Uno eine Programmänderung hochlade. Ich bin jedoch der Meinung, dass die USB keine Rolle spielt, wenn ich den SM nicht nutze.
Nun habe ich beide Arduinos von den USB's getrennt, aber das Verhalten ändert sich nicht.
Man kann doch die Pins 0 und 1 sonst auch für andere Zwecke nutzen, wenn man USB nicht verwendet.

Die Schaltung hat keinen weiteren Sinn, außer, dass ich den Umgang mit der SS kennenlernen möchte.

vG
fredyxx

Mxt
05.01.2017, 14:08
Im Schaltbild vom Uno sind die Pins 0 und 1 auf jeden Fall mit denen vom zweiten Controller verbunden, das ist das IC neben dem USB-Stecker. Und beide Controller hängen an der selben Stromversorgung sind also immer beide an, egal ob das Board über USB oder anders versorgt wird.

Aber wenn das kein Problem ist, dann ist ja gut.

- - - Aktualisiert - - -

Ansonsten hat der Code natürlich einige Probleme:



void loop() {

if (Serial.available())
{
// ...

}


if (Blinken == "ja") {
digitalWrite(ausgang, HIGH);

Serial.println("ja"); // B sendet an A ein ja
}


Sendet in jedem Loop Durchlauf ein "ja", bis wieder was empfangen wird, denn Blinken ändert sich ja nicht dadurch, dass es mit etwas verglichen wird.

fredyxx
05.01.2017, 14:38
Im Schaltbild vom Uno sind die Pins 0 und 1 auf jeden Fall mit denen vom zweiten Controller verbunden, das ist das IC neben dem USB-Stecker. Und beide Controller hängen an der selben Stromversorgung sind also immer beide an, egal ob das Board über USB oder anders versorgt wird.

Das kann ich in dem Schaltbild auch so erkennen. Aber es gibt ja kein Verbot, 0 und 1 nicht zu verwenden, nur eben nicht gleichzeitig mit USB.

Aber dein letzter Hinweis ist gut. Das werde ich mal ändern. Das hatte ich bisher übersehen.

- - - Aktualisiert - - -

Danke, das war's.

Nun kommen am Mega auf dem SM die ja's und nein's völlig gleichmäßig, was vorher nicht der Fall war. Was da ankam war ziemlich durcheinander.

Außerdem klappt es nun auch wenn die USB's gesteckt sind.
Selbst wenn ich am Uno-Programm den SM öffne ist noch alles ok, solange ich aus dem Programm keine anderen Sendebefehle gebe und das ist ja dann auch verständlich!!

Danke und Gruß

fredyxx

Mxt
05.01.2017, 15:28
Diese Art von Fehler ist übrigens der Grund, warum ich dem readStringUntil sehr skeptisch gegenüberstehe.

Wenn mal viel mehr ankommt als gedacht, empfängt der Arduino bis der Speicher voll ist und er stehen bleibt.

fredyxx
05.01.2017, 16:12
Was wäre die Alternative?

Mxt
05.01.2017, 17:32
Also wenn man sich mal anschaut, wie readStringUntil in der Arduino IDE implementiert ist


String Stream::readStringUntil(char terminator)
{
String ret;
int c = timedRead();
while (c >= 0 && c != terminator)
{
ret += (char)c;
c = timedRead();
}
return ret;
}

dann kann man sich etwas ähnliches auch selber bauen.

Auch das da verwendete timedRead ist keine Gehirnchirugie


int Stream::timedRead()
{
int c;
_startMillis = millis();
do {
c = read();
if (c >= 0) return c;
} while(millis() - _startMillis < _timeout);
return -1; // -1 indicates timeout
}


Man kann das also recht einfach dem eigenen Protokoll anpassen und dabei auch mitzählen, wie viele Zeichen man schon gelesen hat. Schickt einem da einer zuviel, schmeißt man es einfach weg. Kommt nach der eingelesenen Zeile noch was und man hat das eingentlich nicht erwartet, kann man das auch behandeln.

Man kann auch "spionieren", was da noch kommt. Es gibt auch ein Serial.peek(). Das arbeitet wie read(), löscht das Zeichen aber nicht aus dem Schnittstellenpuffer.

fredyxx
05.01.2017, 18:03
Das muss ich erst mal verdauen!!