Garbage Display on LCD.

I am trying to build an Exposure Meter with Arduino Uno. The project is supposed to take values for several parameters as input and give the results for four other parameters based on the inputs given. My code ios given here.

#include <LiquidCrystal.h>

const int rs = 12, en = 11, d4 = 10, d5 = 9, d6 = 8, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

#define upmenu 2
#define downmenu 3
#define upval 4
#define downval 5
#define setbutton 6
#define sensorpin A1

unsigned int i = 0;

class parameters{
  
  private:

  String head;
  String para;
  int* int_vals;
  float* float_vals;
  int len;
  int final_val;
  float final_valdec;
  
  public:

  parameters(String n, String x, int* a, int l){
    head = n;
    para = x;
    int_vals = a;
    len = l;
    final_val = *a;
  }
  parameters(String n, String x, float* b, int l){
    head = n;
    para = x;
    float_vals = b;
    len = l;
    final_valdec = *(b+3);
  }
  void getName(){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(head);
  }
  int getIntval(int i){
    i = i%len;
    lcd.setCursor(0,1);
    lcd.print(para+" = ");
    lcd.setCursor(7,1);
    lcd.print(*(int_vals+i));
    lcd.setCursor(12,1);
    lcd.print(final_val);
    return *(int_vals+i);
  }
  float getDecval(int i){
    i = i%len;
    lcd.setCursor(0,1);
    lcd.print(para+" = ");
    lcd.setCursor(7,1);
    lcd.print(*(float_vals+i));
    lcd.setCursor(12,1);
    lcd.print(final_valdec);
    return *(float_vals+i);
  }
  int getLen(){
    return len;
  }
  void setInt(int x){
    final_val = x;
  }
  void setDec(float *b, int x){
    final_valdec = *(b+x);
  }
  int getFinal(){
    return final_val;
  }
  float* getFinal_dec(){
    return &final_valdec;
  }
};

int isoval[] = {12, 24, 40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 530, 640, 800, 1020, 1250, 1600};
int soval[] = {5, 10, 15, 20, 25, 45, 60, 75, 90, 144, 160, 165, 170, 172, 180, 270, 300};
int ssval[] = {1, 2, 4, 8, 15, 30, 48, 50, 60, 100, 125, 250, 500, 1000, 2000, 2500, 4000, 5000, 10000, 20000};
const int sdVal = 360;
int fpsval[] = {6, 12, 18, 24, 30, 36, 48, 72, 96, 144, 192};
float ffval[] = {.33, .5, .67, 1, 1.33, 1.5, 1.67, 2, 2.33, 2.5, 2.67, 3};

parameters iso = parameters("ISO-SENSITIVITY","ISO", isoval, 20);
parameters so = parameters("SHUTTER OPENING","SO", soval, 17);
parameters ss = parameters("SHUTTER SPEED","SS", ssval, 20);
parameters fps = parameters("FRAME PER SECOND","FPS", fpsval, 11);
parameters ff = parameters("FILTER FACTOR","FF", ffval, 12);

parameters opts[] = {iso, so, ss, fps, ff};

float aperture;
float lux;
float footcandle;
float ev;


float reading;
int menu_pos = 0;
int val_pos = 0;
int ff_pos = 0;

void menuchange(int up, int down);
void valuechange(int up, int down);
void showVals(int x);
void disp(int x, int y);
void setValue(int x, int y);
void op();
float sensorop(){
  float temp = analogRead(sensorpin);
  return temp;
}

void setup(){
  lcd.begin(16, 2);
  lcd.clear();
  pinMode(upmenu, INPUT_PULLUP);
  pinMode(downmenu, INPUT_PULLUP);
  pinMode(upval, INPUT_PULLUP);
  pinMode(downval, INPUT_PULLUP);
  pinMode(setbutton, INPUT_PULLUP);
  pinMode(sensorpin, INPUT);
  lcd.setCursor(1,0);
  lcd.print("Exposure Meter");
}

void loop(){
  int menuup = digitalRead(upmenu);
  int menudown = digitalRead(downmenu);
  int valup = digitalRead(upval);
  int valdown = digitalRead(downval);
  int set = digitalRead(setbutton);  
  if(menuup^menudown){    //If asked to change the menu
    menuchange(menuup, menudown);
  }
  if(valup^valdown){   //If asked to change the value of a parmeter
    valuechange(valup, valdown);
  }
  if(set){ //set value for a parameter
    setValue(menu_pos%9, val_pos%(opts[menu_pos%9].getLen()));
  }
  reading = sensorop();
  delay(200);
}

void menuchange(int up, int down){
  if(up){
    menu_pos++;   
  }
  if(down && menu_pos>0){
    menu_pos--;
  }
  disp(menu_pos%9, val_pos%(opts[menu_pos%9].getLen()));
  delay(200);
}

void valuechange(int up, int down){
  if(up){
    val_pos++;
  }
  if(down && val_pos>0){
    val_pos--;
  }
  disp(menu_pos%9, val_pos%(opts[menu_pos%9].getLen()));
  delay(200);
}

void setValue(int x, int y){
  if(x<=3) opts[x].setInt(opts[x].getIntval(y));
  if(x==4){
      ff_pos = y;
      opts[x].getDecval(ff_pos);
  }
}

void showVals(int x, int y){
  int menuup = digitalRead(upmenu);
  int menudown = digitalRead(downmenu);
  if(x<=3) opts[x].getIntval(y);
  if(x==4) opts[x].getDecval(y);
  if(x==5 || x==6){
    lcd.noDisplay();
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    int isof = opts[0].getFinal();
    int sof = opts[1].getFinal();
    int ssf = opts[2].getFinal();
    int fpsf = opts[3].getFinal();
    float fff=ffval[ff_pos];
    delay(100);
    lcd.display();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LUX");
    lcd.setCursor(5,0);
    lcd.print("FOOTCANDLE");
    lcd.setCursor(0,1);
    lcd.print(lux);
    lcd.setCursor(8,1);
    lcd.print(footcandle);
  }
  if(x==7 ||x==8){
    lcd.noDisplay();
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    int isof = opts[0].getFinal();
    int sof = opts[1].getFinal();
    int ssf = opts[2].getFinal();
    int fpsf = opts[3].getFinal();
    float fff=ffval[ff_pos];
    aperture=isof*footcandle*sof*2;
    aperture=aperture/(float(sdVal)*float(ssf)*float(fpsf)*fff);
    aperture=sqrt(aperture);
    ev=log(aperture*aperture*float(ssf))/log(2);
    delay(100);
    lcd.display();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("APERTURE");
    lcd.setCursor(11,0);
    lcd.print("EV");
    lcd.setCursor(3,1);
    lcd.print(aperture);
    lcd.setCursor(11,1);
    lcd.print(ev);
  }
}

void disp(int menu_pos, int val_pos){
  opts[menu_pos].getName();
  showVals(menu_pos, val_pos);
}

Now the problem is after setting the values when I go in the output options the LCD shows some garbage display before showing the desired output. I seek help to eliminate this problem

Did your initial "hello world" sketch display correctly on the LCD?

What do mean by go in the output options?

Setup looks okey. Does the textExposure Meter appear on the display?

Now the problem is after setting the values when I go in the output options the LCD shows some garbage display before showing the desired output.

I see this code which writes to the lcd after menu setting. I'm not clear about everything in the class parameters, but for trouble shooting try this function with .getName() commented out, and see if that is causing the "garbage display" before the correct display given with showVals().

void disp(int menu_pos, int val_pos){
  //opts[menu_pos].getName();
  showVals(menu_pos, val_pos);
}

Railroader:
What do mean by

go in the output options

?

Setup looks okey. Does the text

Exposure Meter

appear on the display?

If you have a look in the code, I have certain parameters like ISO, SO, SS, FPS and FF which have a certain range of values. In the input part I am going to each of the parameters and choosing a specific value for them out of the allowed values they have. If you look at inside the
showVals method, for x<5, there is only some display operations. Upto this point I have no issue to display texts on the lcd. All the lcd display operations are being controlled from here. Now when the value of x goes above 4, there are some calculations involved inside the 'if' clause, which I require as the outputs. They are also certain parameters - LUX, FOOTCANDLE, APERTURE and EXPOSURE VALUE.

I suspect the garbage are being shown on the lcd because of the delay caused due to the calculations. But I am not sure as the garbage occurs for around 7-10 secs in every execution which is an unusual run-time for this tiny mathematical operations.

cattledog:
I see this code which writes to the lcd after menu setting. I'm not clear about everything in the class parameters, but for trouble shooting try this function with .getName() commented out, and see if that is causing the "garbage display" before the correct display given with showVals().

void disp(int menu_pos, int val_pos){

//opts[menu_pos].getName();
 showVals(menu_pos, val_pos);
}

Although I didn't expect that method to cause any trouble but tried commenting it out to give your suggestion a try and nothing changed. The getName() method is called at the time when I am setting the values for input parameters which are ISO, SO, SS, FPS and FF. But the garbage aren't displays at this point. The garbage occurs at this point of the code

if(x==5 || x==6){
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    int isof = opts[0].getFinal();
    int sof = opts[1].getFinal();
    int ssf = opts[2].getFinal();
    int fpsf = opts[3].getFinal();
    float fff=ffval[ff_pos];
    delay(100);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LUX");
    lcd.setCursor(5,0);
    lcd.print("FOOTCANDLE");
    lcd.setCursor(0,1);
    lcd.print(lux);
    lcd.setCursor(8,1);
    lcd.print(footcandle);
  }
  if(x==7 ||x==8){
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    int isof = opts[0].getFinal();
    int sof = opts[1].getFinal();
    int ssf = opts[2].getFinal();
    int fpsf = opts[3].getFinal();
    float fff=ffval[ff_pos];
    aperture=isof*footcandle*sof*2;
    aperture=aperture/(float(sdVal)*float(ssf)*float(fpsf)*fff);
    aperture=sqrt(aperture);
    ev=log(aperture*aperture*float(ssf))/log(2);
    delay(100);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("APERTURE");
    lcd.setCursor(11,0);
    lcd.print("EV");
    lcd.setCursor(3,1);
    lcd.print(aperture);
    lcd.setCursor(11,1);
    lcd.print(ev);
  }

Thanks for the additional information to help pin point the problem.

I suspect the garbage are being shown on the lcd because of the delay caused due to the calculations. But I am not sure as the garbage occurs for around 7-10 secs in every execution which is an unusual run-time for this tiny mathematical operations.

After the 7-10 second display of "garbage", what is the correct display. Is all the printed information in these two sections correct after an initial period?

if(x==5 || x==6){ }
if(x==7 || x==8){}

What was the last thing on the screen before entering these sections?

It looks like you have removed the lcd.noDisplay() and lcd.display() commands from this section. Correct? I was going to suggest that and its very unusual to see them in a sketch.

Printing info on an LCD ought to be "never failing". I started on a low level just to make sure that basic works.
Your code is more complex than what I want to dig into. Therefore the answer.
Do You use interrupts that might change data in a way that the LCD print uses "half updated" data?

Wrong data displayed or real garbage, unrecognisable characters is something else. What does "the garbage look like"?

cattledog:
Thanks for the additional information to help pin point the problem.

After the 7-10 second display of "garbage", what is the correct display. Is all the printed information in these two sections correct after an initial period?

if(x==5 || x==6){ }

if(x==7 || x==8){}




What was the last thing on the screen before entering these sections?

It looks like you have removed the lcd.noDisplay() and lcd.display() commands from this section. Correct? I was going to suggest that and its very unusual to see them in a sketch.

Yes after the 'garbage display'is shown, then the required values are shown correctly. I have a push button connected to switch between the menus, which basically increments x. Now when x=4, and I press the push button, the lcd displays unrecognizable characters for 7-10 seconds, which I am addressing as 'garbage', then show the value of LUX and FOOTCANDLE. Now if I go into the next condition, that is increment x to 7 with push button, then the garbages are shown again, followed by the the values of APERTURE and EV. Now, I have another push button, that traverses the menu in a reverse way, that is it decrements the value of x. If I decrement to go from APERTURE to FOOTCANDLE, the garbage would appear again.

Here's a trouble shooting idea. In the x==5||x==6 section of the code there appear to be some unused local variables. If you comment them out, do you still get the garbage?

You could also try replacing them with fixed values in either this section or the x==6||x==8 section where they appear again but are used.

if(x==5 || x==6){
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    //int isof = opts[0].getFinal();
    //int sof = opts[1].getFinal();
    //int ssf = opts[2].getFinal();
    //int fpsf = opts[3].getFinal();
    //float fff=ffval[ff_pos];
    delay(100);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LUX");
    lcd.setCursor(5,0);
    lcd.print("FOOTCANDLE");
    lcd.setCursor(0,1);
    lcd.print(lux);
    lcd.setCursor(8,1);
    lcd.print(footcandle);
  }

Apologies for late reply, was caught in some college works. Yes the garbage do appear even after commenting out the local variables. I have actually removed them from code as they are unused and undesired load on the memory.

What does the "garbage" look like? Chinese figures instaéad of alfa numerics or what? Look at #8.

Yes, the garbage basically looks like unrecognised characters

That makes me think of some kind of disturbance. Either the electrical connection is intermittent, poor contact, or somehow Control Words are sent to the display. That can affect baudrate, select various options You don't want.
Start securing the electrical Connection.

Yes the garbage do appear even after commenting out the local variables. I have actually removed them from code as they are unused and undesired load on the memory.

Please post the latest code. If the 5||6 section now looks like this, there is really no calculations going on. If you replace lux with a fixed value do you get garbage?

If so, you will need to indicate exactly what happens between the code which makes the x increment and this conditional.

if(x==5 || x==6){
    lux = float(0.005*reading);
    footcandle = (lux/10.76391);
    delay(100);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("LUX");
    lcd.setCursor(5,0);
    lcd.print("FOOTCANDLE");
    lcd.setCursor(0,1);
    lcd.print(lux);
    lcd.setCursor(8,1);
    lcd.print(footcandle);
  }