Arduino - perform task only ONCE every second

Hi,

I am driving a colour TFT with my arduino.

It takes a significant ammount of time to print, hence other tasks are afected and usually data loss occurs.

I need to print to the LCD once a second ONLY, while other tasks in the loop run continuously.

I tought about using the "blink without delay" example, however I need to modify it to turn a variable to ONE once every second. A loop will then check if the variable is one, information is sent to the display, variable is set to zero, and next time the loop runs, if less than a second has elapsed the variable will still check zero, so printing is skipped, howerver other functions on the loop still run.

Any ideas how this could be implemented?

I tought about using the "blink without delay" example

That is the correct approach.

however I need to modify it to turn a variable to ONE once every second.

Why is that a problem?

Turning a variable to one is an unnecessary complication. Once you detect a second has passed, simply call your print function rather than setting a variable to one and then checking if that variable is one and then calling your print function.

Doing something periodically is such a common task that I wrote a library to do this for me. I am surprised that the Arduino libraries don't include this.

DavidOConnor: Doing something periodically is such a common task that I wrote a library to do this for me.

Please share David.... as you say, it's a common requirement, and assuming it's a BlinkWithoutDelay approach many of us would find it very useful.

PaulS:

however I need to modify it to turn a variable to ONE once every second.

Why is that a problem?

As it stands the example togles a bit to one AND leaves it there for one second. So essentially the print statments would be active for one second and inactive for the following second.

Sure this can be modified, I just dont see how. I normally use a loop to check if a condition is true - If it is, executes, if not, does nothing. What would be your aproach?

DavidOConnor: Turning a variable to one is an unnecessary complication. Once you detect a second has passed, simply call your print function rather than setting a variable to one and then checking if that variable is one and then calling your print function.

David, that makes perfect sense, would you care to exemplify how its done? I actually dont do just a print statment, I refresh all the variables on the screen, so a lot of print variables. But for that i need the CPU to be free before so that the loop can run and the variables updated from the serial port, ADC or I/O.

DavidOConnor: Doing something periodically is such a common task that I wrote a library to do this for me. I am surprised that the Arduino libraries don't include this.

Would you mind sharing your library?

As it stands the example togles a bit to one AND leaves it there for one second. So essentially the print statments would be active for one second and inactive for the following second.

Sure this can be modified, I just dont see how. I normally use a loop to check if a condition is true - If it is, executes, if not, does nothing. What would be your aproach?

When sufficient time passes to warrant setting the value to 1, set it to 1. Then, when you discover that the value is 1, do something and set the value to 0.

The blink without delay example shows how to run a piece of code at regular intervals. In the example the code just inverts an output, but you can change that to do whatever you want. Here's a similar example you can use as the basis for a self-contained bit of code to do the timing for you:

void maintainDisplay()
{
    static const unsigned long REFRESH_INTERVAL = 1000; // ms
    static unsigned long lastRefreshTime = 0;

    if(millis() - lastRefreshTime >= REFRESH_INTERVAL)
    {
        lastRefreshTime += REFRESH_INTERVAL;
                refreshDisplay();
    }
}

void refreshDisplay()
{
        // your code to refresh the display here
}

You need to arrange for maintainDisplay() to be called repeatedly, for example each time loop() is called, and it will update the display at whatever interval you specified.

PaulS:

As it stands the example togles a bit to one AND leaves it there for one second. So essentially the print statments would be active for one second and inactive for the following second.

Sure this can be modified, I just dont see how. I normally use a loop to check if a condition is true - If it is, executes, if not, does nothing. What would be your aproach?

When sufficient time passes to warrant setting the value to 1, set it to 1. Then, when you discover that the value is 1, do something and set the value to 0.

This is what i was trying to do, but for some reason it doesnt work.

long previousMillis = 0; 
long interval = 1000;  
int tftrefresh = 0;

void setup() {}

void loop()
{
 
//********************delay 1s**************************
  
    unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) 
        {
          // save the last time you blinked the LED 
          previousMillis = currentMillis;   
        
          if (tftrefresh == 0)
            tftrefresh = 1; // sets tft efresh variable to 1
          else
            tftrefresh = 0; //if not tftrefresh = 0
      
          
        }
  
 if (tftrefresh = 1)
    {
    print stuff
    tftrefresh = 0; /*after its done set tftrefresh to 0 
            so it wont be done again until one second is gone*/
    }
//*********************end of delay 1s*******************
}

PeterH: The blink without delay example shows how to run a piece of code at regular intervals. In the example the code just inverts an output, but you can change that to do whatever you want. Here's a similar example you can use as the basis for a self-contained bit of code to do the timing for you:

void maintainDisplay()
{
    static const unsigned long REFRESH_INTERVAL = 1000; // ms
    static unsigned long lastRefreshTime = 0;
if(millis() - lastRefreshTime >= REFRESH_INTERVAL)
{
    lastRefreshTime += REFRESH_INTERVAL;

                refreshDisplay(); } }

void refreshDisplay() {         // your code to refresh the display here }




You need to arrange for maintainDisplay() to be called repeatedly, for example each time loop() is called, and it will update the display at whatever interval you specified.

Makes sense Ill have a go trying, Thanks.

if (tftrefresh = 1)

= != ==

Do you need to refresh the whole of your display? Mine takes a little over a ms to move the cursor and a ms per character to write. The inconveniently long time to write the whole display is spread out over several smaller partial writes. Program complexity goes up, but it never delays.

JimboZA:

DavidOConnor: Doing something periodically is such a common task that I wrote a library to do this for me.

Please share David.... as you say, it's a common requirement, and assuming it's a BlinkWithoutDelay approach many of us would find it very useful.

I just posted the library to github. Give it a try and let me know what you think.

https://github.com/oconnoda/Timer.git

DavidOConnor: I just posted the library to github. Give it a try and let me know what you think.

Willco... thanks.

ad2049q: Do you need to refresh the whole of your display? Mine takes a little over a ms to move the cursor and a ms per character to write. The inconveniently long time to write the whole display is spread out over several smaller partial writes. Program complexity goes up, but it never delays.

No I dont refresh the complete display, that would take me a significant time.

Most simbols are static items are in the void setup(void) what i refresh is the variables that need to be refreshed. Some are updated once a minute (time, battery capacity), some are updated every second (warnings, range) and other are updated two or more times a second (Voltage and current indicators)

The display is a colour screen with 320x240Resolution

The display is a colour screen with 320x240Resolution

Which display do you have? Which library are you using? Some TFT libraries have poor performance rendering fonts. However in some cases performance can be improved significantly.

JimboZA:

DavidOConnor: I just posted the library to github. Give it a try and let me know what you think.

Willco... thanks.

Righto... slotted 2 timers into some existing code. Now have 2 independently blinking LEDs and rest of code works as before with no blocking. Good stuff, thanks DO'C

Will V2 of the library cater for different on / off times David? :P

JimboZA: Will V2 of the library cater for different on / off times David? :P

I've thought about that. I haven't needed that capability yet, but if you think it would be needed, I'll work on it.

DavidOConnor: I've thought about that. I haven't needed that capability yet, but if you think it would be needed, I'll work on it.

Well, it would be great, but all in good time....... As it is at the moment it'll already be a boon to many Arduinites I'm sure.

JimboZA:

DavidOConnor: I've thought about that. I haven't needed that capability yet, but if you think it would be needed, I'll work on it.

Well, it would be great, but all in good time....... As it is at the moment it'll already be a boon to many Arduinites I'm sure.

I designed the library to be simple and and easy to use, yet be as general as possible. When I wrote the library I though about adding a change interval method, but decided that the same can be achieved by stopping the timer and starting again with a new interval. So yes you can have different on/off times...

void toggleLED(int timer) {
  static int LEDState = 1;

  digitalWrite(ledPin,LEDState?HIGH:LOW);
  LEDState = !LEDState;
  tm.stopTimer(timer);
  if (LEDState) {
    tm.startTimer(1000,toggleLED);
  }
  else {
    tm.startTimer(25,toggleLED);
  }
}

However this has the disadvantage of (possibly) invalidating the timer number if it was saved for later reference in the initial call to startTimer in the setup function. So maybe I'll add a change interval method after all.