Doing things based on time?

So I’ve got code that does a lot of things already and probably shouldn’t be slowed down by any large chunks, anyway. And while I can program, I’d say when it comes to true embedded development, I’m a bit of a neophyte.

My device has a couple buttons connected direct to digital inputs. It also has a small i2c LCD display, an i2c temp/hum sensor, and a PWM fan connected to a digital pin. There’s a PID running the fan based on the temp sensor and I also plan to add an O2 sensor via an i2c 12 bit ADC. Buttons are interfaced with clickButton.

The buttons are used to adjust the temp, but I’d like to add code to have a button press turn on the LCD backlight and then have the backlight time out and turn off something like 10 seconds after the last button press. Anyone got any pointers to the smartest way to make that happen in this kind of situation? I’m pretty good at deciphering sample code for the bits I want, less good at doing things from scratch (but I can usually muddle through). I mean I assume I can just check the time after the button press and then keep checking it every time through loop until 10s has passed (I mean I know how to do math), but is that a reasonable way to do it, or is there a better way?

—Donnie

https://docs.particle.io/reference/device-os/firmware/boron/#software-timers

Well hot dog, that’s exactly what I was looking for. I’ve read the documentation, but it’s been a while since I’ve gone through it all, and the parts that stick best are the parts I need at the time. I didn’t need that then and it didn’t stick, and for some reason I didn’t see it again.

Anyway, thanks a bunch.

—Donnie

Hi Donnie,
yes that is a reasonable way to do it.
I personally like how my code looks when I use the elapsedMillis library (you can find it in the IDE), so I would add stuff like this:

This code goes before the setup() function:

#define LCD_BACKLIGHT_INTERVAL 10000
elapsedMillis lcdBacklightInterval;
bool lcdBacklightOn = false;

This code goes wherever is that the button turns the lcd backlight on:

lcdBacklightOn = true;
lcdBacklightInterval = 0;
// here goes the line where you actually turn on the lcd backlight
digitalWrite(lcdBacklight, HIGH);

This code goes in the loop() function:

  if (lcdBacklightOn) {
    if ( lcdBacklightInterval > LCD_BACKLIGHT_INTERVAL ) {
      lcdBacklightOn = false;
      // turning off the lcd backlight
      digitalWrite(lcdBacklight, LOW);
    }
  }

(I was just now coding something very similar to this so I copy-pasted my code here and changed the vars name to something meaningful to your case)
Cheers!
Gustavo.

EDIT: but maybe with software timers this looks better! let me know please…

I tried the software timer first. It seemed to be pretty easy and worked as I expected, but I think the LCD library I’m using is not thread safe. About every eighth button press I’d end up with garbage on the screen. Have not had that behavior with ANYTHING else I’ve done so far. Actually, it looks like i2c stuff can be made thread safe, but special attention has to be taken. So probably that’s not happening with the LCD, anyway. Maybe other things, too.

So I moved it to elapsedMillis and it seems to be working perfectly. The only thing the example above forgets is to reset the lcdBacklightInterval to zero in the right places. That was pretty easy to figure out, though, and it’s working great. Thanks for the input!

Honestly, it was really six of one, half dozen of the other as to which was easier.

–Donnie

1 Like

good to know and sorry for the omission (on reseting the lcdBacklightInterval to zero) :wink:
Cheers
Gustavo.

Hi, I kept thinking about this. Could it be that you put code in the timer callback function? Perhaps the issues could have been avoided if you set a flag in that callback function and do the lcd backlight off from the loop() function reading that flag?

Would you mind telling me where did I forget to reset so I learn from your code?
Thanks!
Gustavo.

Yeah, that’s definitely possible. I didn’t ever commit that code so I can’t go back and look, though.

I’ll try it again next week. I’ve got some different code that needs to do a very similar thing and I’ll try it with software timers and just do the flag in the handler.

You don’t need it to do a thing one time ever, but you do need to do it if you need to re-use the variable to do it again. Basically my code just takes the first button press to turn on the LCD, and as long as the LCD is on, subsequent button presses change the set temperature. So when I dropped your code in, it worked the FIRST time, but after that I got a flash of backlight and right back off because I hadn’t reset the counter back to zero.

At the risk of outing myself as a horrible programmer, you can go see the code for yourself here:

I was never taught any C++, only C, and I’m not even good at C. But I tend to find sample code that does close to what I want and beat it into submission. So you’ll see ugly mixes of things and whatnot, but I welcome corrections and suggestions.

–Donnie

1 Like

Nice! A PID for altitude training? Where are you heading? :mountain:

Hahaha. Nowhere! But I started altitude training in 2011 and did the Leadville Trail 100 MTB race in 2012. Then last year I went to Nepal and hiked to Everest Base Camp, so I used altitude training for that, too. And now I just still do it because it works. I go to Colorado to mountain bike once a year or so, and live near sea level, so it’s just smart training.

–Donnie

1 Like