I2C String übertragen mit einer max Länge von 100Zeichen

Hallo,

ich muss einen String vom Master Arduino zu einem Slave Arduino via I2C übertragen.
Mein String wird eine max erreichbare Länge von 100Zeichen bekommen können.

Da ich gelesen habe (Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino), dass man via I2C nur 32byte in einem Durchgang übertragen kann, würde ich gerne wissen, ob ich den String in Paketen also alle zB 20 oder 30 Zeichen übertragen kann.
Wird das interne Buffer bei jedem Aufruf von Wire.beginTransmission(Adress) gelöscht?

Würde das so funktionieren?

Der nachfolgende Code ist nur ein Test, da ich keinen Stringvarialbe mit Wire.write übertragen kann, konvertiere ich den String in ein charr Array via string.toCharArray und sende dann anhand der Stringlänge ( Array Länge ) jedes Zeichen einzeln

  // Übertrage die ersten 30Zeichen => 0 übertragen
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)                     
  Wire.write("123456789012345678901234567890");             // Teststring mit 30Zeichen
  Wire.endTransmission();     // stop transmitting

// Übertrage weitere 30 Zeichen => 30 übertragen
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)                     
  Wire.write("123456789012345678901234567890");             // Teststring mit 30Zeichen
  Wire.endTransmission();     // stop transmitting

// Übertrage weitere 30 Zeichen => 60 übertragen
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)                     
  Wire.write("123456789012345678901234567890");             // Teststring mit 30Zeichen
  Wire.endTransmission();     // stop transmitting

// Übertrage weitere 10 Zeichen => 90 übertragen
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)                     
  Wire.write("123456789012345678901234567890");             // Teststring mit 30Zeichen
  Wire.endTransmission();     // stop transmitting

// fertig, 100 Zeichen wurden übertragen....

so sieht derzeit mein Code aus ( in Testphase )
Mittels dtostrf konvertiere ich eine Float Variable in einen String.
Dabei hängt sich der Arduino natürlich auf…

void sendLCD()
{
  char charBuf[16];
  String LCDBuf = "";
  int len = 0; 
  //Stringübertragung ca 80Zeichen ==> Absicherung bis max 100Zeichen
  //g_wind,g_richtung,g_wind30,g_wind60,g_wind180,g_vmax30,g_vmax60,g_temperature,g_humidity,g_datum,g_uhrzeit,g_BSZ_counter_std,g_BSZ_counter_min
  LCDBuf  = dtostrf(g_wind,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += g_richtung;
  LCDBuf += ",";
  LCDBuf += dtostrf(g_wind30,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_wind60,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_wind180,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_vmax30,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_vmax60,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_temperature,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += dtostrf(g_humidity,4,2,charBuf);
  LCDBuf += ",";
  LCDBuf += g_datum;
  LCDBuf += ",";
  LCDBuf += g_uhrzeit;
  LCDBuf += ",";
  LCDBuf += g_BSZ_counter_std;
  LCDBuf += ",";
  LCDBuf += g_BSZ_counter_min;
  
  
  len=LCDBuf.length();           					        // ermittle Stringlänge
  char StringBuf_h[len+1];
  LCDBuf.toCharArray(StringBuf_h,len+1);
  Wire.beginTransmission(4); 							        // transmit to device #4
  char str[5] = {'L','C','D','1'};                // Header Kommando damit übertragener String direkt aufs Display kommt
  for (int j=0;j<4;j++)
  {
   Wire.write(str[j]);                            // sende Zeichenweise LCD, (mit Beistrich)
  }
  byte buffer_h[len+1];                           // Übertrage string byteweise
  for (int i=0;i<=len;i++)                        // übertrage byteweise
  {
    buffer_h[i] =StringBuf_h[i];
    Wire.write(buffer_h[i]);                                                            
  }
  Wire.endTransmission();  
}

lg Dieter

Dabei hängt sich der Arduino natürlich auf.....

Das hängt am String, nicht am I2C (Wire.h)

  1. Wofür brauchst du String ??? += sieht nur einfach aus, ist aber großer Mist. ;) Wenn du einen 100 byte großen Puffer brauchst, definiere ihn als char buffer[101], und schreib die Zeichen direkt rein.
  2. Warum überträgst du die Text-Teile nicht einzeln, dann hast du kein Problem Wire.write() Blocklänge ???

michael_x: 1. Wofür brauchst du String ??? += sieht nur einfach aus, ist aber großer Mist. ;) Wenn du einen 100 byte großen Puffer brauchst, definiere ihn als char buffer[101], und schreib die Zeichen direkt rein.

naja weil der Umgang halt mit String relativ schnell in wenig Programmzeilen erfolgt. Wo soll denn da der Fehler liegen in meiner Methode die Einzelstrings dem Gesamtstring aufzuaddieren?

michael_x:

Dabei hängt sich der Arduino natürlich auf.....

  1. Warum überträgst du die Text-Teile nicht einzeln, dann hast du kein Problem Wire.write() Blocklänge ???

Daran habe ich auch schon gedacht, jedoch habe ich da bei 13 Stringvariablen alleine 13 x diese Programmblockaufrufe.

Wire.beginTransmission(44); Wire.write(Stringblock); Wire.endTransmission();

hmmm irgendwie geht mir dass nicht mehr aus dem Kopf.

Letztendlich brauche ich unbedingt einen String wo alle Einzelstrings drinnen sind, oder ein Char Buffer wo alle Strings in ein char Array umgewandelt wurden und in das Char Buffer reingeschrieben worden sind. Ich will nur eine Variable ( String oder dieses CharBuffer ) über wire.write übertragen, damit der Empfänger aus den einzelnen Zeichen dann einen gesamtes CharBuffer zusammensetzen kann. Der Empfänger schaut sich dann die ersten 3 Zeichen an, wenn diese LCD lauten, dann leitet er das CharBuffer an die Stelle wo die Infos ans LCD ausgegeben werden weiter.

Wie verbinde ich nun in meinem Fall, all diese Einzelstrings in ein großes CharBuffer? Irgendwie stehe ich da momentan voll auf der Leitung....

...String relativ schnell in wenig Programmzeilen... Wo soll denn da der Fehler liegen ?

Stimmt schon, soweit. Aber ein Arduino UNO hat nur 2048 byte RAM.

String Test = "";
Test += "A";
Test += "B";

erzeugt 3 String Objekte, und schmeisst zwei (unbrauchbare kleine) Speicherfetzten wieder weg. Noch schlechter ist, dass diese dynamische Speicherverwaltung keine vernünftige Fehlerbehandlung hat.

char Test[100];
...
Test[0] = 'A';
Test[1] = 'B';
Test[2] = 0;

ist einfach robuster, und auch nur eine Zeile mehr ;)

Der Empfänger schaut sich dann die ersten 3 Zeichen an, wenn diese LCD lauten, dann leitet er das CharBuffer an die Stelle wo die Infos ans LCD ausgegeben werden weiter.

Ob das Ganze in 4 oder 100 Teilen übertragen wird, das Grund-Problem serieller Übertragung muss gelöst werden. Wo fängt was an, wo hört es auf ... (Die zwei Möglichkeiten, das Ende zu erkennen, sind 1. zuerst Länge übertragen, 2. Ende-Zeichen definieren )

Wie verbinde ich nun in meinem Fall, all diese Einzelstrings in ein großes CharBuffer?

Möglichkeit A)

 char data[100];
 int i = 123; 
 char buf1[10];
 dtostrf(g_val,4,2,buf1);

 sprintf(data,"LCD %s,%d, ... \n", buf1, i ); // leider geht %f nicht auf dem Arduino, muss es float oder double sein ?

Möglichkeit B) http://arduino.cc/forum/index.php?topic=103935.0 Reply #3

Leider schreibt ``` dtostrf(g_wind,4,2, &data[20]); ``` eine 0 auf data[24], was danach durch ein ',' ersetzt werden kann. Naja, String += ist schon "eleganter" ;)