nach nun mehreren Tagen Suche und probieren , komme ich einfach nicht zum Erfolg. Ich hoffe ihr könnt
mir helfen.
Habe 2 Mega über I2C angeschlossen. Am Bus hängt noch zusätzlich ein LCD 20x4 , welches der Master ansteuert. Nun möchte ich von Slave 2 Datensätze (String, char ???) zum Master übertragen und dort auf
2 verschiedenen Zeilen anzeigten lassen. Ich bekomme das nur auf einer Zeile hin.
Benutzt habe ich das Tutorial Master Reader/Slave Sender.
Slave Code:
#include <Wire.h>
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
}
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write("Zeile1"); // respond with message of 6 bytes
Wire.write("Zeile2"); // respond with message of 6 bytes
// as expected by master
}
Master Code: (wie muss das richtig aussehen, damit die Daten getrennt auf den LCD Zeilen geschrieben werden???)
#include <Wire.h> #include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for a 16 chars and 2 line display
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
lcd.init(); // initialize the lcd
lcd.backlight();
}
lcd.setCursor(0,2);
while (Wire.available()) { // slave may send less than requested
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
lcd.write(c);
}
Hallo Andy,
Du forderst nur 6 von zwölf Bytes an und schickst den Master dann mittels delay() schlafen. Bin mir nicht sicher, ob das eine gute Idee ist.
ja richtig. 6 ist im Beispiel Code zu wenig. Hab das u.a. auch mit 20(40) bytes probiert. Bekomme auch beide
Datensätze rüber zum Master. Nur weiß ich nicht wie ich Diese dann wieder auf zwei Zeilen schreiben kann.
Ein Lösungsansatz dort wäre hilfreich.
Wenn ich richtig verstanden habe, hast Du 2 Datensätze von je 6 Zeichen, also 12 Zeichen in der Übertragung. Richtig?
Oder sind es eher 2 Zeichenketten zu je 6 sichtbaren (also je 7 Byte "Zeile1")?
Das ist nur nen Beispiel.
Möchte 20 Zeichen pro Zeile voll nutzen. Der Code wird später in mein anderes Projekt implementiert (wenn es mal so läuft wie ich es mir vorstelle). Also könnte ich dann 2x 20 byte zum Master senden?
Wenn ja, wie sieht der code dazu aus? und wie bekomme ich Sie im Master dann wieder aufbereitet?
Habe es schon mit Arrays, Buffer u.s.w probiert. Nix bringt den Erfolg.
Das das nur ein Beispiel ist, ist klar. Es geht aber darum, was Du wirklich machen willst.
Da gibt es mehrere Szenarien, die anders gehandelt werden müssen.
Grundaussage (kam schon) der Puffer für I2C ist 32 Byte. Den entweder hoch setzen (Lib umschreiben) oder bei mehr als 32 Zeichen die Sendung splitten.
wenn es 2 unabhängige Zeichenketten von je 20 Zeichen sind, dann fordere getrennt ZK1 und ZK2 an
Wenn sie gemeinsam übertragen werden sollen, wie willst Du trennen? hat jede ihr '\0', dann ist das einfach, sonst muss man sich was überlegen.
Jetzt bist Du dran. Wie soll es konkret werden, sonst hat es keinen Zweck etwas zu überlegen.
agmue:
Man kann den Slave so implementieren, wie man es von einem IC kennt. Dann kannst Du die Informationen häppchenweise anfordern.
Das ist komplizierter als es sein müsste.
Nochmal:
Das war ein Workaround weil mir damals nicht klar war dass man im Event Handler nur einmal write() machen kann. Es hat mich gewundert dass man scheinbar nicht mehr als ein Byte auf einmal schicken konnte. Das geht aber sehr wohl wenn man mit write() einfach ein Array sendet.
Die Idee ist aber grundlegend nicht verkehrt. Man muss nur von dieser Register-Beschreibung wegkommen. Damit hat das nichts zu tun. Auto-Inkrementierung braucht man nicht zu implementieren, da die Übertragung nicht Byte-weise erfolgt!
Einfach vom Master eine Zahl (0 oder 1) an den Slave schicken. Und je nach deren Wert schickt man einen anderen Datensatz zurück an den Master wenn der Request kommt.
Und was hat setValue() da noch verloren? Das ist eine Funktion um einen int in das Byte Array zu schreiben. Jetzt hat man da aber Strings.
Hier mal etwas mehr auf Strings zugeschnitten und ohne die überflüssige Byte für Byte Übertragung.
Slave:
#include <Wire.h>
const int SLAVE_ADR = 5;
const char* const strings[] = { "Zeile 1", "Zeile 2", "Noch mehr Text" };
const int NUMBER_OF_STRINGS = sizeof(strings) / sizeof(strings[0]);
int index;
void setup()
{
Wire.begin(SLAVE_ADR);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}
void loop()
{
}
void receiveEvent(int howmany)
{
int value = Wire.read();
if (value < NUMBER_OF_STRINGS)
index = value;
}
void requestEvent()
{
Wire.write(strings[index]);
}
Master:
#include <Wire.h>
const int SLAVE_ADR = 5;
void setup()
{
Serial.begin(9600);
Wire.begin();
getData();
}
void loop()
{
}
void getData()
{
for (byte i = 0; i < 3; i++)
{
Wire.beginTransmission(SLAVE_ADR);
Wire.write(i);
Wire.endTransmission();
Wire.requestFrom(SLAVE_ADR, 20);
while (Wire.available() > 0)
{
char c = Wire.read();
if (c > -1)
Serial.print(c);
}
Serial.println();
}
}
Wenn man 20 Byte anfordert ist available() wohl 20 mal wahr, aber read() liefert für die restlichen Bytes -1. Ok, kann man einfach umgehen.
So kann man immer den maximal möglichen Text anfordern und nur so viel anzeigen wie tatsächlich empfangen wird.
Auf der Slave Seite ist der Text nehme ich mal an nicht unbedingt konstant, aber das ist kein Problem. Da kann man Senden was man will. Es muss halt eben in einem write() geschehen! Also wenn man variable Werte einfügen will sprintf() verwenden. Dann steht das in einem Array.
hab den code versucht anzupassen, nun muß ich nochmal nachfragen. Mir ist aufgefallen das eigentlich nur ein
Datensatz übertragen wird und nach 6 empfangenden bytes der Zeilenwechsel stattfindet. Hab ich das richtig erkannt?
Wollte eigentlich zwei unabhängige Variablen später für Zeile1/Zeile2 einsetzen.
"byte registers[NUMBER_OF_REGISTERS]={"Zeile1Zeile2"}; //Array für Daten"
Hab versucht Zeile1Zeile2 durch ein Komma zu trennen, aber das funzt nicht. Könnt ihr das nochmal anschauen.
Schau dir meinen Code an. Da ist es egal wie lange die Strings sind.
Du solltest, aber verstehen wie die beiden Event Handler zusammenarbeiten. Das ist der entscheidende Punkt. Den Rest kann man auch etwas anders machen, je nach Anwendung.
okay, danke werde es testen.
Nur nochmal eine doofe Frage: Wäre es möglich das der Slave direkt ans LCD schreibt?
Mein Projekt besteht aus drei Mega die nacheinander arbeiten. Wenn der erste fertig ist bekommt der 2. ein Signal und startet seinen Ablauf u.s.w. Immer der aktive Mega soll ans LCD schreiben. Nur muß ich dann den Bus Ein uns AUS schalten können. Wäre das eine Option?
Wäre es möglich das der Slave direkt ans LCD schreibt?
Ja klar!
Beide Arduinos können auf das Display schreiben.
Multimaster.
Muss man nur synchronisieren, damit nicht einer dem anderen heimlich den Cursor unter dem Arsch weg klaut.
Der Master macht den Takt.
Der Slave streckt ihn.
Beide sind für das Timing zuständig.
Und wie bekommt man den Takt synchronisiert?
Falsche Frage!
Es dreh sich um Arbitrierung, nicht um Takt.
Die beiden potentiellen Master müssen das untereinander aushandeln.
Alternativ:
If false, endTransmission() sends a restart message after transmission. The bus will not be released, which prevents another master device from transmitting between messages. This allows one master device to send multiple transmissions while in control.