eeprom question

Hi everyone,

I’m fairly new to arduino and have been slowly working on a hydroponic controller.

I have a LCD 16x2 shield and have the arduino controlling the backlight using analogWrite.

I have made a menu and when you go into the back light part of the menu i have the back light value show as a percentage. 0% off 100% fully on.

I have the up and down button controlling the back light percentage so the up button makes the back light brighter by 10%, and up again goes to 20% and so on. This worked great until i needed to save the value to the eeprom to save it when you go in and out of the back light menu.

What happens is when you go into the menu it shows for instance 10% brightness. you press the up button a few times to make it 50% brightness. when you exit the menu it save to the eeprom using EEPROM.update. But when you go back into the back light menu it will show 49%!

My question is how do i make it stay at 50% instead of 49%? maybe rounding or something?

I have posted the code so hopefully that will help show what im doing wrong?

//I have posed this to show what i did before the void setup and void loop
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int backLightPin = 10;

const int PHSetPointAddress = 0;
const int PHDoseTimeAddress = 8;
const int PHDoseIntervalAddress = 16;
const int CFSetPointAddress = 24;
const int CFDoseTimeAddress = 32;
const int CFDoseIntervalAddress = 40;
float backLightAddress = 48;

//End of stuff before void setup and loop

void BackLight()
{
  float backLight = 255; //initial backlight
  int Percentage = 0;
  backLight = EEPROM.read(backLightAddress);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Up and down keys");
  lcd.setCursor(0, 1);
  lcd.print("Backlight:");

  while (ReadKeypad() != 'L')
  {
    btn_push = ReadKeypad();
    WaitBtnRelease();
    if (btn_push == 'D')
    {
      backLight -= (255 - 0) * 0.1;
      if (backLight <= 0)
        backLight = 0;
    }
    else if (btn_push == 'U')
    {
      backLight += (255 - 0) * 0.1;
      if (backLight >= 255)
        backLight = 255;
    }
    analogWrite(backLightPin, backLight);
    Percentage = (backLight * 100) / 255;
    if (Percentage < 100)
    {
      lcd.print(" ");
    }
    if (Percentage < 10)
    {
      lcd.print(" ");
    }
    lcd.setCursor(0, 0);
    lcd.print("Up and down keys");
    lcd.setCursor(0, 1);
    lcd.print("Backlight:" + String(Percentage) + "%");
  }
  if (ReadKeypad() == 'L')
  {
    EEPROM.update(backLightAddress, backLight);
  }
}

As you can see i have left out some (pointless?) code that just shows how the buttons work and set up of the menu which i don’t think people need to see. Remember im just new to arduino so please be gentle and try to explain things like im a child haha.

float backLightAddress = 48;Why a float ? Is the address ever going to be anything but an integer ?

  float backLight = 255; //initial backlight
  int Percentage = 0;

This is just ass-backwards. The light level will always be treated as an int, regardless of your improper data type. The percentage, which can be a float, is constrained to be an int.

  while (ReadKeypad() != 'L')
  {
    btn_push = ReadKeypad();
    WaitBtnRelease();

As long as the value read from the keypad is not an ‘L’, read the keypad again… Why?

You seem to not understand that computers store data in binary, and that 0.1 is NOT a nice even number in binary. Adding 0.1 10 times will NOT give you 1.000000000000000.

Hi Godspeed.

What Paul said about floating point numbers. They have limited precision and can often only approximately represent even simple looking numbers. For example 0.1 will be represented as approx 0.1000000015 as float. So things probably start "going wrong" in the line backLight += (255 - 0) * 0.1.

Coincidentally, 25.5 is a number that is represented exactly as float, so had you used "backLight += 25.5" you may actually have avoided the issue.

This is largely irrelevant though. The main point to take away is just that you can't rely on floats to have an exact integer value, even when ideally you'd expect them to. So when converting to integer always use round() instead allowing the default cast to integer.

That is. Instead of: Percentage = (backLight * 100) / 255;

use

Percentage = round((backLight * 100) / 255);

BTW. The default casting to integer is to trunc. So 49.99999 would just become 49.

Thanks Stuart0!! that has got to be the best answer i have ever gotten off this forum!

I'm not the greatest with computers, and i have never done programming before until learning Arduino (the basics anyway). And i find all I ever get in reply's is people attacking you for not knowing what your doing or bad programming.

You explained in simple terms what I had wrong and how to fix it.

I did some research about the round() function because i was going to use that, but i couldn't find anything that would explain it in layman's terms, so thanks for showing me how! i really appreciate it!