Achso. hier noch der komplette Sketch.
Alarm_07_05_2014_TEST_PC.ino (22.7 KB)
Achso. hier noch der komplette Sketch.
Alarm_07_05_2014_TEST_PC.ino (22.7 KB)
Ich weiß nicht wie das auf dem UNO ging, aber das ist alles andere als gut:
if ( Serial.available() > 0 )
Die serielle Kommunikation braucht viel Zeit. Bei 9600 Baud hast du 1ms pro Zeichen! 1 Baud ist ein Zustandswechsel pro Sekunde und du hast 10 Bits pro Zeichen. Also 1 / Baudrate / 10 Sekunden pro Zeichen
Du kannst also nicht schon nach dem ersten Zeichen alles einlesen.
Bei Strings kann man da bequem bis zu einem Endzeichen einlesen. Bei Zahlen ist es problematischer. Du kannst mal ein entsprechend langes delay() nach der available() Abfrage machen. Da ist dann die Frage ob die mit dieser Blockierung leben kannst. 200-300ms z.B. können locker vertretbar sein. Das bemerkt man eventuell gar nicht. Das Delay sorgt dann dafür dass in der Zwischenzeit die andere Zeichen eintreffen.
Der serielle Eingangspuffer ist glaube ich allerdings nur 63 Bytes groß
Jetzt funktionierts. Mit delay(200) ist das i.O. . Danke schonmal dafür. Liest denn der 2560 den Eingangspuffer schneller ein als der Uno? Schon irgendwie komisch.
Und jetzt noch ein logisches Problem:
Stichwort Bitmaske
if(1 & (EEPROM.read(1)>>0))
{
digitalWrite(10, HIGH); // Alarm-Signal Sirene !
}
if(1 & (EEPROM.read(1)>>1))
{
digitalWrite(53, LOW); // LED-Blitzer Signal !
}
Den LED-Blitzer können wir mit der Maske an- und ausschalten aber bei der Sirene klappt das nicht. Die ist immer an ( im Alarmfall ).
Mir fällt grad ein, dass ich es mal damit probieren kann:
if(1 & EEPROM.read(1))
{
digitalWrite(10, HIGH); // Alarm-Signal Sirene !
}
Verwende bitRead():
http://arduino.cc/en/Reference/BitRead
Das kapselt das für dich mit einem Makro. Dadurch macht man weniger Fehler
Zum Einlesen noch mal. Wenn es für dich passt, kannst du es auch lassen, aber da du vom PC einen String sendest, kannst du ihn auch zeilenweise Einlesen.
So:
http://forum.arduino.cc/index.php?topic=236026.msg1711126#msg1711126
oder
http://forum.arduino.cc/index.php?topic=233883.msg1684623#msg1684623
Ist das gleiche Prinzip, aber leicht anders implementiert
Dabei musst du auf dem PC am Ende des Strings ein Linefeed oder Carriage Return anhängen (je nachdem auf welches Endezeichen man im Code abfragt). Dann liest Zeichen für Zeichen in einen Puffer bis zum Ende. Ohne delay() und ohne zu blockieren.
Die übertragenen Daten selbst kann man auch allgemeiner halten. Bei sowas bietet es sich an die Zahlen durch Kommas zu trennen. Dann kann man mit strtok() die Kommas Schritt für Schritt durch NULL ersetzen. Diese Funktion gibt außerdem jedesmal einen Zeiger auf den Teil-String zurück. Das heißt, dass jeder Teil-String korrekt terminiert ist und direkt in andere Funktionen wie print() und atoi() eingesetzt werden kann. Man muss nur die Reihenfolge der Zahlen kennen, aber es ist egal wie lang diese Zahlen sind. Also muss man sich nicht mit den genauen Indices herumärgern.
Wenn du z.B. sowas in dem Puffer-Array stehen hast: "10,2000,300", kann man das machen:
int val1 = atoi(strtok(serialBuffer, ","));
int val2 = atoi(strtok(NULL, ","));
int val3 = atoi(strtok(NULL, ","));
Danach stehen in val1-3 die drei Zahlen. Und es ist egal wenn die Länge der Zahlen von einer Übertragung zur andern variiert
Wenn man die Zahlen mit einem Zeichen trennt, sparst du dir auch diese Sache mit dem Kopieren des Teil-Strings in ein anderes Array. Da du aber die Länge der Zahlen kennst und die anscheinend konstant sind, könntest du die Teil-Strings wahrscheinlich auch schon in C# korrekt terminieren. Also die Zahlen mit einem '\0' voneinander trennen. C# verwendet für Strings keine Null-Terminierung, aber wenn du das so über Serial schickst, ist es dann für C++ schon korrekt.
Serial.println() mit dem Anfang des Puffers schreibt dann natürlich nicht mehr den gesamten String, aber du kannst dann direkt atoi() mit den Anfang der Teil-Strings machen (ohne strtok(), da du wohl die Indices kennst). Im Prinzip so wie du es jetzt schon hast, aber ohne den Zwischenschritt mit dem anderen Array. Die Variante habe ich noch nicht ausprobiert, aber sollte eigentlich problemlos funktionieren.
Bei der Version kann man auch einfach strcpy() verwenden wenn doch was kopiert werden muss, da eben die Terminierung passt. Wobei so wie du es hast auch memcpy() statt den for-Schleifen schöner und kürzer ist um Speicher zu kopieren.
Noch eine Kleinigkeit. Du solltest bei Serial.println() die Strings in ein F() packen. Sonst müllst du das RAM mit den String Konstanten zu. Da kommen schnell mal ein paar hundert Byte zusammen. So bleiben die Strings im Flash:
Serial.println(F("String im Flash"));
Geht aber nur mit print()/println()