ich versuche gerade zwei Arduinos miteinander Sprechen zu lassen. Das ganze will ich über i2c laufen lassen. Hierfür soll der Master einen String übermitteln, der Anweisungen welche mittels "," getrennt sind übersendet.
das ganze läuft über den Eventhandler soweit ist mir das klar, über Wire.available erhalte ich aussage darüber ob noch gesendet wird, aber wie bekomme ich die Trennung hin? ich lese ja byte für byte ein in den Beispielen von der Software. Oder muß ich erst alles in einen String packen und diesen dann danach erst zerteile? Wenn ja kann ich alles auf einmal auslesen irgendwie?
C-Strings sind hier die beste Wahl, wenn du mit Trenn-Zeichen arbeiten willst. Du brauchst außerdem ein End-Zeichen damit du weißt wann du fertig bist.
Man kann das Byte für Byte einlesen und on-the-fly wieder in Zahlen wandeln, aber vielseitiger ist wenn man erst mal einen ganzen String einliest und danach zerteilt. Dazu braucht man mehr Speicher, aber man ist auch wesentlich flexibler.
Denke auch daran, dass du Integer vor dem Senden in einen C-String wandeln musst! (mit itoa()). Wenn du einfach einen Integer an Wire.write() übergibst wird das Binär gesendet. Dann kommt Müll heraus wenn du auf der anderen Seite einen String erwartest.
das hat mir schon mal geholfen funktioniert jetzt fast. Auch der Hinweis mit itoa hat mir einiges an Problemen erspart.
Jetzt habe ich aber ein neues Problem. Ich lese mit einem Ethernetshield die Uhrzeit von einem Time-Server. Nun würde ich gerne die Stunden und Minute über die i2c schicken. Nun ist aber die Zeit dummerweise ein unsigned long... Wie bekomme ich das den geändert um es zu übertragen?
Nun würde ich gerne die Stunden und Minute über die i2c schicken. Nun ist aber die Zeit dummerweise ein unsigned long...
Üblicherweise senden RTC-Module auf I2C die Zeit gern BCD codiert. (ca. 6 Byte)
Wenn du aber c-strings vorziehst und wirklich nur "hh:mm" willst, ist eine unsigned long unixtime als Text nicht unbedingt das einfachste.
macht das der Compiler für dich und erzeugt ein Array der Länge 5.
Auch Konviertierungs-Funktionen wit itoa() terminieren automatisch die Strings.
Aber wenn du z.B. Zeichen per Hand in einer for-Schleife in ein char Array schreibst bist du dafür selbst verantwortlich.
Danke für die Antwort.
Bei mir muss der Master die aktuelle Zeit und das Datum erfassen und es dann zum Slave schicken.
Die String ist 1:1 wie oben und hat immer die gleiche Länge.
Wird beim übertragen noch irgendein Zeichen hinzugefügt oder reicht es wenn ich einfach beim Slave ein String mit 20+1 (für '\0') Stellen erwarte?
carnefix:
oder reicht es wenn ich einfach beim Slave ein String mit 20+1 (für '\0') Stellen erwarte?
Sollte ausreichen
Und wie oben gesagt sind die Puffer bei I2C kleiner als bei Serial. Also sollte man da keine Romane senden und es bei längeren Sachen lieber Binär übertragen. Aber 21 Byte geht noch.
// Init
DS1307 rtc; // Real-Time-Clock
char datetime[21] = "";
Wire.begin();
void loop() {
rtc.get(&second, &minute, &hour, &day, &month, &year);
datetime = String(day) + "." + String(month) + "." + String(year) + ";";
datetime += String(hour) + ":" + String(minute) + ":" + String(second) + ";";
// start measurement on master
// save data with date and time
// show data, date and time on display
// sending the date and time is the trigger to start the measuring on the slave
Wire.beginTransmission(9); // transmit to device #9
Wire.write(datetime); // sends date and time (dd.mm.yyyy;hh:mm:ss;)
delay(200);
Wire.endTransmission(); // stop transmitting
}
Slave:
// Init
Wire.begin(9);
char datetime[21] = "";
char prev_datetime = datetime;
Wire.onReceive(receiveEvent); // register event // get x
void receiveEvent(int howMany) {
char datetime = Wire.read();
}
void loop() {
// wait for trigger from master
// if the previous date and time has changed, start the new measurement
if (strcmp(prev_datetime, datetime) != 0){
// start measurement
// save data with date and time
// show all on display
prev_datetime = datetime;
}
}
char datetime[21]; // ist kein string-Objekt
rtc.get(&second, &minute, &hour, &day, &month, &year);
sprintf(datetime, "%02d.%02d.%04d %02d:%02d:%02d",
day, month, year, hour, minute, second ); // sprintf ist nicht optimal, aber einfach
lcd.write(datetime); // show datetime on display
Die Variable datetime heißt eigentlich ausgabe, was ich aber hier umgeändert hatte zur Veranschaulichung.
Nach dem erfassen der zeit wird es dann als datetime gespeichert und die ausgabe wird weiter mit messdaten aufgefüllt.
Ich habe bereits ein voll Funktionsfähiges Programm zur Messung und Darstellung auf dem Touch Display bekommen. Ich muss es nur mit dem I2C-bus für mehrere Boards erweitern.
Ich habe ein Teil des Codes beim Master übersehen, es wird eigentlich so deklariert:
String datetime[21] = "";
Ist dies für den Slave korrekt?
void receiveEvent(int howMany)
{
if (Wire.available() == 21) // Wire.available() = number of bytes to read
{
for(int i=0; i<20 ; i++) // till 20 since '\0' was also sent
{
datetime[i] = Wire.read ();
}
}
}
War der Slave Reciever so in Ordnung?
Der ursprüngliche Code ist sehr lang und umfangreich und muss deshalb an vielen Stellen ergänzt werden.
Wenn du die Zeit als Text, und ein zusätzliches '\0' sendest, und insgeamt so viele Zeichen sendest, ist das schonmal besser als der vorige Ansatz.
Warum verwendest du nicht den Parameter int numbytes ?
Und fügst das Text-Ende selbst dazu ?
Ausserdem empfiehlt es sich immer, Teile bei denen man nicht sicher ist ob es funktioniert, gleich zu testen, besonders wenn man Angst hat, viel Fleißarbeit umsonst zu machen, oder wenn man schnell erste Erfolgserlebnisse sehen will.
der Code den ich bekommen hatte, ist voll funktionsfähig und macht keine Probleme.
Deshalb habe ich mich nicht komplett mit dem vorherigen code befasst.
Ich werde mal schauen was mit den aktuellen Code rauskommt.
Ich möchte nun, dass der Slave in void setup() auf ein Signal vom Master wartet und der Master ebenso auf eine Antwort vom Slave wartet, bevor beide in die loop() gehen.
Beim Master kann ich es ja mit einem requestFrom, machen, so dass es auf ein Signal des Slaves wartet.
Ich möchte nun, dass der Slave in void setup() auf ein Signal vom Master wartet und der Master ebenso auf eine Antwort vom Slave wartet, bevor beide in die loop() gehen.
damit der Master wartet, bis die Initialisierung des Slaves abgeschlossen ist.
Ich möchte nicht, das der Master bereits änfangt Daten zu senden, wenn der Slave noch am starten ist.
Daruch soll der Slave kein Triggern des Masters verpassen damit ich am Ende die gleiche Menge an Messdaten gespeichert habe.