LCD 16x2 - display primary message - break to display battery level for short period

Hi all,

I'm trying to use millis() to do something similar to blink without delay two LEDs at different rates. I've played with a number of options but can't do exactly what I want.

I want to display on one 16x2 LCD screen two alternating messages - values & their labels for 10 seconds - and display battery voltage & percentage for 2 seconds returning to the first screen.

I have it working of a sort but I can't get it to do exactly what I want & I'm not sure why.

https://youtube.com/shorts/x-3PdOPc4WM?feature=share

In setup I've defined

#define BATT_INTERVAL        10000
#define COUNT_INTERVAL       5000 // increased from 2000 as experiment 

I'd tried 2000 but it only flicked up briefly. Changing to 5000 extended it but not to 5 seconds. More like 2 seconds. See video.

The loop contains the following based on the blink without delay for 2 LEDs. I'm guessing because the two LEDs are on two outputs that they can operate independently it's quite different than trying to alternate the display on an LCD on a fixed duty cycle.

  if((millis() - lastMillisA >= COUNT_INTERVAL)) { // was newCounterTotal > myCounterTotal OR  >COUNT_INTERVAL && (newCounterTotal > myCounterTotal)
    lastMillisA = millis();
    LCDtemplate(); // sets LCD labels up for values printed below
//    myCounterTotal = newCounterTotal;
    lcd.setCursor(4,0);
    lcd.print(myCounterHigh);
    lcd.setCursor(12,0);
    lcd.print(myCounterLow);   
    lcd.setCursor(4,1);
    lcd.print(myCounterDouble); 
    lcd.setCursor(12,1);
    lcd.print(myCounterTotal);
 
    }
// Battery monitor
  static unsigned long lastMillisB = 0;
  if((millis() - lastMillisB) >= BATT_INTERVAL) {
    lastMillisB = millis();
    Serial.println();
   
// Serial monitor output    
    Serial.print("voltage: ");
    Serial.print(gauge.readVoltage()/1000);
    Serial.println(" V");
    Serial.print("precentage: ");
    Serial.print(gauge.readPercentage());
    Serial.println(" %");
    LCDbattlevel();   // subroutine that displays battery voltage & percentage
  }

What's the best way to get the LCD to show one screen for 10 seconds, a second for 2 seconds and cycle like that?

I've tried adapting the similar question but I can't work out where he went wrong with the = vs == that was the solution. I've changed the test in each if statement to == but it doesn't alternate. It might be as simple as using his solution but getting the "==" in the right places.

I've uploaded my sketch's full code. I'm a paramedic with a long ago career in electronic engineering (35+ years) not a coder so it's not pretty but it nearly works.

Thanks for any help.

Dave

Matts_Skeet_Project_v1-7_lowbatt_LCD_works.ino (16.8 KB)

Would it really matter if you used "delay" after all you are only displaying a couple of readings?
Read and display one for y time, clear screen read and display the other for x time.

One way would be something like this:

  • Make a boolean variable that holds the display status; e.g. 'true' representing the battery level.
  • Run the millis() timer and flip the boolean every 2 or 10 seconds.
  • Have a separate routine monitor the boolean from loop(); if it has changed, then change the display.

Use a boolean variable to control which data is displayed. In loop() something like this

if (display == true)

{
  //code here to display one set of data
}
elae
{
  //code here to display the other set of data
}

Change the value of the boolean using millis() timing in loop(). When the period ends, change the state of the boolean

1 Like

Hi Bluejets

I did try that but using delay prevents reading the switch inputs that come in and perform an essential task and increment the count.

I'll try some of the other suggestions once I get back into this again in a few days, and any that come in while I'm back at work. Probably back in the shed Sunday.

Cheers,

Dave

Good reason to show the complete code then initially I would think.

Entire sketch Is uploaded & linked at bottom of post? :man_shrugging:t2:

Dave

Another idea

Once a second, increment a variable that runs 0 to 9

   mode++; if (mode >= 10) mode = 0;

When you display, test the mode:

  if (mode < 8) {

// dispaly one thing

  }
  else {

//  display the other thing

  } 

You figure out how to increment the mode once a second. You could use a blink without delay pattern.

I didn't read your code, you shou,d post it here if you want readers. If you are using an RTC, you could key off the current value of seconds, viz:

  mode = seconds % 10;

and the same if/else statement.

HTH

a7

Something like this?

unsigned long
  tStart,
  tEnd = 12000, // twelve seconds
  elapsed;

void setup()
{
  //Serial.begin(9600);

}

void loop()
{
  elapsed = millis() - tStart;
  if(elapsed >= tEnd)
    tStart += tEnd;
  if(elapsed < 10000)
  {
    // do 10 second task
  }
  else
  {
    // do 2 second task
  }  

}

Hi @JCA34F ,

This does work. I've not started with any particular offer above, just working from bottom up & I could see how this one related to what I'd tried.

One issue I have that was present in my own was that the LCD doesn't need to refresh every time the Arduino runs through loop. Just at the start of the battery display, or when the counter value changes during the ten second display.

I've got the latter sorted. I just compare newCounterTotal with myCounterTotal and if it's changed I update the display.

I can't work out in the battery display part how to just write to the display once at the start of the 2 seconds (your // do 2 second task) and then don't write to the screen again until 2 seconds is up.

Do I need to put a second milli's if for 2 seconds in there that toggles a true/false or something that I test?

I'll have a play.

Thanks though.

I'll try some of the other solutions too, but they'll need a solution for the battery display flicker too. Probalby the same solution.

DJ

Here's how I usually solve this. It's flexible and robust, but it's probably more complicated than the lines you're thinking along now, and it consumes more memory (not a big issue with a 16x2 though):

  • Create an array of bytes that holds the display information; i.e. a display buffer. Create a second array of the same size as well.
  • When writing to the display, write to the buffer instead of the actual display.
  • Have a function that is called from loop and e.g. every 100ms does the following: compare both buffer arrays, one character at a time. If they're the same, exit the function. If they're different, write the new character to the display. Copy the new character to the second (shadow) array.

The main disadvantage of this is that you'll need 16x2x2 = 64 bytes of memory. The benefits, however, are:

  • You can easily adjust the display refresh rate to your taste
  • In your code, you don't have to worry about whether certain data is already on the display and whether it should be refreshed, as this happens automatically
  • Only the required traffic is generated on the I2C, SPI etc. bus. With a small 16x2 display this may not matter much, but with bigger displays, this will make a distinct difference in the responsiveness/smoothness of the display.

Ok. I can understand why that would work and it seems like a logical solution. I've not ever done anything like that so I'm going to learn some new skills if I go down this path - and that's never a bad thing.

I'm guessing that I would need one array for the battery voltage screen and another for the target counter information?

Currently I set up a template with the target information
0000000000111111
0123456789012345
H i : L o :
D b l: To t:

And then write the changing variables to referenced locations on the LCD to put numbers in the right spot. I'm guessing I can write those to a location in the array? Or do I need to rewrite all 16 x 2 locations in the array at the same time?

I'll go do some searching now, but if you have sample code that shows what you do that would be great. If not I'll find something on basic arrays and have a play in a separate sketch then try integrating it.

Cheers

Dave

Latest version of sketch below:



// V1-7 is last working version. Battery monitor in development.
/*
 * ClayDelay to Eletronica Progetti interface 

 * 

 * SwitchManager skeleton 
 
 
 Uses SwitchManager library written by Nick Gammon
 
 The library handles switch de-bouncing and provides timing and state change information in your sketch.
 The SwitchManager.h file should be placed in your libraries folder, i.e.
 C:\Users\YourName\Documents\Arduino\libraries\SwitchManager\SwitchManager.h
 You can download the library at:
 http://gammon.com.au/Arduino/SwitchManager.zip    Thank you Nick!
 
 In this example we have 2 normally open (N.O.) switches connected to the Arduino - HIGH and LOW.
 
 The two switches are connected between VCC (3.3 or 5 volts) and an Arduino input pin.
 The library enables pull-up resistors for your switch inputs.
 Pushing a switch makes its pin LOW. Releasing a switch makes its pin HIGH.
 
 The SwitchManager library provides 10ms de-bounce for switches. 
 i.e. enum { debounceTime = 10, noSwitch = -1 };
 If you need more time, edit the SwitchManager.h file
 i.e. enum { debounceTime = 50, noSwitch = -1 }; //here it is changed to 50ms
 */
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include "DFRobot_MAX17043.h"
#include <SwitchManager.h>       

#ifdef __AVR__
  #define ALR_PIN       5
#else
  #define ALR_PIN       D5
#endif

#define BATT_INTERVAL        2000
#define COUNT_INTERVAL       5000
      
//object initiations
DFRobot_MAX17043        gauge;
uint8_t       intFlag = 0;


SwitchManager mylowSkeetSwitch;
SwitchManager myhighSkeetSwitch;


unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long heartFlashRate  = 500UL; // time the led will change state       
unsigned long incShortPress   = 500UL; // 1/2 second
unsigned long incLongPress    = 5000UL;// 2 seconds 
unsigned long
  tStart,
  tEnd = 12000, // twelve seconds
  elapsed;

const byte heartBeatLED       = 13;
int myCounterTotal;
int newCounterTotal;
int myCounterHigh;
int myCounterLow;
int myCounterDouble;
int alternate;


const int HIGH_RELAY = A0; // was A0 but using that for low battery sense. May have to short 10k R5 to use 5
const int LOW_RELAY = A1;
const int DOUBLE_RELAY = 6;
const int lowSkRelease = 8;
const int highSkRelease = 9;

int highSkReleaseState = 0; // changed initial stat from 1 to 0 26.3.24 for 4ch relay board https://www.ebay.com.au/itm/131621839918
int lowSkReleaseState = 0; // changed initial stat from 1 to 0 26.3.24 for 4ch relay board https://www.ebay.com.au/itm/131621839918

int releaseState = 0;
int doubleTest = 0;
int relayState;
int ledState = LOW;        // current state of the output pin

unsigned int totaliser = 0;

//======================================================================

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

//======================================================================


void interruptCallBack()
{
  intFlag = 1;
}
//======================================================================
void setup()
{

// set up the LCD's number of columns and rows:
  lcd.init();
  lcd.init();
  // Turn on the blacklight and print a message.
  lcd.backlight();
  //****
  lcd.home(); //set cursor to top left corner
  // Print a message to the LCD.
  lcd.print("TrapTronix Aust"); //print the text to the lcd
  lcd.setCursor(0,1);
  lcd.print("(c) DJ 2024");
  delay(3000);
  lcd.clear();
  
  lcd.print(" +61 407532232 "); //print the text to the lcd
  lcd.setCursor(0,1);
  lcd.print("(c) DJ 2024");
  delay(3000);



  // Initialize the serial port at a speed of 115200 baud
  Serial.begin(115200);
  //---
  while(!Serial);
  Serial.println();
  Serial.println();
  pinMode(ALR_PIN, INPUT_PULLUP);
  attachInterrupt(ALR_PIN, interruptCallBack, FALLING);  //default alert is 32%
  
  while(gauge.begin() != 0) {
    Serial.println("gauge begin faild!");
    delay(2000);
  }
  delay(2);
  Serial.println("gauge begin successful!");
  gauge.setInterrupt(32);  //use this to modify alert threshold as 1% - 32% (integer)
  //---

  
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

// set up the display with Hi, Lo, Dbl & Tot
  LCDtemplate();


// Write relay outputs high so that when pinMode is set they don't briefly change state  
  digitalWrite(HIGH_RELAY, HIGH);
  digitalWrite(LOW_RELAY, HIGH);
  digitalWrite(DOUBLE_RELAY, HIGH);

  //gives a visual indication if the sketch is blocking
  pinMode(heartBeatLED, OUTPUT);  
  pinMode(highSkRelease, INPUT);
  pinMode(lowSkRelease, INPUT);
  pinMode(HIGH_RELAY, OUTPUT);
  pinMode(LOW_RELAY, OUTPUT);
  Serial.print("Double relay state: ");
  Serial.println(doubleTest);
  pinMode(DOUBLE_RELAY, OUTPUT);

//the handleSwitchPresses() function is called when a switch changes state  
  myhighSkeetSwitch.begin (highSkRelease, handleSwitchPresses);
  mylowSkeetSwitch.begin (lowSkRelease, handleSwitchPresses);



  


} //                   E N D  O F  s e t u p ( )

//======================================================================

void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  //***************************
  //some code to see if the sketch is blocking
  if (CheckTime(heartBeatMillis, heartFlashRate, true))
  {
    //toggle the heartBeatLED
    digitalWrite(heartBeatLED,!digitalRead(heartBeatLED));

  }


 elapsed = millis() - tStart;
  if(elapsed >= tEnd)
    tStart += tEnd;
  if(elapsed < COUNT_INTERVAL)
  {
    // do 10 second task

    if(newCounterTotal > myCounterTotal){
    LCDtemplate(); // sets LCD labels up for values printed below
    myCounterTotal = newCounterTotal;
    lcd.setCursor(4,0);
    lcd.print(myCounterHigh);
    lcd.setCursor(12,0);
    lcd.print(myCounterLow);   
    lcd.setCursor(4,1);
    lcd.print(myCounterDouble); 
    lcd.setCursor(12,1);
    lcd.print(myCounterTotal);
    static unsigned long lastMillisC = 0;
  if((millis() - lastMillisC) >= COUNT_INTERVAL) {
    lastMillisC = millis();
    alternate = 1;
    }
  }
  }
  else
  {
    // do 2 second task
    if(alternate == 1); {
    lcd.setCursor(0,1);
        LCDbattlevel();
    static unsigned long lastMillisD = 0;
    if((millis() - lastMillisD) >= BATT_INTERVAL) {
    lastMillisD = millis();
    alternate = 0;
    }       
        
// Serial monitor output    
    Serial.print("voltage: ");
    Serial.print(gauge.readVoltage()/1000);
    Serial.println(" V");
    Serial.print("precentage: ");
    Serial.print(gauge.readPercentage());
    Serial.println(" %");
  }  
  } 



/*

  static unsigned long lastMillisA = 0;  
  if((millis() - lastMillisA >= COUNT_INTERVAL)) { // was newCounterTotal > myCounterTotal OR  >COUNT_INTERVAL && (newCounterTotal > myCounterTotal)
    lastMillisA = millis();
    LCDtemplate(); // sets LCD labels up for values printed below
    myCounterTotal = newCounterTotal;
    lcd.setCursor(4,0);
    lcd.print(myCounterHigh);
    lcd.setCursor(12,0);
    lcd.print(myCounterLow);   
    lcd.setCursor(4,1);
    lcd.print(myCounterDouble); 
    lcd.setCursor(12,1);
    lcd.print(myCounterTotal);
 
    }
// Battery monitor
  static unsigned long lastMillisB = 0;
  if((millis() - lastMillisB) >= BATT_INTERVAL) {
    lastMillisB = millis();
    Serial.println();
   
// Serial monitor output    
    Serial.print("voltage: ");
    Serial.print(gauge.readVoltage()/1000);
    Serial.println(" V");
    Serial.print("precentage: ");
    Serial.print(gauge.readPercentage());
    Serial.println(" %");
    LCDbattlevel();
  }
*/
//**   


  if(intFlag == 1) {
    intFlag = 0;
    gauge.clearInterrupt();
    Serial.println("Low power alert interrupt!");
    //put your battery low power alert interrupt service routine here
  }
///LCD
// Set cursor to start of line 2, print total targets since reset, move to end of line & blink

//  lcd.setCursor(12,1);
//  lcd.print(myCounterTotal);
  lcd.setCursor(15,1);
  lcd.blink();


  //***************************
  //check to see what's happening with the switches
  //"Do not use delay()s" in your sketch as it will make switch changes unresponsive 
  //Use BlinkWithoutDelay (BWD) techniques instead.

  myhighSkeetSwitch.check (); 
  mylowSkeetSwitch.check (); 

  //***************************
  //put other non-blocking stuff here

// my code pasted here
// Check double switch activation
  
    doubleTest = lowSkReleaseState + highSkReleaseState;
//  Serial.println(doubleTest);

// double test & output to the high relay 1 when no double   
if (doubleTest == 1 && highSkReleaseState ==1)
  {
  digitalWrite(HIGH_RELAY, LOW);  // changed 22/4 for ebay Relay boards - neg state on
  delay(500);
  digitalWrite(HIGH_RELAY, HIGH);  // changed 22/4 for ebay Relay boards - neg state on
  delay(40);
  newCounterTotal = myCounterTotal+1;
  myCounterHigh++;
  Serial.print("High total = ");
  Serial.println(myCounterHigh);
  lcd.setCursor(4,0);
  lcd.print(myCounterHigh);
  Serial.print("Total targets thrown = ");
  Serial.println(myCounterTotal);
  }

// double test & output to the low relay 2 when no double       
if (doubleTest == 1 && lowSkReleaseState ==1)
  {
  digitalWrite(LOW_RELAY, LOW);  // changed 22/4 for ebay Relay boards - neg state on
  delay(500);
  digitalWrite(LOW_RELAY, HIGH);  // changed 22/4 for ebay Relay boards - neg state on
  delay(40);
  newCounterTotal = myCounterTotal+1;;
  myCounterLow++;
  Serial.print("Low total = ");
  Serial.println(myCounterLow);
  lcd.setCursor(12,0);
  lcd.print(myCounterLow);
  Serial.print("Total targets thrown = ");
  Serial.println(myCounterTotal);
  }

// skeet pair - test whether double switch activation has occurred. doubleTest may be redundant? Output to double relay 3
else if (doubleTest >= 2 && lowSkReleaseState == 1 && highSkReleaseState == 1)
  {

  digitalWrite(DOUBLE_RELAY, LOW);   // changed 22/4 for ebay Relay boards - neg state on
  delay(500);


  Serial.println("Double relay triggered by this code section.");
  digitalWrite(DOUBLE_RELAY, HIGH);  // changed 22/4 for ebay Relay boards - neg state on
  delay(40);
  newCounterTotal = myCounterTotal +2;
  myCounterDouble++;
  Serial.print("Double total = ");
  Serial.println(myCounterDouble);
  Serial.print("Total targets thrown = ");
  Serial.println(myCounterTotal);
  lcd.setCursor(4,1);
  lcd.print(myCounterDouble);
  }

// reset both to low before repeating / waiting for next activation
  lowSkReleaseState = LOW;
  highSkReleaseState = LOW;


  digitalWrite(HIGH_RELAY, !relayState);  // ! changed 22/4 for ebay Relay boards - neg state on
  digitalWrite(LOW_RELAY, !relayState);  //! changed 22/4 for ebay Relay boards - neg state on
  
//  Serial.println(relayState);
//  Serial.println(dtlReleaseState);
  delay(20);        // delay in between reads for stability




} //                      E N D  O F  l o o p ( )


//======================================================================
//                          F U N C T I O N S
//======================================================================


//                        C h e c k T i m e ( ) 
//**********************************************************************
//Delay time expired function
//parameters:
//lastMillis = time we started
//wait = delay in ms
//restart = do we start again  

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart) 
{
  //has time expired for this task?
  if (currentMillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //yes, get ready for the next iteration
      lastMillis = millis();  
    }
    return true;
  }
  return false;

} 
//                 E N D   o f   C h e c k T i m e ( )

//                 Serial print Filename, Date & Time
//**********************************************************************
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}

// E N D o f PrintFileNameDateTime


//                 Serial print LCD Template
//**********************************************************************

void LCDtemplate(){
  lcd.clear();
  lcd.home();
  lcd.print("Hi:     Lo:");
  lcd.setCursor(0,1);
  lcd.print("Dbl:    Tot:");
}

//   Output battery to LCD
//***********************************************************************

void LCDbattlevel(){
// LCD monitor output
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Batt volt: ");
    lcd.setCursor(13,0); 
    lcd.print(gauge.readVoltage()/1000);
    lcd.setCursor(0,1);
    lcd.print("Batt level: ");
    lcd.setCursor(13,1); 
    lcd.print(gauge.readPercentage());
    lcd.setCursor(15,1);
    lcd.print("%");

}
//

//                h a n d l e S w i t c h P r e s s e s ( )
//**********************************************************************

void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  // You get here "ONLY" if there has been a change in a switches state.
  // 26/3/24 Switches in this project are NO switch. 10K pulls pin HIGH. press of switch pulls pin LOW
  //When a switch has changed state, SwitchManager passes this function 3 arguments:
  //"newState" this will be HIGH or LOW. This is the state the switch is in now.
  //"interval" the number of milliseconds the switch stayed in the previous state
  //"whichPin" is the switch pin that we are examining  



  switch (whichPin)
  {

   //***************************    
/*
#       ####### #     #    #######    #    ######   #####  ####### ####### 
#       #     # #  #  #       #      # #   #     # #     # #          #    
#       #     # #  #  #       #     #   #  #     # #       #          #    
#       #     # #  #  #       #    #     # ######  #  #### #####      #    
#       #     # #  #  #       #    ####### #   #   #     # #          #    
#       #     # #  #  #       #    #     # #    #  #     # #          #    
####### #######  ## ##        #    #     # #     #  #####  #######    #    
                                                                           
######  ####### #       #######    #     #####  ####### 
#     # #       #       #         # #   #     # #       
#     # #       #       #        #   #  #       #       
######  #####   #       #####   #     #  #####  #####   
#   #   #       #       #       #######       # #       
#    #  #       #       #       #     # #     # #       
#     # ####### ####### ####### #     #  #####  ####### 
*/   
    //are we dealing with this switch?
  case lowSkRelease: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The incSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= incShortPress) 
      {

      }



    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW 
    // THIS is our condition as pin is normally pulled high via 10k and is pulled low when switch closes.
    else 
    {
      Serial.println("The Low Skeet Release was just pushed");

        // Set variable to write to token box 
        lowSkReleaseState = HIGH;
    
    } 

    break; //End of case lowSkRelease
   


    //***************************    
    /*
#     # ###  #####  #     #    #######    #    ######   #####  ####### ####### 
#     #  #  #     # #     #       #      # #   #     # #     # #          #    
#     #  #  #       #     #       #     #   #  #     # #       #          #    
#######  #  #  #### #######       #    #     # ######  #  #### #####      #    
#     #  #  #     # #     #       #    ####### #   #   #     # #          #    
#     #  #  #     # #     #       #    #     # #    #  #     # #          #    
#     # ###  #####  #     #       #    #     # #     #  #####  #######    #    
                                                                               
######  ####### #       #######    #     #####  ####### 
#     # #       #       #         # #   #     # #       
#     # #       #       #        #   #  #       #       
######  #####   #       #####   #     #  #####  #####   
#   #   #       #       #       #######       # #       
#    #  #       #       #       #     # #     # #       
#     # ####### ####### ####### #     #  #####  ####### 
    */
  
    //are we dealing with this switch?
  case highSkRelease: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The incSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= incShortPress) 
      {

      }



    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW 
    // THIS is our condition as pin is normally pulled high via 10k and is pulled low when switch closes.
    else 
    {
      Serial.println("The High Skeet Release was just pushed");


        // Set variable to write to token box 
        highSkReleaseState = HIGH;

    
    
    } 

    break; //End of case highSkRelease


  
    //*************************** 
    //Put default stuff here
    //default:
    //break; //END of default

  } //End switch (whichPin)
  
} //      E n d   o f   h a n d l e S w i t c h P r e s s e s ( )


//======================================================================
//                      E N D  O F  C O D E
//======================================================================

No, two arrays for the screen, regardless of what content is on there. The switching logic for the actual content is unrelated to the screen buffer. That's part of the beauty of the concept; it effectively decouples the control of the screen as such from the functional behavior of your user interface. Even if you switch between 50 different screens, it'd still be the same two buffer arrays.

Try this principle

unsigned long currentTime;
unsigned long periodStartTime;
unsigned long tempPeriod = 5000;
unsigned long batteryPeriod = 2000;
bool showingTemp = true;
int temperature;
int voltage;

void setup()
{
    Serial.begin(115200);
    currentTime = millis();
    periodStartTime = currentTime;
    displayValue();
}

void loop()
{
    currentTime = millis();
    switch (showingTemp)
    {
        case true:
            if (currentTime - periodStartTime >= tempPeriod)
            {
                showingTemp = false;
                displayValue();
                periodStartTime = currentTime;
            }
            break;
        case false:
            if (currentTime - periodStartTime >= tempPeriod)
            {
                showingTemp = true;
                displayValue();
                periodStartTime = currentTime;
            }
            break;
    };
}

void displayValue()
{
    if (showingTemp)
    {
        temperature = random(50);
        Serial.print("the temperature is ");
        Serial.println(temperature);
    }
    else
    {
        voltage = random(100);
        Serial.print("the voltage is ");
        Serial.println(voltage);
    }
}

Without closing it flag, @UKHeliBob shows the use of a variable that only has two values (one of the things called a flag)

bool showingTemp = true;

The logic can be written many ways. For doing something once

    if (not dataHasBeenDispalyed) {
        doTheDispalyThing();
        dataHsBeenDisplayed = true;
    }

I used a different variable name to reflect its roll. I called a function that could just be instead all your display commands, or do put them in a better named function for readability.

The only trick/problem is resetting the flag… in this situation you could reset when your larger logic calls for displaying the other information.

There to keep the seconds up to date, actually in some cases the minute would and the hour would and so forth unless you deliberately synchronize to, say, starting at three seconds into the minute your 8 on 2 off rhythm.

Then just watch the seconds and only paint them when it changes, because you did the other stuff once, and had a… flag so that only happens once which… you could reset in the other section.

  timeHasBeenDispalyed = false;  // so time section will print the entire screen next time

a7

Broken fingers...don't know how to post code in code brackets...let someone else do all the work then??

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.