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.
Bedankt voor het gebruik van code tags in je eerste post
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
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
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?
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.