Hold the sensor value on button press

Hi I am developing a light meter using a BH1750 light sensor.
My code is as follows:

#include <LCD5110_Graph.h>
#include <Wire.h>
#include <BH1750.h>

LCD5110 lcd(3,4,5,6,7);
extern unsigned char BigNumbers[];
extern uint8_t nuline[];
extern uint8_t ui[];
extern uint8_t splash[];


BH1750 lightSensor;
String light;

void setup() {
 
 lightSensor.begin();
 lcd.InitLCD();
 lcd.setFont(BigNumbers);
 lcd.clrScr();
 lcd.drawBitmap(0, 0, nuline, 84, 48);
 lcd.update();  
 delay(5000);
 lcd.clrScr();
 lcd.drawBitmap(0, 0, splash, 84, 48);
  lcd.update();  
 delay(2000);
 
}
void loop() {
  
 int stringLength=0;
 
 uint16_t lux = lightSensor.readLightLevel()*10;
 
 light = String(lux);
 stringLength = light.length();
 
 lcd.clrScr();
 lcd.drawBitmap(0, 0, ui, 84, 48);
 printLight(stringLength);
 lcd.update();
 
 delay(150);
}

void printLight(int length)
{
  switch(length)
  {
    case 1:  lcd.print(light,68,22); break;
    case 2:  lcd.print(light,54,22); break;
    case 3:  lcd.print(light,40,22); break;
    case 4:  lcd.print(light,26,22); break;
    case 5:  lcd.print(light,12,22); break;
    default:  lcd.print(light,0,22); break;
  }
}

I would now like to add a button which when pressed will hold the reading on the sensor.
For e.g. i shine a light on the sensor and it displays 1500 lux for example. Now when i turn it off the reading goeas back to 500 or whatever the general room brightness is.

What i am looking to achieve is once i press the button while the light is being shined. the display should stay on 1500 lux even after i turn off my light.

On pressing the button again, the sensor would go back to displaying real-time brightness as usual.

Any kind of help is appreciated. I am a newbie and I've managed to come up with this code after copious amount of reading and experimenting. Unfortunately the deadline for this is looming closer and I'm stuck with this challenge.

P.S. Using an Arduino UNO and a Nokia display

You need to detect when the button becomes pressed and change the state of a boolean variable when that happens. Look at the StateChangeDetection example to see how to detect the button press. If the boolean is now true save the value to be displayed

Later in the code control what is displayed depending on the state of the boolean, either the current value or the saved value

You can keep a (global or static) flag variable, e.g. called isMeasuring. If you press the button, change the variable from true to false or vice versa.

Your lux variable also needs to be global or static.

If isMeasuring equals true, execute lux = lightSensor.readLightLevel()*10;
Else don't execute it.

Be aware of button bounce and that you might want to react on the change of state of the button and not on the state itself.

This should do it; you do not need to do a dedicated debouce because you have a 150ms delay.

The variable has been renamed from isMeasuring to isHold indicating that the last reading will be held if the flag is true.
The code does a detection of the state change and reacts on a change from HIGH to LOW. The button must be wired between puin and GND

// we use negative logic (low means that the button is pressed)
#define ISPRESSED LOW

#include <LCD5110_Graph.h>
#include <Wire.h>
#include <BH1750.h>

LCD5110 lcd(3, 4, 5, 6, 7);
extern unsigned char BigNumbers[];
extern uint8_t nuline[];
extern uint8_t ui[];
extern uint8_t splash[];

// the hold button
const byte pinHoldBtn = 2;

BH1750 lightSensor;
String light;

void setup()
{

  lightSensor.begin();
  lcd.InitLCD();
  lcd.setFont(BigNumbers);
  lcd.clrScr();
  lcd.drawBitmap(0, 0, nuline, 84, 48);
  lcd.update();
  delay(5000);
  lcd.clrScr();
  lcd.drawBitmap(0, 0, splash, 84, 48);
  lcd.update();
  delay(2000);

  // button between pin and GND
  pinMode(pinHoldBtn, INPUT_PULLUP);
}

void loop()
{

  // remember if we're in hold or measure mode
  static bool isHold = false;

  // variable for lux measurement; will be remembered
  static uint16_t lux;

  // remember previous button state
  static byte prevHoldState = !ISPRESSED;


  // check the button
  byte btnState = digitalRead(pinHoldButton);
  if (btnState != prevHoldState)
  {
    prevHoldState = btnState;
    if (btnState == ISPRESSED)
    {
      isHold = !isHold;
    }
  }

  // if not in hold mode
  if (isHold == false)
  {
    lux = lightSensor.readLightLevel() * 10;
  }

  int stringLength = 0;
  light = String(lux);
  stringLength = light.length();

  lcd.clrScr();
  lcd.drawBitmap(0, 0, ui, 84, 48);
  printLight(stringLength);
  lcd.update();

  delay(150);
}

void printLight(int length)
{
  switch (length)
  {
    case 1:  lcd.print(light, 68, 22); break;
    case 2:  lcd.print(light, 54, 22); break;
    case 3:  lcd.print(light, 40, 22); break;
    case 4:  lcd.print(light, 26, 22); break;
    case 5:  lcd.print(light, 12, 22); break;
    default:  lcd.print(light, 0, 22); break;
  }
}

Try it, ask if you have questions. I could not compile as I don't have the libraries but the basics should be OK.

1 Like

Thanks a ton for this @sterretje !!

Works like a dream! I am now studying your code to learn more from this. Just a small question. When i execute this program, the sensor reading on the lcd is 0. I have to press the button again for it to start displaying the lumens in real-time. How can i get it to start displaying real-time lumen reading the moment i power it on?

Again. You have no clue how thankful i am for having helped me in this small adventure. :slight_smile:

You can make lux a global variable and read it once in setup(); in that case it does not have to be static.

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