Remove a delay from an LCD output

I have a sparkfun 16x2 lcd kit. I want to display 2 screens of data before looping. To do this I just use a delay and then print the second screen.
This works but I’m on a mission to remove as many delays as possible from my code as its not looping fast enough to get better than about 50second full loop.
So any ideas to do what im doing without a delay would be great.

// Display on LCD
  //Display first screen 
  led.empty();
  led.at(1,3,"Air Temp: ");
  led.at(1,13,(int)temp_f);
  led.at(2,1,"CO2:");
  led.at(2,5,CO2LevelValue);
  led.at(2,10,"Hum:");
  led.at(2,14,(int)humidity);
  delay(5000);  //I dont like this delay.  must be a better way
  //Display second screen
  led.empty();
  led.at(1,3,"H2O Temp: ");
  led.at(1,13,(int)watertempinf);
  led.at(2,1,"PPM:");
  led.at(2,5,(int)TDSValue);
  led.at(2,10,"PH:");
  led.at(2,13,intValue);  
  led.at(2,14,".");  
  led.at(2,15,(anotherIntValue,2));   
  delay(5000);

GroPi5000v0_4.pde (12.4 KB)

Look at the blink without delay example. Each time that code is reached, see if it is time to display screen one. If it is, do so. If not, see if it is time to display screen two. If it is, do so. If not, move on.

Each time you display a screen, record when, so you know when it is time to display the next one.

amazing how you can search around for hours when your brain is thinking in a different direction. Thanks Ill try that.

A quick look at your code

I see some double code in your app (e.g. logging into the router) => make a separate function of that.

Furthermore I should redesign void loop() * add conditional timing (some things don't need to be done every loop * splt the making of the measurements and displaying them

#define FETCHLEVELTIMEOUT (5 * 60 * 1000L)   // five minutes
unsigned long lastFetchLevels = 0;

#define DISPLAYTIMEOUT 1000   // every second
unsigned long lastDisplay = 0;

int screenID = 0;

void loop()        
{
  if (millis() - lastFetchLevels > FETCHLEVELTIMEOUT)   
  {
    lastFetchLevels = millis();              
    getMaxLevels();  //ask PHP for Max levels and create global variables  only run me every 1 to 5 minutes.
  }

  doSensorcheck()
  doSomethingAboutIt();  //  Compare Max levels to current levels and do something about it. 

  if (millis() - lastDisplay > DISPLAYTIMEOUT )   
  {
    lastDisplay = millis();
    doDisplay()
   }

}

void doDisplay()
{
  screenID = constrain(screenID, 0,2);
  switch(screenID)
  {
    case 0 : Serial.println("this is screen 0");  // etc
      break;
    case 1 : Serial.println("this is screen 1");
      break;
    case 2 : Serial.println("this is screen 2");
      break;
    default: // should not happen => reset screenID
      screenID = 0;
      break;
  }
  screenID++;
}

This way you update the max levels every 5 minutes, and you update the display every second. The measurements and actions are executed as fast as possible.

furthermore in getMaxLevels() you expect that when Serial.Available > 0 you have all the data in your buffer. This is not always the case Better write the routine in such a way that you first fill the buffer until you got the delimiter # and then start parsing

bool bufferComplete = false;
while (! bufferComplete )
{
  if (Serial.available()) 
  {
     ch = Serial.read();
     if (ch == '

Hopes this helps Rob) { pos = 0; continue; }     if (ch == '#') { bufferComplete = true; continue; }     string[pos++] = ch;     if (pos == 31) pos = 0; // safeguard missing #  } } string[pos] = 0;  // not needed after every char ```

Hopes this helps Rob

awesome, thanks rob. My next step actually is removing a bunch of delays and starting towards cleaning things up. This will help a bunch. You are right, i dont need to check max levels every loop. I also dont need to post the results to php to log every loop either. It sucks up gigs a day in mysql.

It sucks up gigs a day in mysql.

Isn't it amazing what such a small processor can generate ;)

ok I made a good bit of progress. Got alot of stuff moved to functions. Its starting to run much smoother now without all the delays and its easier to read with the functions.
Having trouble with the display on lcd function though. On start it runs through case 0,1,2 correctly. But then it just gets stuck on case 2. It blinks like it is clearing the lcd and displaying case 2 over and over.

void doDisplay()
{
  int intValue = (int)PHValue; // convert float PHValue to tricky int combination
  float diffValue = PHValue - (float)intValue;
  int anotherIntValue = (int)(diffValue * 1000.0);
  screenID = constrain(screenID, 0,2);
  switch(screenID)
  {
  case 0 :  
    // Display on LCD
    //Display first screen 
    led.empty();
    led.at(1,3,"Air Temp: ");
    led.at(1,13,(int)temp_f);
    led.at(2,1,"CO2:");
    led.at(2,5,CO2LevelValue);
    led.at(2,10,"Hum:");
    led.at(2,14,(int)humidity);
    break;
  case 1 : //Display second screen
    led.empty();
    led.at(1,3,"H2O Temp: ");
    led.at(1,13,(int)watertempinf);
    led.at(2,1,"PPM:");
    led.at(2,5,(int)TDSValue);
    led.at(2,10,"PH:");
    led.at(2,13,intValue);  
    led.at(2,14,".");  
    led.at(2,15,(anotherIntValue,2));   
    break;
  case 2 : 
    led.empty();
    led.at(1,3,"Some other");
     led.at(2,1,"awesomeness");
    // screenID = 0;
    break;
  default: // should not happen => reset screenID
    screenID = 0;
    break;
  }
  screenID++;
} //End of doDisplay

GroPi5000v0_5.pde (13.5 KB)

It blinks like it is clearing the lcd and displaying case 2 over and over

screenID = constrain(screenID, 0,2);
screenID++;

Have a look at modulo arithmetic, using the % operator.

ok. correct me if I'm wrong but the constrain actually doesnt make it loop it just says anything under 0 will return 0 and anything above 2 will return 2. so screenID++; was counting up to infinity but the constrain was just keeping it at 2.

So I seem to have fixed it by adding screenID = -1; in the case 2 statement. which cause it screen++ to equal 0 and start the loop over.

screenID = constrain(screenID, 0,2);
  switch(screenID)
  {
  case 0 :  
    // Display on LCD
    //Display first screen 
    led.empty();
    led.at(1,3,"Air Temp: ");
    led.at(1,13,(int)temp_f);
    led.at(2,1,"CO2:");
    led.at(2,5,CO2LevelValue);
    led.at(2,10,"Hum:");
    led.at(2,14,(int)humidity);
    break;
  case 1 : //Display second screen
    led.empty();
    led.at(1,3,"H2O Temp: ");
    led.at(1,13,(int)watertempinf);
    led.at(2,1,"PPM:");
    led.at(2,5,(int)TDSValue);
    led.at(2,10,"PH:");
    led.at(2,13,intValue);  
    led.at(2,14,".");  
    led.at(2,15,(anotherIntValue,2));   
    break;
  case 2 : 
    led.empty();
    led.at(1,3,"Some other");
     led.at(2,1,"awesomeness");
     screenID = -1;
    break;
  default: // should not happen => reset screenID
    screenID = 0;
    break;
  }
  screenID++;

Or you could write screenID = (screenID + 1) % 3; instead of screenID++; which will keep cycling 0, 1, 2, 0, 1, 2 etc. Or you could set up the next phase of screenID in each of the "case"s.

makes sense now. thanks.