EEPROM niet werken

ik wil twee verschillende waarden naar de EEPROM schijven maar de holesMAX werkt wel en de times werkt niet.
hoe kan ik dit oplossen?


#include <Wire.h>    // Bibliotheek voor I2C communicatie
#include <Adafruit_GFX.h>  // Bibliotheek voor grafische functies
#include <Adafruit_SSD1306.h>  // Bibliotheek voor SSD1306 OLED display
#include <EEPROM.h>  // Bibliotheek voor EEPROM geheugen

#define SCREEN_WIDTH 128  // OLED display breedte, in pixels
#define SCREEN_HEIGHT 64  // OLED display hoogte, in pixels
#define OLED_RESET -1  // Reset pin # (of -1 als de Arduino reset pin wordt gedeeld)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // Initialiseren van het OLED display

const float holesPerRevolution = 8;  // Aantal gaten per omwenteling
const float d = 0.095;  // Diameter van het wiel in meters
const int resetKnop = 3;  // De knop die de afstand reset

float afstand = 0.0;  // Afstand in kilometers
float rpm = 0.0;  // Omwentelingen per minuut
float snelheid = 0.0;  // Snelheid in km/u
unsigned long millisBefore = 0;  // Opslaan van de laatste update tijd
int holes = 0;  // Aantal gaten sinds de laatste update (moet volatile zijn voor gebruik in een interrupt)
volatile int holesMAX = 0; //maximum 20 000 gaten
long holesTOT = 0;  // Totaal aantal gaten
volatile long times = 0;  // het aantal keer dat holesMAX de 20 000 heeft gehaald

int lastButtonState = 0;  // De vorige status van de knop
int ButtonState = 0;  // De huidige status van de knop

void setup() {
  pinMode(resetKnop, INPUT);  // Instellen van de reset knop als input
  eeprom();  // Lezen van de totale gaten uit de EEPROM

  // Initialiseren van het SSD1306 OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Adres 0x3C voor 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);  // Blijven hangen als het display niet kan worden geïnitialiseerd
  }
  display.clearDisplay();  // Display wissen
  display.setTextSize(1);  // Tekstgrootte instellen
  display.setTextColor(SSD1306_WHITE);  // Witte tekst instellen
  
  Serial.begin(9600);  // Start de seriële communicatie op 9600 baud
  display.setCursor(0, 0);  // Cursor positie instellen
  display.print("Speed Sensor");  // Tekst weergeven op display
  pinMode(2, INPUT);  // Instellen van pin 2 als input
  attachInterrupt(digitalPinToInterrupt(2), count, FALLING);  // Interrupt instellen voor pin 2, activeert bij vallende flank
  display.clearDisplay();  // Display wissen
  millisBefore = millis();  // Opslaan van de huidige tijd in millisBefore
}

void loop() {
  ButtonState = digitalRead(resetKnop);  // Lezen van de status van de reset knop
  if (millis() - millisBefore > 500) {  // Als er meer dan 500 milliseconden zijn verstreken
    rpm = (holes / holesPerRevolution) * 120;  // Berekenen van de RPM
    millisBefore = millis();  // Reset de timer
    holes = 0;  // Reset het aantal gaten
  }
  snelheid = ((rpm * PI * d) / 60) * 3.6;  // Snelheid berekenen en omzetten naar km/u
  afstand = ((holesTOT / holesPerRevolution) * d * PI) / 1000;  // Afstand berekenen en omzetten naar kilometers
  print_to_OLED();  // Functie aanroepen om gegevens naar het OLED display te printen
  print_to_Serial(); // Functie aanroepen om gegevens naar de seriële monitor te printen

  if (lastButtonState != ButtonState) {  // Als de knop status is veranderd
    holesMAX = 0;  // Reset het totaal aantal gaten
    times = 0;
    holesTOT = 0;
    EEPROM.put(1, 0);  // Schrijf 0 naar EEPROM
    EEPROM.put(0, 0);  // Schrijf 0 naar EEPROM
  }
  lastButtonState = ButtonState;  // Update de laatste knop status
}

void print_to_OLED() {
  /*display.clearDisplay();  // Display wissen
  display.setCursor(0, 0);  // Cursor positie instellen
  display.print("Holes: ");  // Tekst printen
  display.print(holes);  // Het aantal gaten printen
  display.setCursor(0, 10);  // Cursor verplaatsen
  display.print("RPM: ");  // Tekst printen
  display.print(rpm, 1);  // De RPM printen met één decimaal
  display.setCursor(0, 20);  // Cursor verplaatsen
  display.print("V: ");  // Tekst printen
  display.print(snelheid, 1);  // De snelheid printen met één decimaal
  display.print(" km/h");  // Eenheid printen
  display.setCursor(0, 30);  // Cursor verplaatsen
  display.print(afstand, 3);  // De afstand printen met drie decimalen
  display.print(" km");  // Eenheid printen
  display.setCursor(0, 40);  // Cursor verplaatsen
  display.print("Total Holes: ");  // Tekst printen
  display.print(holesTOT);  // Het totaal aantal gaten printen
  display.display();  // Inhoud naar het display sturen
  */
}

void print_to_Serial() {
  /*Serial.print("Holes: ");
  Serial.println(holes);
  Serial.print("RPM: ");
  Serial.println(rpm, 1);
  Serial.print("V: ");
  Serial.print(snelheid, 1);
  Serial.println(" km/h");
  Serial.print("Afstand: ");
  Serial.print(afstand, 3);
  Serial.println(" km");*/
  Serial.print("Total Holes: ");
  Serial.println(holesMAX);
}

void count() {
  holes++;  // Verhoog het aantal gaten
  holesMAX = holesMAX  + 1000;  // Verhoog het totaal aantal gaten
  if (holesMAX >= 20000){
    holesMAX = 0;
    times++;
    EEPROM.put(0, times);
  }
  holesTOT = holesMAX + (20000* times);
  EEPROM.put(1, holesMAX); 
  
}

void eeprom() {
  // Lees het totaal aantal gaten uit de EEPROM
  EEPROM.get(1, holesMAX);  
  EEPROM.get(0, times);
  holesTOT = holesMAX + (20000* times);  // Zet het totaal aantal gaten op de opgeslagen waarde
  
  
}

Het probleem is allicht dat de adressering in bytes is, maar je datatype is groter; in het geval van 'holesMax' is het twee bytes (int = 16 bits = 2 bytes), in het geval van variabele 'times' is het 4 bytes (long = 32 bits = 4 bytes).
Dus als je eerst een 2-bytes variabele schrijft naar adres 0 en vervolgens iets wegschrijft naar adres 1, dan overschrijf je sowieso de helft van de eerste variabele, want die beslaat zelf al bytes 0 + 1.

Bij het teruglezen heb je een soortgelijk probleem met overlappende variabelen in je EEPROM.

Begin dus eens met het adres in het EEPROM van holesMax te veranderen naar 2 i.p.v. 1 en kijk hoe dat gaat.

Ik heb verder niet naar de rest van je code gekeken; het is goed mogelijk dat je nog andere problemen hebt.

thx,
het werkte niet met 2 maar ik heb het op 3 gezet en nu werkt het wel.

Hallo @tobeser

Bedankt voor het gebruik van code tags in je eerste post :+1:
Ik heb je vraag verplaatst naar de Nederlandse sectie van het forum. In de Engelstalig secties dien je je vraag in het Engels te stellen :wink:


Je int variabele is twee bytes (ervan uitgaande dat je een 8-bit processor gebruikt (bv Uno)) en een long is vier bytes.

Dus adres 0 voor je times en adres 4 voor je holesMax.

Wat hints:
Gebruik geen hard gecodeerde adressen; op hoeveel plekken heb je die '1' naar '5' moeten veranderen?

Je bent beter af met iets als

// eeprom address for times
uint16_t eepromTimes = 0;
// eeprom address for holesMax
// BUG fix
//uint16_t holesMax = sizeof(eepromTimes);
uint16_t eepromHolesMax = sizeof(eepromTimes);

En gebruik b.v.

eeprom.put(eepromTimes, times);

Als dit een configuratie is kun je overwegen een struct te gebruiken.

struct CONFIG
{
  int holesMax;
  long times;
};

CONFIG cfg;

Je kunt dat in een (1) keer opslaan en terug lezen met

eeprom.put(0, cfg);
eeprom.get(0, cfg);

De velden in de struct kun je benaderen met een punt

Serial.print(cfg.times);
Serial.print(cfg.holesMax);

Opmerking:
Ik heb geen acht geslagen op de volgorde waarmee je originele programma werkte.

2 Likes

ik heb het 3 keer moeten vervangen.
die nieuwe code die jij zegt snap ik niet helemaal dus kan je die al invullen in mijn code als je tijd hebt?
of uitleggen hoe ik het juist moet doen.

In sterretje's code is iets fout gegaan met de code tags (die hij net als ik zou doen, vermoedelijk handmatig heeft ingevuld), maar dat heeft hij inmiddels opgelost.

Ik vermoed dat je (of jullie) nog niet zo ver bent/zijn dat je met stuct werkt.

In de eerste code die sterretje liet zien, maakt hij gebruik van het beginadres 0, en daar reserveert hij dan de ruimte voor jouw Times variabele met die nieuwe variabele eepromTimes van het type uint16_t.
Daarna kijkt hij hoe groot Times is met de functie sizeof, en reserveert dan een volgende ruimte met de variabele met de naam eepromHolesMax.
Nu kun je eepromTimes en eepromHolesMax gebruiken wanneer je je eeprom gaat benaderen, en gebruik je die variabelen in plaats van een vast getal.
Dat heeft dus als voordeel dat de gereserveerde ruimte mee verandert met de grootte van je variabele.
Wanneer die grootte van de variabele niet zal veranderen en/of je niet dat niet wil gebruiken, is het toch een goed idee om de variabelen eepromTimes en eepromHolesMax te gaan gebruiken, zodat je dat niet vaker hoeft aan te passen in je code, en daar dan ook minder snel fouten mee zult gaan maken.
Let er op dat wanneer je commentaar regels gebruikt, en je je code verandert, ook de commentaren daarmee overeen laat stemmen.
Wanneer dit voor een schoolopdracht zou zijn, is dat extra belangrijk.

Ik heb het nu toegepast maar als ik mijn arduino zonder stroom zet en dan terug insteek dan leest hij bij times uit de EEPROM bijna een miljard.
hoe kan dat?

Laat je vernieuwde programma maar zien (in een nieuw antwoord).

Dit is de code die ik nu heb.
ik heb het commentaar nog niet aangepast

#include <Wire.h>    // Bibliotheek voor I2C communicatie
#include <Adafruit_GFX.h>  // Bibliotheek voor grafische functies
#include <Adafruit_SSD1306.h>  // Bibliotheek voor SSD1306 OLED display
#include <EEPROM.h>  // Bibliotheek voor EEPROM geheugen

#define SCREEN_WIDTH 128  // OLED display breedte, in pixels
#define SCREEN_HEIGHT 64  // OLED display hoogte, in pixels
#define OLED_RESET -1  // Reset pin # (of -1 als de Arduino reset pin wordt gedeeld)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // Initialiseren van het OLED display

const float holesPerRevolution = 8;  // Aantal gaten per omwenteling
const float d = 0.095;  // Diameter van het wiel in meters
const int resetKnop = 3;  // De knop die de afstand reset

float afstand = 0.0;  // Afstand in kilometers
float rpm = 0.0;  // Omwentelingen per minuut
float snelheid = 0.0;  // Snelheid in km/u
unsigned long millisBefore = 0;  // Opslaan van de laatste update tijd
int holes = 0;  // Aantal gaten sinds de laatste update (moet volatile zijn voor gebruik in een interrupt)
volatile int holesMAX = 0; //maximum 20 000 gaten
long holesTOT = 0;  // Totaal aantal gaten
volatile long times = 0;  // het aantal keer dat holesMAX de 20 000 heeft gehaald

int lastButtonState = 0;  // De vorige status van de knop
int ButtonState = 0;  // De huidige status van de knop

// eeprom address for times
uint16_t eepromTimes = 0;
// eeprom address for holesMax
// BUG fix
//uint16_t holesMax = sizeof(eepromTimes);
uint16_t eepromHolesMax = sizeof(eepromTimes);

void setup() {
  pinMode(resetKnop, INPUT);  // Instellen van de reset knop als input
  eeprom();  // Lezen van de totale gaten uit de EEPROM

  // Initialiseren van het SSD1306 OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Adres 0x3C voor 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);  // Blijven hangen als het display niet kan worden geïnitialiseerd
  }
  display.clearDisplay();  // Display wissen
  display.setTextSize(1);  // Tekstgrootte instellen
  display.setTextColor(SSD1306_WHITE);  // Witte tekst instellen
  
  Serial.begin(9600);  // Start de seriële communicatie op 9600 baud
  display.setCursor(0, 0);  // Cursor positie instellen
  display.print("Speed Sensor");  // Tekst weergeven op display
  pinMode(2, INPUT);  // Instellen van pin 2 als input
  attachInterrupt(digitalPinToInterrupt(2), count, FALLING);  // Interrupt instellen voor pin 2, activeert bij vallende flank
  display.clearDisplay();  // Display wissen
  millisBefore = millis();  // Opslaan van de huidige tijd in millisBefore
}

void loop() {
  ButtonState = digitalRead(resetKnop);  // Lezen van de status van de reset knop
  if (millis() - millisBefore > 500) {  // Als er meer dan 500 milliseconden zijn verstreken
    rpm = (holes / holesPerRevolution) * 120;  // Berekenen van de RPM
    millisBefore = millis();  // Reset de timer
    holes = 0;  // Reset het aantal gaten
  }
  snelheid = ((rpm * PI * d) / 60) * 3.6;  // Snelheid berekenen en omzetten naar km/u
  afstand = ((holesTOT / holesPerRevolution) * d * PI) / 1000;  // Afstand berekenen en omzetten naar kilometers
  print_to_OLED();  // Functie aanroepen om gegevens naar het OLED display te printen
  print_to_Serial(); // Functie aanroepen om gegevens naar de seriële monitor te printen

  if (lastButtonState != ButtonState) {  // Als de knop status is veranderd
    holesMAX = 0;  // Reset het totaal aantal gaten
    times = 0;
    holesTOT = 0;
    EEPROM.put(eepromHolesMax, 0);  // Schrijf 0 naar EEPROM
    EEPROM.put(eepromTimes, 0);  // Schrijf 0 naar EEPROM
  }
  lastButtonState = ButtonState;  // Update de laatste knop status
}

void print_to_OLED() {
  display.clearDisplay();  // Display wissen
  display.setCursor(0, 0);  // Cursor positie instellen
  display.print("Holes: ");  // Tekst printen
  display.print(holes);  // Het aantal gaten printen
  display.setCursor(0, 10);  // Cursor verplaatsen
  display.print("RPM: ");  // Tekst printen
  display.print(rpm, 1);  // De RPM printen met één decimaal
  display.setCursor(0, 20);  // Cursor verplaatsen
  display.print("V: ");  // Tekst printen
  display.print(snelheid, 1);  // De snelheid printen met één decimaal
  display.print(" km/h");  // Eenheid printen
  display.setCursor(0, 30);  // Cursor verplaatsen
  display.print(afstand, 3);  // De afstand printen met drie decimalen
  display.print(" km");  // Eenheid printen
  display.setCursor(0, 40);  // Cursor verplaatsen
  display.print("Total Holes: ");  // Tekst printen
  display.print(holesTOT);  // Het totaal aantal gaten printen
  display.setCursor(0, 55);  // Cursor verplaatsen
  display.print(times);  // Tekst printen
  display.display();  // Inhoud naar het display sturen
  
}

void print_to_Serial() {
  Serial.print("Holes: ");
  Serial.println(holes);
  Serial.print("RPM: ");
  Serial.println(rpm, 1);
  Serial.print("V: ");
  Serial.print(snelheid, 1);
  Serial.println(" km/h");
  Serial.print("Afstand: ");
  Serial.print(afstand, 3);
  Serial.println(" km");
  Serial.print("Total Holes: ");
  Serial.println(holesMAX);
}

void count() {
  holes++;  // Verhoog het aantal gaten
  holesMAX++;  // Verhoog het totaal aantal gaten
  if (holesMAX == 20000){
    holesMAX = 0;
    times++;
    EEPROM.put(eepromTimes, times);
  }
  holesTOT = holesMAX + (20000* times);
  EEPROM.put(eepromHolesMax, holesMAX); 
  
}

void eeprom() {
  // Lees het totaal aantal gaten uit de EEPROM
  EEPROM.get(eepromHolesMax, holesMAX);  
  EEPROM.get(eepromTimes, times);
  holesTOT = holesMAX + (20000* times);  // Zet het totaal aantal gaten op de opgeslagen waarde
  
  
}

Een 'vers' EEPROM dat nooit is beschreven bevat doorgaans allemaal binaire 1-en. Oftewel, elke byte heeft de waarde 255, elke (unsigned) 16-bit integer 65535, enz. Het probleem zal zich 'vanzelf' oplossen als je eenmaal de juiste waarden in het EEPROM schrijft.

Ik denk dat dat komt omdat ik de volgorde van de variabelen in de EEPROM omgedraaid heb. Zie dit commentaar in het eerdere antwoord.

iedereen bedank om hij te helpen.
voorlopig werkt alles hoe ik het wil.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.