- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 44

Thema: EEPROM - ausgelesener Wert ist ungenau

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    131

    EEPROM - ausgelesener Wert ist ungenau

    Hallo Forum,
    ich bin mal wieder an einem kleinen Arduino FM-Radio dran, diesmal mit RDA5807M, Arduino Pro Mini und OLED 128x32.
    Ich speichere die aus dem RDA ausgelesene Frequenz im EEPROM, um bei Neustart bei der selben Station zu beginnen.
    Mein Problem ist die Genauigkeit. Manchmal stimmt die Startfrequenz genau, oft liegt sie aber nach Reset oder Neustart mehr oder weniger neben der vorherigen. Ich hab versuchsweise kleine Pausen vor und nach dem EPROM-Schreiben eingefügt. Hat nichts gebracht. Die sind zwar immer in der Nähe des Sollwerts aber selten genau wo sie sollen.
    Hier der Code:
    Code:
    /**************************************************************************
     * FM-Radio mit RDA5708M, Arduino Pro Mini 3.3V und OLED 128x32           *
     * Steuerung über vier Drucktaster:                                       *
     *    button 1 - volume down                                              *
     *    button 2 - volume up                                                *
     *    button 3 - scan frequency down                                      *
     *    button 4 - scan frequency up                                        *
     * Das OLED-display zeigt zwei Zeilen:                                    *
     *  1- "Empfangsfrequenz"                                                 *
     *  2- "Volume level" + "Batteriespannung"                                *
     *      alternativ bei Unterschreiten von 3,3V "CHARGE BATTERY"           *           
     * Die Empfangsfrequenz wird im EEPROM gespeichert.                       *
     *                                                                        *
     * U.Galepp 2018                                                          *
     **************************************************************************/
    
    #include <Arduino.h>
    #include <Wire.h>
    #include <radio.h>
    #include <RDA5807M.h>
    #include "U8glib.h"
    #include <EEPROM.h>
    
    U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);  // Auswahl des OLED Typs
    
    #define FIX_BAND     RADIO_BAND_FM            // ausgewähltes Band ist FM
    #define FIX_VOLUME   3                        // Lautstärke beim Start
    
    RDA5807M radio;                               // create an instance of class for RDA5807M chip
    
    int volume = FIX_VOLUME;
    
    int button_1 = 4;                             // Taster für volume up an D4
    int button_2 = 5;                             // Taster für volume down an D5
    int button_3 = 6;                             // Taster für scan up an D6
    int button_4 = 7;                             // Taster für scan down an D7
    int buttonState_1 = 0;
    int buttonState_2 = 0;
    int buttonState_3 = 0;
    int buttonState_4 = 0;
    int frequency;
    char vol[2];
    float volts;
    char akku[4];
    
    /*** setup ***/
    void setup()
      { 
      Serial.begin(57600);
      Serial.println("Radio...");
      delay(200);
      
      radio.init();                               // Radio initialisieren
      radio.setBand(FIX_BAND);
      EEPROM.get(0, frequency);
      delay(100);
      radio.setFrequency(frequency);
      delay(100);
      radio.setVolume(volume);
      
      pinMode(button_1, INPUT);                   // Taster-Pins als Eingang definieren
      pinMode(button_2, INPUT);                   // -||-
      pinMode(button_3, INPUT);                   // -||-
      pinMode(button_4, INPUT);                   // -||-
      digitalWrite(button_1, HIGH);               // Pull-Up Widerstände aktivieren
      digitalWrite(button_2, HIGH);               // -||-
      digitalWrite(button_3, HIGH);               // -||-
      digitalWrite(button_4, HIGH);               // -||-
      } 
    
    /*** Subroutine Spannungsmessung ***/
    void measureVolt()
      { analogReference(INTERNAL);
        volts = (float)analogRead(A0)*6.1/1000;}
    
    /*** Subroutine Datenanzeige auf OLED ***/
    void displayData()
      {
       u8g.firstPage(); 
        do {
          u8g.setFont(u8g_font_helvB14);
          char s[12];
          radio.formatFrequency(s, sizeof(s));
          u8g.drawStr( 10, 15, s);
          u8g.setFont(u8g_font_unifont);
          
          if(volts > 3.3)                         // wenn Vcc > 3.3V zeige "Volume" & "Volt"       
            {
            u8g.drawStr( 0, 32, "Vol:");
            sprintf (vol, "%d", volume);          // Umwandlung int "volume" zu char "vol"
            u8g.drawStr( 35, 32, vol);
            u8g.drawStr( 60, 32, "Bat:");
            dtostrf(volts, 2, 1, akku);           // Umwandlung float "volts" zu char "akku"  
            u8g.drawStr( 95, 32, akku);
            u8g.drawStr( 119, 32, "V");
            }
           else                                   // wenn VCC >= 3.3V zeige "CHARGE BATTERY"
           {
            u8g.drawStr(8, 32,"CHARGE BATTERY");
           }
        } while( u8g.nextPage() );
      }
       
    /*** main loop ***/
    void loop() 
      {
      measureVolt();                              // Batteriespannung messen
      
      displayData();                              // alle Daten auf OLED anzeigen
    
    /*  frequency = (radio.getFrequency());       // nur zum Test was gespeichert ist
        Serial.print("Frequenz: ");                 
        Serial.println(frequency);
    */
       
      if(!digitalRead(button_1) ) {               // wenn Taster 1 gedrückt, Volume einen Schritt runter
       while(!digitalRead(button_1) )             // warten auf Taster loslassen == HIGH
          {delay(10);}
          volume --;
          if (volume < 0) volume = 0;
          radio.setVolume(volume);
          delay(100);
          } 
            
      if(!digitalRead(button_2) ) {               // wenn Taster 2 gedrückt, Volume einen Schritt hoch
       while(!digitalRead(button_2) )             // warten auf Taster loslassen == HIGH
          {delay(10);}
          volume ++;
          if (volume == 16) volume = 15;
          radio.setVolume(volume);
          delay(100);
         } 
         
      if(!digitalRead(button_3) ) {               // wenn Taster 3 gedrückt, abwärts scannen   
       while(!digitalRead(button_3) )             // warten auf Taster loslassen == HIGH
          {delay(10);}
          radio.seekDown();
          delay(100);
          frequency = (radio.getFrequency());     // neue Frequenz aus RDA5807M auslesen
          delay(100);
          EEPROM.put(0, frequency);               // neue Frequenz in EEPROM speichern
          delay(100);
          }
          
      if(!digitalRead(button_4) ) {               // wenn Taster 4 gedrückt, aufwärts scannen   
       while(!digitalRead(button_4) )             // warten auf Taster loslassen == HIGH
          {delay(10);}
          radio.seekUp();
          delay(100);
          frequency = (radio.getFrequency());     // neue Frequenz aus RDA5807M auslesen
          delay(100);
          EEPROM.put(0, frequency);               // neue Frequenz in EEPROM speichern
          delay(100);
          }
      }
    Ich habe heute erst mit EEPROM begonnen, wahrscheinlich habe ich einen Denkfehler aber wo?
    Für Tips wäre ich dankbar.

    Gruß Uwe

  2. #2
    shedepe
    Gast
    Könntest du ungenau mal genauer spezifizieren. Habe deinen Code jetzt nicht gelesen. Aber prinzipiell: Wenn du einen Wert im EEPROM speicherst und nicht total viel Pech hast und dir kosmische Strahlung ein Bit kippen lässt, dann wirst du diesen Wert auch wieder auslesen.

    Dein Problem könnte eventuell daran liegen, dass du die Frequenz als int ausliest, die EEPROM library aber nur bytes erwartet.
    EEPROM.read() gibt aufjedenfall nur einzelne Bytes zurück.

  3. #3
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo!

    @ basteluwe

    Ich vermute, dass der Fehler durch AFC ("Automatic Frequency Control" -> automatische steuerung der Frequenz) verursacht ist. Auf der "page 9" des Dateblattes habe ich im Register 04H das AFCD "default=0" gefunden. Das bedeutet, dass AFC aktiv ist und du könntest probieren das AFCD "disable=1" programmieren und schauen ob das hilft.
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  4. #4
    HaWe
    Gast
    Zitat Zitat von PICture Beitrag anzeigen
    @ basteluwe

    Ich vermute, dass der Fehler durch AFC ("Automatic Frequency Control" -> automatische steuerung der Frequenz) verursacht ist. Auf der "page 9" des Dateblattes habe ich im Register 04H das AFCD "default=0" gefunden. Das bedeutet, dass AFC aktiv ist und du könntest probieren das AFCD "disable=1" programmieren und schauen ob das hilft.
    Zitat Zitat von PICture Beitrag anzeigen
    Genau ! Änliches habe ich schon im Beitrag #3 erwähnt.
    hier sprichst du aber nur von AFC, das betrifft allerdings nicht die Frage, ob er überhaupt mit dem Scan fertig ist, was über das flag bit 8 im byte an 0x02 abgefragt werden kann.

    D.h., es ist ganz egal ob automatisch (AFC) oder manuelle Kanalwahl - er kann in beiden Fällen mit dem Scan fertig sein oder eben auch nicht, und wenn nicht, kann es in beiden Fällen zu den beobachteten Scanfrequenz-Abfragefehlern führen.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    131
    Zitat Zitat von shedepe Beitrag anzeigen
    Könntest du ungenau mal genauer spezifizieren. Habe deinen Code jetzt nicht gelesen. Aber prinzipiell: Wenn du einen Wert im EEPROM speicherst und nicht total viel Pech hast und dir kosmische Strahlung ein Bit kippen lässt, dann wirst du diesen Wert auch wieder auslesen.

    Dein Problem könnte eventuell daran liegen, dass du die Frequenz als int ausliest, die EEPROM library aber nur bytes erwartet.
    EEPROM.read() gibt aufjedenfall nur einzelne Bytes zurück.
    Mit Ungenauigkeit meinte ich, ich speichere z.B. den Wert 8820, was 88,20 MHz bedeutet. Bei Neustart tuned der chip aber z.B. auf 8800, also 88,0 MHz. Diese Abweichung ist nicht konstant! Manchmal stimmt der Wert auch.
    Ich weiß, dass EEPROM.read() bzw. EEPROM.write() nur bytes akzeptieren. Ich verstehe diese Seite aber so, das EEPROM.put() bzw. EEPROM.get() auch int oder float akzeptieren. Oder nicht?

    Gruß Uwe

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.10.2008
    Ort
    Kehnert
    Beiträge
    1.159
    Ich hatte mal ein Problem mit einem AVR, wollte mit der Zuweisung EEPROMVARIABLE = WERT abspeicher. Da musste ich
    feststellen, dass die erste EEPROM-Zelle warscheinlich nicht funktioniert. Nachdem ich eine EEPROM-Dummyfunktion im
    Quelltext davor reingeschrieben habe, lief es.
    VG Micha
    Was brauche ich für Werkzeug - in dieser Reihenfolge seht ihr es:
    Vorschlaghammer, Notebook, BASCOM, Lötequipment, Rohrzange, Bolzenschneider ...

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    .. musste ich feststellen, dass die erste EEPROM-Zelle warscheinlich nicht funktioniert. Nachdem ich eine EEPROM-Dummyfunktion ..
    Es ist sicher fünf Jahre her, da hatte ich dasselbe Problem festgestellt und etliche Hinweise auf ne Dummyfunktion gefunden. Seit der Zeit definiere*) ich wie folgt und habe keine Probleme:
    Code:
    // ###>>> Byte-Array, das erste Byte des EEPROMS gilt als nicht vertrauenswürdig
      uint8_t   firstByteDummy      EEMEM; 
      uint8_t   eeDUMMYbytes [100]  EEMEM;  // Dummies
      uint8_t   eeBytes [12]        EEMEM;  // ?? Allzweckbytes ??
      uint16_t  eeSrvoff[12]        EEMEM;  // Servo-Position - Offset
      u8    SVT[12][11]             EEMEM;  // Servotexte
    *) vgl. Kernighan-Ritchie, Vorwort zur deutschen Ausgabe
    Definition: Eigenschaft und Speicherplatz
    Deklaration: nur Eigenschaft
    Ciao sagt der JoeamBerg

  8. #8
    shedepe
    Gast
    Dass es einzelne Zellen defekt sind, kann passieren. Jedoch konnte ich keine Hinweise finden, dass Zelle 0 per se kaputt ist.

    fas EEPROM.put() bzw. EEPROM.get() auch int oder float akzeptieren
    Stimmt. Da Arduino C++ ist, kann man die Funktionen natürlich entsprechend überladen.

    Ein Dummy Read Write auf den EEPROM ist eine gute Idee.
    Ein weiterer Punkt auf den das Datenblatt hinweist, ist dass der EEPROM Inhalt korrumpiert werden kann, wenn man versucht bei zu geringer Versorgungsspannung zu lesen oder zu schreiben. Das ist in diesem Fall aber denke ich auszuschließen. (Nur der Vollständigkeit halber erwähnt)

Ähnliche Themen

  1. [ERLEDIGT] I2C Wert nach EEPROM 24C512 schreiben
    Von Bot-Builder im Forum C - Programmierung (GCC u.a.)
    Antworten: 7
    Letzter Beitrag: 13.03.2013, 08:34
  2. Edit: Wie Wert in EEPROM speichern?
    Von Maxxtro im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 24
    Letzter Beitrag: 23.02.2009, 10:03
  3. Bicore - ungenau
    Von boarter im Forum Elektronik
    Antworten: 0
    Letzter Beitrag: 29.06.2008, 01:15
  4. HEX Wert aus EEprom BINär umwandeln PICBASIC
    Von Robbersoft im Forum PIC Controller
    Antworten: 3
    Letzter Beitrag: 19.08.2007, 00:34
  5. Float Wert in EEPROM schreiben
    Von AlexAtRobo im Forum C - Programmierung (GCC u.a.)
    Antworten: 5
    Letzter Beitrag: 26.06.2006, 22:10

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen