hi,
using the eepromex.h library, as i want an easy way to write larger numbers into a power off / failure state.
using a flow meter to read millilitres, the numbers can get reasonably high, but every single unit that i measure (pint) is 568ml, a keg holds 22 gallons, or 176 pints, or 99968ml, and the keg gets changed 8 times a week, 799744, and im allowing a few weeks worth of data collection, (8 weeks) 6397952, or 26 weeks ( 20,793,344ml )
i opted for unsigned long as the integer for the failsafes, and found that the standard eeprom needs a lot of clever additions to record this.
using the eepromex library makes the large numbers much easier to use.
i intend to use the eeprom update function once every 15 mins, as for 12 hours a day, the system will be recording the same number and will cause needless writes (being aware of the 100k cycles that are available to the chip)... this code for testing purposes does an update every 2 seconds, but will be changed.
i have the system operating nicely, im playing with the flow, resetting, seeing the saved numbers on the serial monitor and on the display and feeling quite chuffed with myself...
...and after a while i get a "maximum number of writes"
ive stuck a counter into the code, and this magic number happens after 100 writes / updates, and the system stops recording number changes.
how do i get around this?
oh, if i restart the process, then everything starts perfectly fine.
http://playground.arduino.cc/Code/EEPROMex
// Liquid flow rate sensor
// Measure the liquid/water flow rate using this code.
// Connect Vcc and Gnd of sensor to arduino, and the signal line to arduino digital pin 2.
#include "U8glib.h"
//#include "EEPROM.h"
#include "EEPROMex.h"
// adding the oled screen
U8GLIB_SSD1306_128X64 u8g(10, 9, 12);
byte statusLed = 13;
byte sensorInterrupt = 0; // 0 = digital pin 2
byte sensorPin = 2;
unsigned int eepromAddress = 0;
unsigned int eepromSaveTime = 5000;
unsigned long currentTime;
int writeNumber = 0;
// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;
volatile byte pulseCount;
float flowRate;
unsigned int flowMillilitres;
unsigned long totalMillilitres;
unsigned int pints;
unsigned long oldTime;
unsigned long oldSaveTime;
void setup()
{
// flip screen, if required
// u8g.setRot180();
// set font for oled
u8g.setFont(u8g_font_unifont);
// Initialize a serial connection for reporting values to the host
Serial.begin(9600);
// Set up the status LED line as an output
pinMode(statusLed, OUTPUT);
digitalWrite(statusLed, HIGH); // We have an active-low LED attached
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);
pulseCount = 0;
flowRate = 0.0;
flowMillilitres = 0;
oldTime = 0;
oldSaveTime = 0;
totalMillilitres = EEPROM.readLong(eepromAddress);
pints = totalMillilitres / 568;
// The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
// Configured to trigger on a FALLING state change (transition from HIGH
// state to LOW state)
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
pinMode(13, OUTPUT);
}
/**
Main program loop
*/
void loop() {
currentTime = millis();
if ( (currentTime - oldTime) > 1000) { // Only process counters once per second
// Disable the interrupt while calculating flow rate and sending the value to the host
detachInterrupt(sensorInterrupt);
// take a reading every second
flowRate = ((1000.0 / (currentTime - oldTime)) * pulseCount) / calibrationFactor;
// reset the timer
oldTime = currentTime;
// convert to litres
flowMillilitres = (flowRate / 60) * 1000;
// Add the millilitres passed in this second to the cumulative total
totalMillilitres += flowMillilitres;
// convert to pints
pints = totalMillilitres / 568;
unsigned int frac;
// Print the flow rate for this second in litres / minute
Serial.print("Flow rate: "); Serial.print(int(flowRate)); Serial.print("."); frac = (flowRate - int(flowRate)) * 10; Serial.print(frac, DEC); Serial.print("L/min");
Serial.print(" Current Flow: "); Serial.print(flowMillilitres); Serial.print("mL/Sec");
Serial.print(" Total: "); Serial.print(totalMillilitres); Serial.print("mL");
Serial.print(" Pints: "); Serial.println(pints);
// picture loop
u8g.firstPage();
do {
draw();
} while (u8g.nextPage() );
// Reset the pulse counter so we can start incrementing again
pulseCount = 0;
// Enable the interrupt again now that we've finished sending output
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
} // end of timed loop (1000)
// manual reset
if (Serial.available()) {
char ch = Serial.read();
if (ch == 'r') {
totalMillilitres = 0;
EEPROM.writeLong(eepromAddress, totalMillilitres);
Serial.println("*** Manual Reset ***");
}
}
// if enough time has passed, save the current reading
if ( (currentTime - oldSaveTime) > eepromSaveTime) {
// write the value to the eeprom
//EEPROM.write(eepromAddress, totalMillilitres);
// update the address in the eeprom if different
EEPROM.updateLong(eepromAddress, totalMillilitres);
Serial.print("data saved: "); Serial.print(EEPROM.readLong(eepromAddress)); Serial.print(" :: "); Serial.print(writeNumber);
Serial.println();
writeNumber++;
oldSaveTime = currentTime;
} // end of timed loop (eepromSaveTime)
}// end of void loop
void pulseCounter() {
// Increment the pulse counter
pulseCount++;
}
void draw() {
u8g.setPrintPos(0, 20);
u8g.print("Pints: "); u8g.print(pints);
u8g.setPrintPos(0, 40);
u8g.print("Flow: "); u8g.print(flowMillilitres); u8g.print(" ml/s ");
u8g.setPrintPos(60, 60);
u8g.print("FlowZero");
}