LCD and Millis

Hello! I am working on a project, and three of the main components are a three way switch, a pressure sensor and a LCD screen. How it works is that depending on the setting of the switch, the LCD screen displays certain things.

Switch is up - displays certain set of instructions
Switch is middle - shows certain screen (this is good, it's the other two options that do not work)
Switch is down - displays a different set of instructions

There are a few problems with my current code:

If you switch the switch to the "up" position, the screen will not update until it cycles through completely (current code = 20 seconds). The pressure applied needs to update every half second, and the screen needs to be able to change instantaneously on the flick of the switch, and not be delayed 20 seconds. You can take a look at the code I have. I know I need to use millis for the LCD instructions, I'm just not sure how I should go about implementing it.

//LIBRARIES
#include <LiquidCrystal_I2C.h>
#include <Wire.h>  
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

//VARIABLES
int light = 5; //LED that lights up when too much pressure is applied
int up = 6; //switch pin
int down = 7; //switch pin
int pot = A1; //potentiometer pin
int potval; //value of poteniometer
const int maxpressure = 80; //Analog reading of most pressure allowed to be applied 

void setup() {
  
  //START SERIAL
  Serial.begin(9600);
  
  //DECLARATIONS
  pinMode(light, OUTPUT);
  pinMode(up, INPUT);
  pinMode(down, INPUT);
  
  //INITIAL STATES
  digitalWrite(up, HIGH);
  digitalWrite(down, HIGH);
  
  //INITIAL LCD DISPLAY
  lcd.begin(20,4);
  lcd.setCursor(0,0); 
  lcd.print("Hello");
  delay(5000);
}

void loop() {
  
  //PRINT POTENTIOMETER READING (initial testing, to be changed)   
  potval = analogRead(pot); 
  potval = map(potval,0,1023,0,100);
  Serial.println("Potentiometer Reading: "); 
  Serial.println(potval); 
  
  //DECLARE PRESSURE READINGS
  int pressure = analogRead(A0);
  pressure = map(pressure,0,1023,0,100);
  Serial.println("Pressure Reading: "); 
  Serial.println(pressure);
  
  //LED TURNS ON IF TOO MUCH PRESSURE
  if(pressure>maxpressure)
  {
    digitalWrite(light, HIGH);
  }
  else
  {
    digitalWrite(light,LOW);
  }

//GOING UP
lcd.clear();
  if(digitalRead(up)==LOW)
  {
    lcd.backlight();
    lcd.setCursor(0,0);
    lcd.print("Instructions for");
    lcd.setCursor(0,1); 
    lcd.print("going up");  
    lcd.setCursor(0,3);
    lcd.print("Pressure:"); 
    lcd.setCursor(10,3);
    lcd.print(pressure);
    lcd.setCursor(13,3);
    lcd.print("/");
    lcd.setCursor(14,3);
    lcd.print(maxpressure); 
    delay(5000);
    
      lcd.setCursor(0,0);
      lcd.print("                    ");
      lcd.setCursor(0,1); 
      lcd.print("                    ");
      lcd.setCursor(0,0);
      lcd.print("Place strong foot");
      lcd.setCursor(0,1); 
      lcd.print("on next stair");    
      delay(5000);
      
        lcd.setCursor(0,0);
        lcd.print("                    ");
        lcd.setCursor(0,1); 
        lcd.print("                    ");
        lcd.setCursor(0,0);
        lcd.print("Place weak foot");
        lcd.setCursor(0,1); 
        lcd.print("on next stair"); 
        delay(5000);
        
          lcd.setCursor(0,0);
          lcd.print("                    ");
          lcd.setCursor(0,1); 
          lcd.print("                    ");
          lcd.setCursor(0,0);
          lcd.print("Place cane");
          lcd.setCursor(0,1); 
          lcd.print("on next stair");     
          delay(5000);
  }

//GOING DOWN
lcd.clear();
  if(digitalRead(down)==LOW)
  {
    lcd.backlight();
    lcd.setCursor(0,0);
    lcd.print("Instructions for");
    lcd.setCursor(0,1); 
    lcd.print("Going down");  
    lcd.setCursor(0,3);
    lcd.print("Pressure:"); 
    lcd.setCursor(10,3);
    lcd.print(pressure);
    lcd.setCursor(13,3);
    lcd.print("/");
    lcd.setCursor(14,3);
    lcd.print(maxpressure); 
    delay(5000);
    
      lcd.setCursor(0,0);
      lcd.print("                    ");
      lcd.setCursor(0,1); 
      lcd.print("                    ");
      lcd.setCursor(0,0);
      lcd.print("Place cane");
      lcd.setCursor(0,1); 
      lcd.print("on next stair");    
      delay(5000);
      
        lcd.setCursor(0,0);
        lcd.print("                    ");
        lcd.setCursor(0,1); 
        lcd.print("                    ");
        lcd.setCursor(0,0);
        lcd.print("Place weak foot");
        lcd.setCursor(0,1); 
        lcd.print("on next stair"); 
        delay(5000);
        
          lcd.setCursor(0,0);
          lcd.print("                    ");
          lcd.setCursor(0,1); 
          lcd.print("                    ");
          lcd.setCursor(0,0);
          lcd.print("Place strong foot");
          lcd.setCursor(0,1); 
          lcd.print("on next stair");     
          delay(5000);
  }
  
//MIDDLE STATE
lcd.clear();
  if((digitalRead(up)==HIGH)&&(digitalRead(down)==HIGH))
  {
    lcd.setCursor(0,0);
    lcd.print("Pressure:");
    lcd.setCursor(10,0);
    lcd.print(pressure); 
    lcd.setCursor(13,0);
    lcd.print("/");
    lcd.setCursor(14,0);
    lcd.print(maxpressure); 
    lcd.setCursor(0,1);
    lcd.print("1st # = Pressure Now");
    lcd.setCursor(0,2);
    lcd.print("2nd # = Max Pressure");
    lcd.setCursor(0,3);
    lcd.print("Do not exceed 2nd #!");
    delay(800);
    //lcd.noBacklight();
  }
}

The UP and DOWN sections need some work. Print pressure needs to update every second and the delays need to be replaced so that screen can change instantly. I can supply anything else you might need!

Make an LCD update function that's branched to whenever the switch changes states OR every 1/2 second.

@Runaway

Sorry I'm kind of a noobie at arduino. Can you please elaborate a bit, or give an example code?

You can make your own functions.

Here is an "absurd" example --

void hitIt ()
{
  digitalWrite(5,HIGH);
}

Placing
hitIt();
would make that function happen.
So, if you place your LCD updating "code" in a function then you can call it as you need it.

Ah ok, I understand how to make functions, but how does this solve my millis/delay issue? Sorry, don't mean to be a pain.

here is what I've done...

void UpStairs()
{
int pressure = analogRead(A0);

lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Instructions for");
lcd.setCursor(0,1);
lcd.print("going up");
lcd.setCursor(0,3);
lcd.print("Pressure:");
lcd.setCursor(10,3);
lcd.print(pressure);
lcd.setCursor(13,3);
lcd.print("/");
lcd.setCursor(14,3);
lcd.print(maxpressure);
delay(5000);

lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place strong foot");
lcd.setCursor(0,1);
lcd.print("on next stair");
delay(5000);

lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place weak foot");
lcd.setCursor(0,1);
lcd.print("on next stair");
delay(5000);

lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place cane");
lcd.setCursor(0,1);
lcd.print("on next stair");
delay(5000);
}

and then

lcd.clear();
if(digitalRead(up)==LOW)
{
UpStairs();
}

but switch still does not automatically update

It's all those delay(5000) 's

Well yes, I know. But how can I remove them? I need the LCD to display each section for 5 seconds or so. I don't know how to use millis that well.

Once you write the LCD then it will not change till you write it again.
So then you want to commit to some course of action and upon completion of it: wait 5 seconds before going on to the next thing OR do something else if the switch changes OR some other thing if 1/2 sec has elapsed?

Let me break it down

Switch is in position A

LCD displays instruction #1, waits 5 seconds and instruction #2 is displayed
At the same time, pressure updates on a different line and never clears

Switch is in position B

LCD immediately clears (breaks current loop and enters B loop) and displayed instruction #3, waits 5 seconds and instruction #4 is displayed
At the same time, pressure updates on a different line and never clears

It's all very clear in your head, but is anything (else) supposed to happen inside these 5-second periods?
It's not clear to me where you want the windows for these escapes (?) that you require (?).
And I do not want to be interpreted as (being) an impediment to your progress, so I should probably duck out.

Dont worry I have enough time

In those 5 seconds I need:

The LCD screen to display a certain insturction (Ex: Move right foot up)
and current pressure on a pressure sensor to be displayed

So if this is my LED

line 1: Move right foot up
line 4: Current pressure (updates every half second)

WAIT 5 seconds

line 1: move left foot up
line 4: current pressure (updates every half second)

WAIT 5 seconds

etc.

but the problem is that I want to be able to end the loop at any time with the flick of a switch

Let's see. Currently you try using delays which is generally bad in any code. Instead use millis();

#define DESIRED 5000
uint64_t startTime, currentTime;

setup() {
    startTime, currentTime = millis();
}

loop() {
    currentTime= millis(); //Update current time
    
    //Next is done if 5sec is gone from startTime
    if (currentTime-startTime > DESIRED) {
       startTime, currentTime = millis();
       while (currentTime-startTime <= DESIRED) {
             Prosessing code here
             currentTime = millis();
       }
       startTime = millis(); //Reset start time to count next occurance
    }

}

You need to add always 1 start time variable for each funtion that you need counter to. when you need modes if some function can be pefromed, use global boolean variables and allow function done only if it is true and keep it false untile your switch allows something to happen.

If you need interupt the handling with switch, you need digital switch and use attachInterupt(0, myFunction, CHANGED) to be able to interrupt your coded and then prosesso your function to handle something. Remember to decalre volatile variables when using interupts so that after interupt the data is kept.

@Jeroi

Thanks, I didn't understand some of that technical mishmash at the end but I'll look into it and see what I can learn.

lcd.clear();
if(digitalRead(up)==LOW)
{
currentTime= millis();
if (currentTime-startTime > DESIRED) {
startTime, currentTime = millis();
while (currentTime-startTime <= DESIRED) {
lcd.backlight();
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Instructions for");
lcd.setCursor(0,1);
lcd.print("going up");
lcd.setCursor(0,3);
lcd.print("Pressure:");
lcd.setCursor(10,3);
lcd.print(pressure);
lcd.setCursor(13,3);
lcd.print("/");
lcd.setCursor(14,3);
lcd.print(maxpressure);
currentTime = millis();
}
startTime = millis(); //Reset start time to count next occurance
}

currentTime= millis();
if (currentTime-startTime > DESIRED) {
startTime, currentTime = millis();
while (currentTime-startTime <= DESIRED) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place strong foot");
lcd.setCursor(0,1);
lcd.print("on next stair");
}
startTime = millis(); //Reset start time to count next occurance
}

currentTime= millis();
if (currentTime-startTime > DESIRED) {
startTime, currentTime = millis();
while (currentTime-startTime <= DESIRED) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place weak foot");
lcd.setCursor(0,1);
lcd.print("on next stair");
}
startTime = millis(); //Reset start time to count next occurance
}

currentTime= millis();
if (currentTime-startTime > DESIRED) {
startTime, currentTime = millis();
while (currentTime-startTime <= DESIRED) {
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("Place cane");
lcd.setCursor(0,1);
lcd.print("on next stair");
}
startTime = millis(); //Reset start time to count next occurance
}
}

This didnt work, it prints nothing...

take startTime (that's your "mark")

then you have to check the switch status
and re-check the time vs your mark

startTime = millis();
timeout_or_switch ();

// ---------------

void timeout_or_switch ()
{
  if (theSwitch == active)
  {  switchinitiatedRoutine(); }  // bail out here
  currentTime = millis();  // re-check time elapsed
  if (currentTime - startTime < 5000) //  is this "rollover proof"?
  {  timeout_or_switch(); }   // time remaining
  else
  { // a function where strong, weak, cane routines/functions are determined}
}

Do not cross-post. Thread locked.

You can finish the discussion here...
http://forum.arduino.cc/index.php?topic=314255.0