My EEPROM data kept resetting =(

Hi,

The data in EEPROM kept resetting ever since i’ve added RTC1307 and its code. Here’s my code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <Arduino.h>
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>

unsigned int tvalue;
unsigned long total_tvalue;
unsigned long imp_count;
float wattpower=0.0;
unsigned int t_overflow_count;
unsigned int start;
float imp_period;
float culimp_period;
unsigned int display =0;

unsigned int timer_value;
float energy_KWH;
LiquidCrystal lcd(12,11,9,4,3,5);
const int swpin=7;
const int buttonPin=8;
int pinState=0;
int btn=0;
#define ledPin 13
int addr=0;
tmElements_t tm;


void setup() 
{
pinMode(swpin,INPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin,INPUT);
lcd.begin(16,2);

long four = EEPROM.read(addr);
long three = EEPROM.read(addr + 1);
long two = EEPROM.read(addr + 2);
long one = EEPROM.read(addr + 3);

//Return the recomposed long by using bitshift.
long imp_count = ((four << 0) & 0xFF) + ((three << 8 ) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);

energy_KWH = (float)(imp_count * 0.0005); // cumulative kWh value

noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0; 
  TCNT1=0;
  
    TIMSK1 |= (1 << TOIE1);    // enable timer interrupt
TCCR1B |= (1<<CS10);  
//CLKPR |=(1<<CLKPCE);
//CLKPR |=0x00;
	
    EIMSK |= (1 << INT0);     // Enable external interrupt INT0
  EICRA |= (1 << ISC01);    // Trigger INT0 on falling edge
  interrupts();             // enable all interrupts
  
  Serial.begin(9600);
  while (!Serial) ; // wait for serial
  delay(200);
}

void loop() 
{  
//tmElements_t tm;
  
  

 [glow=yellow,2,300]{ 
  pinState=digitalRead(buttonPin);
  if (pinState == LOW) 
  {
    delay(100);
    if(pinState == LOW)
    {
      for (int i = 0; i < 512; i++)  // write a 0 to all 512 bytes of the EEPROM
        {
          EEPROM.write(i, 0);
          lcd.setCursor(0,1);
          lcd.print("E : 0.0000");
          lcd.print(" kWh");
          //start=0;
        }
    }
     else 
        {
        }
    }
 } [/glow]
 btn=digitalRead(swpin);
 switch(btn) 
 {
  case LOW:
  lcd.clear();                //clears LCD screen
  lcd.setCursor(0,1);         // set the cursor to column 0, line 1
                              // (note: line 1 is the second row, since counting begins with 0):
  lcd.print("PWR : ");       // prints text onto assigned cursor position
  lcd.setCursor(5,1);
  lcd.print(wattpower,0);
  lcd.print(" W");

  break;  
 
  case HIGH:
  lcd.clear();                //clears LCD screen
  lcd.setCursor(0,1);         // set the cursor to column 0, line 1
                              // (note: line 1 is the second row, since counting begins with 0):
  lcd.print("E :");       // prints text onto assigned cursor position
  lcd.setCursor(3,1);
  lcd.print(energy_KWH,4);
  lcd.print(" kWh");

  break;                      //exit from loop
}
if (RTC.read(tm)) {
    lcd.setCursor(0,0);
    lcd.print(tm.Hour);
    lcd.print(':');
    lcd.print(tm.Minute);
    lcd.print(':');
    lcd.print(tm.Second);
    //Serial.print("  ");
    //Serial.print(tm.Day);
   // Serial.write('/');
   // Serial.print(tm.Month);
   // Serial.write('/');
   // Serial.print(tmYearToCalendar(tm.Year));
   // Serial.print("  ");
  } else {
    if (RTC.chipPresent()) {
      Serial.println("The DS1307 is stopped.  Please run the SetTime");
      Serial.println("example to initialize the time and begin running.");
      Serial.println();
    } else {
      Serial.println("DS1307 read error!  Please check the circuitry.");
      Serial.println();
    }
    delay(9000);
  }
//Serial.println(state);
delay(1000);  // put your main code here, to run repeatedly:

}


ISR(TIMER1_OVF_vect)
{

t_overflow_count++;
  digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
} 	

int address=0;
byte four ;
byte three ;
byte two ;
byte one ;

ISR(INT0_vect) {
if (start==0)
{
//*********************************
// reset timer values, and start
// timer
//*********************************
tvalue=0;
TCNT1=0;
TCCR1B |= (1<<CS10);       
start=1;
t_overflow_count=0;
}

else
{
display=1;   
  TCCR1B = 0;   	//stop timer
//*********************************
// compute power in watts
// and convert to ascii
tvalue=TCNT1;   	// get residual 16-bit timer0 value
total_tvalue = (((unsigned long) t_overflow_count) << 16) + tvalue;	  // compute total time elapsed in bits between 2 impulses
imp_period=(float)(total_tvalue * 0.0000000625);
culimp_period = culimp_period + imp_period;				        // compute total time elapsed in sec; 1 bit = 6us
wattpower= (1800)/imp_period;							            // power = (watt-sec/impulse period)
//sprintf (watt_buf, "%9.0f", wattpower);					         // convert floating point value to ascii for LCD display

//*********************************
// compute energy in kilowatts-hour
// and convert to ascii
//*********************************

long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);

//Return the recomposed long by using bitshift.
imp_count = ((four << 0) & 0xFF) + ((three << 8 ) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);

imp_count++;								
energy_KWH = (float)(imp_count * 0.0005); // cumulative kWh value
//sprintf (KWH_buf, "%9.3f", energy_KWH);   // here is sprintf prototype function usage  

if(imp_count > 2000000000)
{
  imp_count = 0;
}

//Decomposition from a long to 4 bytes by using bitshift.
      //One = Most significant -> Four = Least significant byte
       four = (imp_count & 0xFF);
       three = ((imp_count >> 8 ) & 0xFF);
       two = ((imp_count >> 16) & 0xFF);
       one = ((imp_count >> 24) & 0xFF);

      //Write the 4 bytes into the eeprom memory.
      EEPROM.write(address, four);
      EEPROM.write(address + 1, three);
      EEPROM.write(address + 2, two);
      EEPROM.write(address + 3, one);

//*********************************
// reset timer values, and restart
// timer
//*********************************
t_overflow_count=0;
tvalue=0;
TCNT1=0;
TCCR1B |= (1<<CS10); 

}
print2digits(tm.Hour);
Serial.print(':');
print2digits(tm.Minute);
Serial.print(':');
print2digits(tm.Second);
Serial.print("  ");
Serial.print(tm.Day);
Serial.write('/');
Serial.print(tm.Month);
Serial.write('/');
Serial.print(tmYearToCalendar(tm.Year));
Serial.print("       ");
Serial.print(energy_KWH,4);
Serial.print("kWh, ");
Serial.print(wattpower,0);
Serial.print("W, ");
Serial.println(culimp_period);
Serial.print("  ");


}
void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

And the serial monitor (before commenting out the clearing of EEPROM part)
00:00:00 0/0/1970 0.0010kWh, 0W, 0.00
00:00:00 0/0/1970 0.0005kWh, 1796W, 1.00
00:00:00 0/0/1970 0.0010kWh, 1814W, 1.99
09:38:54 22/7/2014 0.0015kWh, 1817W, 2.98
09:38:54 22/7/2014 0.0005kWh, 1814W, 3.98
09:38:54 22/7/2014 0.0010kWh, 1820W, 4.97
09:38:54 22/7/2014 0.0015kWh, 1820W, 5.96
09:38:57 22/7/2014 0.0020kWh, 1820W, 6.94
09:38:58 22/7/2014 0.0025kWh, 1814W, 7.94
09:38:58 22/7/2014 0.0005kWh, 1814W, 8.93
09:38:58 22/7/2014 0.0010kWh, 1814W, 9.92
09:39:02 22/7/2014 0.0015kWh, 1817W, 10.91
09:39:03 22/7/2014 0.0020kWh, 1814W, 11.90
09:39:04 22/7/2014 0.0025kWh, 1814W, 12.90
09:39:05 22/7/2014 0.0030kWh, 1814W, 13.89
09:39:06 22/7/2014 0.0035kWh, 1814W, 14.88
09:39:06 22/7/2014 0.0005kWh, 1814W, 15.87
09:39:06 22/7/2014 0.0010kWh, 1816W, 16.86
09:39:06 22/7/2014 0.0015kWh, 1814W, 17.85
09:39:09 22/7/2014 0.0020kWh, 1817W, 18.85
09:39:09 22/7/2014 0.0005kWh, 1814W, 19.84
09:39:09 22/7/2014 0.0010kWh, 1818W, 20.83
09:39:13 22/7/2014 0.0015kWh, 1815W, 21.82
09:39:13 22/7/2014 0.0020kWh, 1814W, 22.81
09:39:13 22/7/2014 0.0005kWh, 1814W, 23.80
09:39:13 22/7/2014 0.0010kWh, 1816W, 24.79
09:39:17 22/7/2014 0.0015kWh, 1820W, 25.78
09:39:18 22/7/2014 0.0020kWh, 1814W, 26.78
09:39:19 22/7/2014 0.0025kWh, 1814W, 27.77
09:39:20 22/7/2014 0.0030kWh, 1814W, 28.76
09:39:21 22/7/2014 0.0035kWh, 1814W, 29.75
09:39:22 22/7/2014 0.0040kWh, 1814W, 30.74
09:39:23 22/7/2014 0.0045kWh, 1814W, 31.74

*I can’t paste the screenshot of serial monitor, so i copied and pasted it.

But once I commented out the button for clearing EEPROM (highlighted part of code), the program works alright. But it’s a requirement to have this feature (button to clear EEPROM) for this project. What’s the problem with my code? Please help, Thanks a lot!

Hello,

You say you have the problem since you added the RTC... And then you say if you remove the code for the button, it works... So I'm a bit confused.

If the problem is your button code: How is your button wired? Are you sure you wired it so it reads LOW when pressed ?

Also, still about that button, you should debounce it properly: http://arduino.cc/en/Tutorial/Debounce

Or, as you are using many big delays, you should look into using interrupts to catch every button presses, because actually your code won't catch button presses while the code is delayed... Or yet better, get rid of those delays and use non blocking code instead :slight_smile:

Do you have pull up or pull down resistors on the button pin?

It's easiest to declare the button pin as INPUT_PULLUP.

Which Time and DS1307RTC library are you using ?
Is the Time library doing things ?
Are you using a cheap DS1307 from Ebay ? You can expect anything from them (except working normal).

Is something else using EEPROM ?

Can you move some of the strings to flash ?
Like this with the F() macro: Serial.println(F("DS1307 read error! Please check the circuitry."));
If that changes it, there is something with the variable and ram.

You are making the compiler go wondering in circles, banging its head to wall about what users come up with this time.

unsigned long imp_count;
energy_KWH = (float)(imp_count * 0.0005);

Do that calculation in float, or in integers, or whatever. Don't mix it like that.
You can do the calculation with floats:

unsigned long imp_count;
energy_KWH = ( (float)imp_count * 0.0005 );

Hi,

Thanks for the reply.

You say you have the probelm since you added the RTC… And then you say if you remove the code for the button, it works… So I’m a bit confused.

Sorry, I understand it’s confusing. It confused me too. Before i added the RTC1307, the code works totally the way i wanted. But after I’ve added the RTC, the problem started to surface and after rounds of figuring where’s the problem, i suspected it’s the EEPROM. Since the accumulated values were stored in the EEPROM, there’s no way the value kept resetting. Then i commented out the (clearing of EEPROM) part, my the problem is gone however, it’s a requirement for this project.

If the problem is your button code: How is your button wired? Are you sure you wired it so it reads LOW when pressed ?

Below is the button connection.

Hi,

Thanks for all of your replies.

Yes, I've downloaded the time library and used it to set and read time. I'm using the adafruit breakout kit for RTC. From what i know, the EEPROM is only for storing the accumulated value. (I didn't write all of the code, it's a continued project from previous student)

I'll try all of your suggestions and get back with the results. Thanks again! :slight_smile:

Can you move some of the strings to flash ?
Like this with the F() macro: Serial.println(F("DS1307 read error! Please check the circuitry."));
If that changes it, there is something with the variable and ram.

There's no visible changes after i've uploaded it, so i suppose that there's nothing wrong?

I may be wrong, but it appears to me that your button wiring is incorrect, it should be like this (in your case, active low):

Your schematic shows an Arduino? pin? that is grounded directly...
Do you have the board wired as per the drawing? or is the switch symbol incorrect?
@ Guix, Which pin on an Arduino is PIC?

Doc

The button pin wiring the way you show it always connects the button pin to ground.

I would suggest wiring one side of the button to ground, and connect the other side to the input pin configured for INPUT_PULLUP.

When the button is closed, it will pull the input pin low.

Docedison:
@ Guix, Which pin on an Arduino is PIC?

:slight_smile: Sorry but that's the first picture that I found, showing difference between active low and active high.

When I asked: "Which Time and DS1307RTC library are you using ?", I ment that you should give links to the actual library that you have imported :stuck_out_tongue:
Some Time libraries have time alarms that use the EEPROM of the Arduino.

Hi,

Your schematic shows an Arduino? pin? that is grounded directly...
Do you have the board wired as per the drawing? or is the switch symbol incorrect?

I didn't know that i shouldn't connect the pin directly to ground. I've changed accordingly to what Guix had shown (Thanks Guix)

When I asked: "Which Time and DS1307RTC library are you using ?", I ment that you should give links to the actual library that you have imported smiley-razz
Some Time libraries have time alarms that use the EEPROM of the Arduino.

I got the links from kcranley @ http://forum.arduino.cc/index.phpPHPSESSID=9bjj3hi0ai8ov6ntpoutebm4a6&topic=185894.15

Download Time.zip from Time Library, Timekeeping and Time/Date Manipulation on Teensy
Download TimeAlarms.zip from http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
Download DS1307RTC.zip from http://www.pjrc.com/teensy/td_libs_DS1307RTC.html

I've changed accordingly to all of your suggestions but the problem still persist. I'll improve further and get back with the results soon. Really thanks a lot for all of your helpful suggestions.

I don't know anymore what could the be the cause. I took a look at those libraries, but they don't use EEPROM.

The wiring of some 4 leg buttons can be confusing because two of the four legs are always connected to each other . If you can confirm the operational behavior or your button with a multimeter it would be best. I think that if you wire diagonally across the button then it will always be open when not pressed, and it will closed the circuit when pressed.