Probleme mit I2C

Hey Leute,

ich benötige etwas Hilfe bei meinem Arduino Programm.

Kurze Zusammenfassung: ich soll von meinem Ausbilder aus ein “einfaches” I2C-Programm erstellen damit es nachfolgende Azubis einfacher haben in das Thema I2C einzusteigen.

Ich habe mir das Buch “Die elektronische Welt mit Arduino entdecken” von Erik Bartmann zur Hilfe genommen und daraus das Programm abgeschrieben, welches einen EEPROM ansteuert.
Jedoch entsteht ein Fehler beim Überprüfen und ich verstehe einige Programmzeilen nicht.

                                 /*Ansteuerung eines EERPOM per I2C*/


#include <Wire.h>                                                     
#define I2Cadresse 0x50                                             //Adresse des Speicherbausteins festlegen

void setup() 
{
 Wire.begin();                                                       //Starten des I2C-bus
 Serial.begin(9600);                                                 //stellt die Serielleschnittstelle zur Verfügung; Übertragungsrate: 9,6 kbit/s 
 unsigned int speicheradresse = 0;                                   //Startadresse
 byte wert = 7;                                                      //Zu speichernder Wert
 schreibeEEPROM(I2Cadresse, speicheradresse, wert);                  //schreiben des vorgegebenen Werts
 Serial.println(leseEEPROM(I2Cadresse, speicheradresse), HEX);       //lesen des EEPROM´s
}

void loop() 
{
 void schreibeEEPROM(int I2Cadresse, unsigned int speicheradresse, byte daten)
 {
   Wire.beginTransmission(I2Cadresse);                               //Verbindung zu I2C einleiten
   Wire.write((byte)(speicheradresse >> 8 ));                        //höchstwertiges Byte (MSB) senden
   Wire.write((byte)(speicheradresse & 0xFF));                       //niederwertiges Byte (LSB) senden
   Wire.write(daten);                                                //Daten-Byte senden
   Wire.endTransmission();                                            //Verbindung zu I2C trennen
   delay(5);                                                          //5ms Pause
 }
byte leseEEPROM(int I2Cadresse, unsigned int speicheradresse)
 {
   byte datenByte = 0xFF;
   Wire.beginTransmission(I2Cadresse);                                 //I2C Verbindung starten    
   Wire.write((byte)(speicheradresse >>8));                             //höchstwertiges Byte (MSB) senden
   Wire.write((byte)(speicheradresse & 0xFF);                          //niederwertiges Byte (LSB) senden
   Wire.endTransmission();                                             //Verbindung zu I2C trennen
   Wire.requestFrom(I2Cadresse, 1);                                    //Anfordern der Daten vom Slave; "1" steht für eon Daten-Byte
   if(Wire.available()) datenByte 0 Wire.read();                       //sind Daten vorhanden?
   return datenByte;                                                   //Daten-Byte zurückliefern    
 }
}

Die Arduino IDE zeigt mir einen Fehler in der Zeile

schreibeEEPROM(I2Cadresse, speicheradresse, wert); //schreiben des vorgegebenen Werts

im void setup() und zwar soll diese nicht deklariert sein aber das wird sie doch im void loop?!
Zudem verstehe ich diese Programmzeile nicht wirklich und finde auch keine Erklärung dazu im Internet.

2 lokale Funktionen in Loop? Das willst du nicht!

Bitte setze deinen Code in Code-Tags ( links oben ). Dann wird er besser lesbar dargestellt, und es entstehen auch keine emoticons wo sie nicht hingehören.

Ich kann mir nicht vorstellen, dass das so in dem Buch steht. Du defninierst die Funktionen 'schreibeEEPROM' und 'leseEEPROM' innerhalb einer anderen Funktion. loop() ist ja ebenfalls eine Funktion. Das funktioniert aber nicht, da sie so nicht global bekannt sind. Du musst diese Funktionen ausserhalb von loop definieren. Dann ist dein loop() zwar leer, aber Du willst ja scheinbar im setup nur mit einmal schreiben und lesen testen, ob der Zugriff auf das EEPROM funktioniert.

El_Duino: Hey Leute,

ich benötige etwas Hilfe bei meinem Arduino Programm.

Kurze Zusammenfassung: ich soll von meinem Ausbilder aus ein "einfaches" I2C-Programm erstellen damit es nachfolgende Azubis einfacher haben in das Thema I2C einzusteigen.

Nur als Idee: In Bezug auf I2C hat es bei mir bei diesem Beispiel zur Nutzung der DS3231-RTC klick gemacht: http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/ Mit dem Datenblatt kann man dann weitere Funktionen wie das Auslesen der Temperatur hinzufügen. Für mich wirkte die Benutzung der RTC sehr motivierend.

Vielen Dank für die schnelle Antwort. Habe das mit dem code geändert (war mein erster Post, bin noch nicht so drin in dem Thema aber vielen Dank )
Ich habe den Fehler gefunden, denn um buch steht:

void loop(){ /* leer */}

Hätte ich selbst drauf kommen müssen, vor allem weil er es vorher noch extra erwähnt hatte das man bloß nicht mit dem loop arbeiten soll da der EEPROM nur gewissen lese/schreib Zyklen hat.

Dennoch habe ich den Fehler: ‘schreibeEEPROM’ was not declared in this scope

Super, für den Test ist sicher richtig, das nicht im loop() zu machen, aber in einem echten Anwendungsprogramm wird es dann schon im loop() verwendet werden (nicht die Definition, aber der Funktionsaufruf ). Dann muss man aber auf andere Weise sicherstellen, dass das EEPROM nicht in jedem loop() Durchlauf, sondern nur bei Bedarf geschrieben wird, denn sonst ist es in der Tat schnell hinüber. Lesen ist übrigens kein Problem, nur zu oft Schreiben macht das EEPROM kaputt. Die halten zwar normalerweise >100000 Schreibzyklen aus, aber wenn man das in jedem loop macht, schafft der Arduino das ziemlich flott ;)

Wir reden von externen EEPROMs und nicht vom EEPROM im ATmega. Die externen halten normalerweise 1 000 000 Schreibzyklen aus. Grüße Uwe

Dennoch habe ich den Fehler: 'schreibeEEPROM' was not declared in this scope

Der Fehler ist doch klar!

Und die Lösung steht schon drin! Deklariere : 'schreibeEEPROM' Und dann bitte so, dass sie auch im Sichtbarkeitsbereich liegt.

Upps, ja die Nullen .. da fehlte eine :-[ . Aber auch das schafft der Arduino in sehr überschaubarer Zeit, wenn man in jedem loop() schreibt.

combie: Deklariere : 'schreibeEEPROM'

In der Arduino IDE sollte die Definition der Funktion eigentlich ausreichen. Die Frage ist, wie sein Sketch jetzt aussieht.

El_Duino: Dennoch habe ich den Fehler: 'schreibeEEPROM' was not declared in this scope

Die Antwort hast Du doch schon in #1 bekommen.

Gruß Tommy

so sieht aktuell mein Programm aus:

                                   /*Ansteuerung eines EERPOM per I2C*/


#include <Wire.h>                                                     
#define I2Cadresse 0x50                                               //Adresse des Speicherbausteins festlegen

void setup() 
{
  Wire.begin();                                                       //Starten des I2C-bus
  Serial.begin(9600);                                                 //stellt die Serielleschnittstelle zur Verfügung; Übertragungsrate: 9,6 kbit/s 
  unsigned int speicheradresse = 0;                                   //Startadresse
  byte wert = 7;                                                      //Zu speichernder Wert
  schreibeEEPROM(I2Cadresse, speicheradresse, wert);                  //schreiben des vorgegebenen Werts
  Serial.println(leseEEPROM(I2Cadresse, speicheradresse), HEX);       //lesen des EEPROM´s
}

 void loop()
{
 /* leer */
}

 void schreibeEEPROM(int I2Cadresse, unsigned int speicheradresse, byte daten)
 {
   Wire.beginTransmission(I2Cadresse);                               //Verbindung zu I2C einleiten
   Wire.write((byte)(speicheradresse >> 8 ));                        //höchstwertiges Byte (MSB) senden
   Wire.write((byte)(speicheradresse & 0xFF));                       //niederwertiges Byte (LSB) senden
   Wire.write(daten);                                                //Daten-Byte senden
   Wire.endTransmission();                                            //Verbindung zu I2C trennen
   delay(5);                                                          //5ms Pause
 }
 byte leseEEPROM(int I2Cadresse, unsigned int speicheradresse)
 {
   byte datenByte = 0xFF;
   Wire.beginTransmission(I2Cadresse);                                 //I2C Verbindung starten    
   Wire.write((byte)(speicheradresse >>8));                             //höchstwertiges Byte (MSB) senden
   Wire.write((byte)(speicheradresse & 0xFF);                          //niederwertiges Byte (LSB) senden
   Wire.endTransmission();                                             //Verbindung zu I2C trennen
   Wire.requestFrom(I2Cadresse, 1);                                    //Anfordern der Daten vom Slave; "1" steht für eon Daten-Byte
   if(Wire.available()) datenByte 0 Wire.read();                       //sind Daten vorhanden?
   return datenByte;                                                   //Daten-Byte zurückliefern    
 }

@combie das habe ich schon verstanden aber wie soll ich das deklarieren ?

Bitte habt etwas Verständnis dafür dass die Arduino Umgebung noch relativ Neuland für mich ist.

Der Fehler liegt etwas tiefer. Die Fehlermeldung ist eine Folge davon, dass in der Definition der Funktion ein Fehler aufgetreten ist. Das Problem ist deine Namensgebung. Hier:

#define I2Cadresse 0x50                                               //Adresse des Speicherbausteins festlegen

definiertst Du I2Cadresse als Konstante für den Precompiler. D.h. überall wo 'I2Cadresse' in deinem Sketch vorkommt, setzt der Precompiler '0x50' ein, und erst dann wird kompiliert.

In deinen Definitionen benutzt den gleichen Namen für die Funktionsparameter:

void schreibeEEPROM(int I2Cadresse, unsigned int speicheradresse, byte daten)

und

byte leseEEPROM(int I2Cadresse, unsigned int speicheradresse)

Hier ersetzt der Precompiler das nun auch durch '0x50', was dann aber beim Kompilieren zum Fehler führt, denn in der Definition der Funktion kannst Du keinen Zahlenwert als Parameternamen verwenden.

Du musst in der Definition deiner beiden Funktionen einen anderen Namen verwenden. Hier zeigen sich die Tücken des Precompilers, der nur stur Textersetzungen macht, ohne die Namensräume zu kennen. Mit

const byte I2Cadresse = 0x50;                                               //Adresse des Speicherbausteins festlegen

hättest Du das Problem nicht bekommen. Der Code enthält aber dann noch weitere Fehler.

Edit: Es ist deshalb auch eine sehr sinnvolle Übereinkunft, #define - Konstanten immer rein in Großbuchstaben zu benennen, damit es keine Überschneidungen mit Variablennamen gibt.

Danke dafür, habe noch ein paar Fehler gefunden bzw. finden lassen;)