Erstmal ich bin absoluter Anfänger, hab jetzt seit 3 Wochen zwei Arduinos. Hardware ist für mich kein Problem nur beim programmieren happert es total... nun steh vor nem sicher für Euch banalen Problem:
Am ersten Arduino sind 4 analge Sensoren und 8 digitale. Er ist als I2C Slave konfiguriert. Er erfasst Messdaten rechnet ein bisschen drann rum.
Der 2. Arduino ist I2C Master und hohlt die Daten ab und macht weiter
Die Messdaten Erfassung und die generelle I2C Kommunikation hab ich hinbekommen nun zu meinem Problem:
Ich möchte am 1 Arduino die 12 Variablen zu einem String zusammenfügen das ist mit den digitalen Daten kein problem da es nur 1stellige Werte sind nur die analogen machen mir Probleme da sie von 0-1023 gehen somit bekomme ich einen String unterschiedlicher länge was mir dann am 2.arduino beim abfragen per i2c Probleme bereitet. jetzt stell ich mir halt vor das bei den Analogwerten einfach Nullen vorne eingefügt werden solange bis die Aariable 4 Stellen hat somit komme ich auf einen String der dann immer 24Byte lang ist (4x4bytes für die analogen Werte plus 8 byte für die digitalen)
Auch das Zerlegen des empfangenen Strings macht mir Probleme da ich keinen Ansatzpunkt habe... wie gesagt ich bin programmier DAU.
Ist überhaupt mein Gedankengang richtig oder gibts ne bessere Variante die Daten vom Master aus abzufragen?
Hi,
ich habs mir jetzt nicht genau angesehen, aber gerade für dein Längenproblem bin ich der Meinung das du das (sorry) ungeschickt gelöst hast. Dafür gibt nämlich eine Funktion. Versucht mal folgendes
char buffer[90]; // hier den Wert auf was sinnvolles stellen
sprintf(buffer,"%3i",wert_zwischen_0_und_999);
oder für deine nullen
sprintf(buffer,"%03i",wert_zwischen_0_und_999);
also aus
switch (laenge1)
{
case 1:
Geber_1 = String("000" + Geber_1);
break;
case 2:
Geber_1 = String("00" + Geber_1);
break;
case 3:
Geber_1 = String("0" + Geber_1);
break;
case 4:
break;
}
hi danke erstmal für deinen tip. nur komm ich nicht ganz klar damit:
als ausgangspunkt gibts den "int Kanal_1" der die werte per analogread zwischen 0-1023 bekommt.
anschliessend (im mir geposteten code nicht ersichtlich) werden noch bestimmte faktoren mit dem Kanal_1 zusammen gerechnet. wir sind noch immer bei nem int der jetzt nen wertebereich von -500 bis +1000 hat.
nach den berechnungen wird der int Kanal_1 in den string Geber_1 umgewandelt. in dem switch wird dann die führenden nullen ergänzt um immer 4 stellig zu sein
danach werden die strings Geber_1 bis Geber_4 aneinandergehängt und können vom i2c master dann abgefragt werden.
wenn ich jetzt deinem beispiel folgend Geber_1 als char definiere bringe ich die integer werte nicht mehr rein , bekomme immer diesen fehler:
sticks_1_4:43: error: incompatible types in assignment of 'char' to 'char [4]'
hier nochmal der gesamte code mit deiner modifikation:
// Sticks 1-4
#include <Wire.h>
// ADC deklarieren
int ADC0=0;
int ADC1=1;
int ADC2=2;
int ADC3=3;
//Kanäle deklarieren
int Kanal_1;
int Kanal_2;
int Kanal_3;
int Kanal_4;
//div deklarationen
int laenge1=0;
int laenge2=0;
int laenge3=0;
int laenge4=0;
char Geber_1[4];
String Geber_2 = "";
String Geber_3 = "";
String Geber_4 = "";
String Geber_sum = "";
void setup ()
{
Serial.begin(57600);
Wire.begin(1); // Starte i2c bus als Slave mit addresse #1
Wire.onRequest(i2c_request); // I2C interrupt Routine i2c request
}
void loop()
{
//Kanäle einlesen
Kanal_1=analogRead(ADC0);
Kanal_2=analogRead(ADC1);
Kanal_3=analogRead(ADC2);
Kanal_4=analogRead(ADC3);
// Geber_1 = String(Kanal_1, DEC);
Geber_1 = char(analogRead(ADC0));
Geber_2 = String(Kanal_2, DEC);
Geber_3 = String(Kanal_3, DEC);
Geber_4 = String(Kanal_4, DEC);
//laenge1 = Geber_1.length();
laenge2 = Geber_2.length();
laenge3 = Geber_3.length();
laenge4 = Geber_4.length();
//switch (laenge1)
//{
//case 1:
// Geber_1 = String("000" + Geber_1);
// break;
//case 2:
// Geber_1 = String("00" + Geber_1);
// break;
//case 3:
// Geber_1 = String("0" + Geber_1);
// break;
//case 4:
// break;
//}
sprintf(Geber_1,"%04i",int(Geber_1));
switch (laenge2)
{
case 1:
Geber_2 = String("000" + Geber_2);
break;
case 2:
Geber_2 = String("00" + Geber_2);
break;
case 3:
Geber_2 = String("0" + Geber_2);
break;
case 4:
break;
}
switch (laenge3)
{
case 1:
Geber_3 = String("000" + Geber_3);
break;
case 2:
Geber_3 = String("00" + Geber_3);
break;
case 3:
Geber_3 = String("0" + Geber_3);
break;
case 4:
break;
}
switch (laenge4)
{
case 1:
Geber_4 = String("000" + Geber_4);
break;
case 2:
Geber_4 = String("00" + Geber_4);
break;
case 3:
Geber_4 = String("0" + Geber_4);
break;
case 4:
break;
}
Geber_sum = String(Geber_1 + Geber_2 + Geber_3 + Geber_4);
// Werte Seriell ausgeben
Serial.println(Geber_sum);
}
void i2c_request() //daten per i2c senden
{
char buffer[32];
Geber_sum.toCharArray(buffer, 32);
Wire.send(buffer);
}
wo mach ich den hier den fehler?
lg joe
edit: ausserdem ist mir gerade aufgefallen das durch sprintf das compilierte programm um ca 800byte länger ist....
// Sticks 1-4
#include <Wire.h>
// ADC deklarieren
int ADC0=0;
int ADC1=1;
int ADC2=2;
int ADC3=3;
//Kanäle deklarieren
int Kanal_1;
int Kanal_2;
int Kanal_3;
int Kanal_4;
//div deklarationen
int laenge1=0;
int laenge2=0;
int laenge3=0;
int laenge4=0;
char Geber_1[4];
String Geber_2 = "";
String Geber_3 = "";
String Geber_4 = "";
String Geber_sum = "";
void setup ()
{
Serial.begin(57600);
Wire.begin(1); // Starte i2c bus als Slave mit addresse #1
Wire.onRequest(i2c_request); // I2C interrupt Routine i2c request
}
void loop()
{
//Kanäle einlesen
Kanal_1=analogRead(ADC0);
Kanal_2=analogRead(ADC1);
Kanal_3=analogRead(ADC2);
Kanal_4=analogRead(ADC3);
// Geber_1 = char(analogRead(ADC0));
Geber_2 = String(Kanal_2, DEC);
Geber_3 = String(Kanal_3, DEC);
Geber_4 = String(Kanal_4, DEC);
//laenge1 = Geber_1.length();
laenge2 = Geber_2.length();
laenge3 = Geber_3.length();
laenge4 = Geber_4.length();
//switch (laenge1)
//{
//case 1:
// Geber_1 = String("000" + Geber_1);
// break;
//case 2:
// Geber_1 = String("00" + Geber_1);
// break;
//case 3:
// Geber_1 = String("0" + Geber_1);
// break;
//case 4:
// break;
//}
sprintf(Geber_1,"%04i",Kanal_1);
switch (laenge2)
{
case 1:
Geber_2 = String("000" + Geber_2);
break;
case 2:
Geber_2 = String("00" + Geber_2);
break;
case 3:
Geber_2 = String("0" + Geber_2);
break;
case 4:
break;
}
switch (laenge3)
{
case 1:
Geber_3 = String("000" + Geber_3);
break;
case 2:
Geber_3 = String("00" + Geber_3);
break;
case 3:
Geber_3 = String("0" + Geber_3);
break;
case 4:
break;
}
switch (laenge4)
{
case 1:
Geber_4 = String("000" + Geber_4);
break;
case 2:
Geber_4 = String("00" + Geber_4);
break;
case 3:
Geber_4 = String("0" + Geber_4);
break;
case 4:
break;
}
Geber_sum = String(Geber_1 + Geber_2 + Geber_3 + Geber_4);
// Werte Seriell ausgeben
Serial.println(Geber_sum);
}
void i2c_request() //daten per i2c senden
{
char buffer[32];
Geber_sum.toCharArray(buffer, 32);
Wire.send(buffer);
}
das mit dem Code "zuwachs" liegt glaube ich daran das weitere libs includet werden müssen. wenns bei dir auf den speicherplatz ankommt dann kannste sprintf tatsächlich nicht benutzten. Also das hat schon seine Richtigkeit... machts halt einfacher zu schreiben
die ersten 16 zeichen sind in "Geber_1" gespeichert und enthält aus mir unerfindlichen gründen alle kanäle von 1-4
die 2.te sequenz (Geber_2)mit 12 zeichen enthält die kanäle 2-4
die 3.te sequenz (Geber_3)mit 8 zeichen enthält die Kanäle 3,4
und einzig die 4.te sequenz(Geber_4) mit 4 Zeichen ist eigentlich korrekt und enthält nur den 4. Kanal
ich erkenne zwar das muster das dahintersteckt nur hab ich momentan keinen plan ... hab mir zar die englische referenz zu sprintf reingezogen nur blick ich die nicht ganz...
so wie ich das verstehe interagiert die erste sprintf anweisung mit allen nachfolgenden....
kommt mir vor wie bei ner seriellen ausgabe wo alles aneinander gereiht wird bis das Serial.println kommt
liege ich da richtig?
übrigens danke für deine hilfe.....
lg joe
edit: nachdem ich jetzt den code von den switch schleifen und unnötigen variablen befreit habe... ist der code sogar um einiges kleiner geworden
Und mich erst, normalerweise gibt's nur erstaunlich Ergebnisse wenn man z.b. Sowas macht
unsigned Long Test=123;
Char Buffer[10];
sprintf(Buffer,"%i",Test);
wobei das ja nun definitiv ein programmierfehler ist hab ich mich schon öfters über sowas gewundert
nö, test ist vom typ long, und %i heisst "interpretiere als integer" da kommt dann irgendwas wie 4234234234 raus...
"%lu" wäre richtig ... kannst ja mal testen
"mit großer Macht geht große Verantwortung einher,Luke" 8) also ja, ist schon extrem praktisch, aber ich hab schön öfters ein restart damit verursacht
und leider: nein, hab ich nicht. ist alles nur ungesundes halbwissen meinerseits. ich verwende:
%abc
wobei a entweder 0 oder ein paar andere sachen sein kann und dann für sowas steht wie "fülle mit nullen auf" oder + steht glaube für "mach ein pluszeichen davor wenns positiv ist" sowas ..
dann b anzahl an stellen ... also %08i kennst du ja schon 8 stelliger interer wert (häh?) ... vom prinzip her 8)
und dann c kann i,lu,s sein ( bestimmt noch mehr, aber die benutze ich hauptsächlich ) int,unsigned long,char array
Gruß JKW
PS: Sag Bescheid wenn du eine findest
edit1: Ich weiß das ist unvollständig und das man da noch mehr machen kann, sowas wie genauigkeit etc, das sollte nur zum Ausdruck bringen wofür ICH das hauptsächlich benutze und keine Anleitung sein ... nicht hauen
so bin jetzt ganz gut mit menem projekt unterwegs.
nun möchte ich aber etwas zur sicherheit ber der daten übermittlung am I2C machen da ich hinundwieder I2C fehler habe (manchmal kommt ein undefiniertes zeichen)
jetzt hab ich 2 dinge im kopf
1.) möchte ich die zu übermittelnde zeichenfolge verkürzen/komprimieren
2.) ne prüfsumme generieren um am master den empfangenen string auf richtigkeit zu überprüfen
Nabend, ich denke mal es wäre am besten ein neues Thema dafür zu eröffnen, da es ja denkbar wenig mit der Überschrift zutun hat.
Mein Rat wäre lediglich nicht gegen die Symptome sondern gegen die Ursache anzu gehen. Vor jedem senden den String auf senderseite per serielle Verbindung ausgeben und sobald ein Fehler auftritt kpntrollieren ob das was du senden wolltest korrekt war.
Wenn wirklich Fehler auftreten die aber durch Induktion oder ähnliches verursacht wurden und sich nicht durch den i2c Master, dann vielleicht die Kabel verdrillen.
Checksumme könntest du sonst z.b. Aus der Summe aller zahlen modulo "beliebiger wert" errechnen und anhängen. Oder zahlen nach hex wandeln vor der übertragung. Oder oder oder
gruß JKW
ich wollte diesen thread nochmal kurz aus der Versenkung holen da ich mit genau dieser Thematik den ganzen Abend verbracht hab.
Sprintf ist mehr als gefährlich,
ich hab heute ewig gesucht und dann genau dort den Fehler gefunden
char char_buffer[20] stand irgendwo, unglaublich weit oben im Quelltext, war früher mal 100 Felder groß. Vor ner Woche hab ich mal zum optimieren das Feld auf 20 Reduziert und heute gingen immer meine Variablen flöten ... das lag letztlich daran das die Anweisung: