Question about proper programming structure...

In a situation where there is, for example, an if/then statement within the loop() function that alters the state of a variable, is there harm (in terms of lag) when the value of the variable is written to redundantly every single time loop() cycles? This, versus using flags to make sure that the variable value is only written to when the value is changed (using a flag variable, for example).

If my description sounds confusing look at these two sample codes below. Both do the exact same thing: With two timers LED on pin 13 is set ON for 10 seconds, then OFF for 5 seconds, and this loops infinitely.

In the first example the line "digitalWrite(LED, HIGH/LOW);" is ONLY executed if the state of the pin is supposed to change value from HIGH to LOW or vice versa. In the second example "digitalWrite(LED, HIGH/LOW);" is executed every single time loop() runs regardless of whether LED is supposed to change value. Both sketches work perfectly, but is there any real disadvantage with using the second example? Example one seems 'cleaner' because it's not redundantly executing unnecessary code, but it uses more variables than example 2.

Thoughts?

Here are the sketches:

EXAMPLE 1:

long On_Timer = millis(); // ticker
long On_Time =10000;
long Off_Timer = millis(); // ticker
long Off_Time = 5000;
boolean ON_OFF = 0;
boolean ON_OFF_READ = 1;

int LED = 13;

void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);
ON_OFF_READ = 1;
Off_Timer = millis();
On_Timer = millis();
}

void loop() {
// put your main code here, to run repeatedly:

if(millis() - On_Timer > On_Time & ON_OFF_READ == 1)
{
Off_Timer = millis();
ON_OFF_READ = 0;
}

if(millis() - Off_Timer > Off_Time & ON_OFF_READ == 0)
{
On_Timer = millis();
ON_OFF_READ = 1;
}

if(ON_OFF == 0 & ON_OFF_READ == 0) // Turns led OFF
{
digitalWrite(LED, LOW); // PUT ADDITIONAL RELAY CODE HERE
ON_OFF = 1;
}
if(ON_OFF == 1 & ON_OFF_READ == 1) // PUT ADDITIONAL RELAY CODE HERE
{
digitalWrite(LED, HIGH);
ON_OFF = 0;
}

}

=================================

Example 2:

long On_Timer = millis(); // ticker
long On_Time =10000;
long Off_Timer = millis(); // ticker
long Off_Time = 5000;
boolean ON_OFF_READ = 1;

int LED = 13;

void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);
ON_OFF_READ = 1;
Off_Timer = millis();
On_Timer = millis();
}

void loop() {
// put your main code here, to run repeatedly:

if(millis() - On_Timer > On_Time & ON_OFF_READ == 1)
{
Off_Timer = millis();
ON_OFF_READ = 0;
}

if(millis() - Off_Timer > Off_Time & ON_OFF_READ == 0)
{
On_Timer = millis();
ON_OFF_READ = 1;
}

if(ON_OFF_READ == 0) // Turns led OFF
{
digitalWrite(LED, LOW);

}
if(ON_OFF_READ == 1) // Turns led ON
{
digitalWrite(LED, HIGH);

}

}

You're using the bitwise and, '&' instead of the logical and, '&&' in your if statements. If '&&' is too confusing, I sympathize with you - that is why the option of just using the word, 'and' was recently added to the language. '&&' and 'and' are exactly equivalent.

For example,

if(millis() - On_Timer > On_Time && ON_OFF_READ == 1)

or

if(millis() - On_Timer > On_Time and ON_OFF_READ == 1)

but since ON_OFF_READ is a boolean, you can also just say

if(millis() - On_Timer > On_Time and ON_OFF_READ)

You could gain some performance by switching the operands of the and.

if (ON_OFF_READ and (millis() - On_Timer > On_Time))

Forehead slap. :slight_smile:

Ok I understand what you guys mean and that is something I overlooked, but back to my original question, let's assume ON_OFF_READ is not Boolean. Regardless, example 2 executes the line "digitalWrite(LED, HIGH/LOW);" every single loop cycle redundantly but uses one less variable than example 1 which only runs "digitalWrite(LED, HIGH/LOW);" when the state of the pin actually needs to change. From that point of view which example is more preferable?

moses1592:
back to my original question, let's assume ON_OFF_READ is not Boolean

What is it, then? What does it represent?

aarg:
What is it, then? What does it represent?

If it was integer instead of boolean for example. I know there's no real reason to do this.

My original question dealt with redundantly executing a line of code (in this case "digitalWrite(LED, HIGH/LOW);") versus preventing redundant execution but using another extra variable to prevent it. My apologies if I'm missing something here.

....i mean assigning the same value to "digitalWrite(LED, HIGH/LOW);" over and over and over again vs only when the value actually changed.

moses1592:
....i mean assigning the same value to "digitalWrite(LED, HIGH/LOW);" over and over and over again vs only when the value actually changed.

Have a look at IDE -> file/examples/digital/state change detection.

When your condition *becomes true * that's a state change. When it *goes false * that's another, separate, state change.

dougp:
Have a look at IDE → file/examples/digital/state change detection.

When your condition *becomes true *that’s a state change. When it *goes false *that’s another, separate, state change.

I understand that. Let’s say you have a sketch and the only code in loop() is: “digitalWrite(LED, HIGH);”. Nothing more than that.

From the standpoint of what goes on after the sketch is compiled and run, how does the hardware handle this? The state does not change, so is the request essentially skipped until the state changes or does something else happen such that the hardware/cpu takes an extra step to essentially attempt to reassign the same value/state to the pin over and over again and use some of processing power while doing so? Sorry if that doesn’t make sense, not sure how else to ask this.

moses1592:
Let’s say you have a sketch and the only code in loop() is: “digitalWrite(LED, HIGH);”. Nothing more than that.

From the standpoint of what goes on after the sketch is compiled and run, how does the hardware handle this? The state does not change, so is the request essentially skipped until the state changes or does something else happen such that the hardware/cpu takes an extra step to essentially attempt to reassign the same value/state to the pin over and over again and use some of processing power while doing so?

The output will be written HIGH each time through loop(). That being the only statement it will be executed thousands, possibly hundreds of thousands of times every second. The time (processor clock cycles) to execute each write will be the same each occurrence.

A hardware memory write operation never cares about the current contents of a memory location. The previous value is simply discarded as it is overwritten. Thus if the old value and the new value are the same, or different, it makes no difference whatsoever in how the processor behaves. The reason I mention memory, is that the I/O ports on the AVR processor (for example) appear as a memory location that is "visible" to the external pins (I am simplifying and ignoring all the possible modes beyond the basic digital output, such as serial etc.).

That all means that if you write a 1 to an output that is already a 1, nothing changes and the program marches on as if nothing special happened.

Where things get bad, is where people transfer that habit of constantly updating data whether or not it has changed, to some device that can't handle it.

A hardware memory write operation never cares about the current contents of a memory location.

This is not completely true for IO registers, which occasionally have "side effects" when written to.
For example, on an Uno you can write PORTD (which is what digitalWrite() does) as many times as you want with the same value, and the pins will stay the same. But if you write to PIND, you'll TOGGLE the bits that are one in the byte you write. (this is supposed to provide a fast/convenient pin-toggle service.)

Thank you, that is exactly what I was inquiring about.

Moses,
after over 100 posts I'd have thought you'd know about code tags by now!

For your simple example it probably doesn't really matter what you do, however, as code gets more complex these things become important. General layout of any program is along the lines of:

  • Read all the inputs
  • Check to see if any input has changed
  • Do any processing required as a result of the change
  • Check to see if there are now outputs that need to be changed
  • Update any outputs as required
  • Start again

Those things can all be interleaved, for example input 1 could be being read then input 2 processed.

Note that every stage depends on the previous stage changing something that then requires subsequent processing; if there's no change to an input there's no need to do the next step, with no need to change the outputs.

For example,
Typically I include some form of clock in my projects (I like to have the time displayed everywhere). Clocks, for human use, can be typically incremented once per second. So, in my code you will see something that checks if the second has incremented (an input) since last time, if (and only if) it has it will calculate the new minute, hour, day etc and send the new date and time to the display. As seconds are increment every second (obviously!) the clock part of the display is updated every second. The clock is not updated more than that, there's no need.

This achieves 2 things to do with saving resources:
On the processor it means it is not spending time working out a new time over and over again when the time has not changed. This frees up resources for other things that might need doing instead, and contributes to the general idea of non-blocking code, the processor only does what needs doing.

If you are a regular reader you will know I use Nextion displays, these communicate through a serial port. By only updating the display when something changes I am keeping the serial port free for things that need updating, making everything more responsive.

All this contributes to faster, more responsive code, but the effects mostly only really show up in big programs, but if you ignore it on small programs then it will cause problems when they get bigger and it will be a lot of effort to re-write everything when the problems show up.

Sometimes on these fora you will see someone has created a very small program that sends stuff to the serial monitor every time around loop() and they cannot understand why their program is not very responsive. The cause is that serial is slow and sending data to the serial monitor on every loop() is slowing everything else down.

PerryBebbington:
Sometimes on these fora you will see someone has created a very small program that sends stuff to the serial monitor every time around loop() and they cannot understand why their program is not very responsive. The cause is that serial is slow and sending data to the serial monitor on every loop() is slowing everything else down.

Thanks for the in depth response (and sorry for not using code tags :roll_eyes: ) I understand exactly what you are saying here. I know that redundant execution of a more complex procedure like serial output can slow things down. What I was questioning was if a sketch was continuously trying to (redundantly) assign an output I/O pin the same value over and over and over, versus using an if/then statement to block the redundant assignment if the value has not changed. Does using an if/then to block redundant assignment of the same value use less processing power than to simply leave the if/then out and have the code continuously assign the same value over and over again redundantly? I interpreted the post before yours as stating that from a processing standpoint, nothing happens if variable (or I/O pin) already has that particular value. Again, I'm asking this in the context of simply assigning a single variable or I/O pin a value, nothing more complex than that which would obviously slow things down.

moses1592:
I know that redundant execution of a more complex procedure like serial output can slow things down. What I was questioning was if a sketch was continuously trying to (redundantly) assign an output I/O pin the same value over and over and over, versus using an if/then statement to block the redundant assignment if the value has not changed. Does using an if/then to block redundant assignment of the same value use less processing power than to simply leave the if/then out and have the code continuously assign the same value over and over again redundantly? I interpreted the post before yours as stating that from a processing standpoint, nothing happens if variable (or I/O pin) already has that particular value. Again, I'm asking this in the context of simply assigning a single variable or I/O pin a value, nothing more complex than that which would obviously slow things down.

I realise that my answer was not a direct answer to your question.
As to:

Does using an if/then to block redundant assignment of the same value use less processing power than to simply leave the if/then out and have the code continuously assign the same value over and over again redundantly?

I don't know but there won't be much in it. Do you own an oscilloscope? Set up a test to see which is faster, something like writing to a pin 1000 times and having another pin change state each time 1000 writes have been made, then another test that does something similar with if(0). You'll have to work out the details.

I think my answer, while not exactly what you asked is closely related and is a direct answer to subject

proper programming structure

. In any case, usually there's a lot more going on that simply writing to or not writing to a pin, usually there's a whole load of other code the might or might not run first before the pin is or is not written to. Writing to the pin is the end of a chain of other events, so we are not just talking about whether you should allow the pin to be written to many times or not, we are (in many cases) talking about whether all that other code should be run or not.

You also have to consider how you are writing to the pin; The Arduino environment comes with the convenient digitalWrite() function, which makes it easy for people new to all this to write to pins, and makes code portable as it is works the same regardless of processor. DigitalWrite() hides the hardware from you, you don't need to worry about how it changes the state of a pin, that's been sorted out for you. That comes at a cost though, there's a whole load of code that you wouldn't need if you manipulated the port registers directly. If you write directly to the port your code will be faster, whether it's worth the bother only you can decide.

My solution to this is to (try to) never do something that doesn't need to be done, so I would not repeatedly write to a pin if that write would not change its state. Maybe in many cases it doesn't matter, but it'd a good habit to get into. There will, of course, be exceptions.

If you are looking to a concrete answer, there isn't one beyond use your judgement in the program you have.

PerryBebbington:
I realise that my answer was not a direct answer to your question.
As to: I don't know but there won't be much in it. Do you own an oscilloscope? Set up a test to see which is faster, something like writing to a pin 1000 times and having another pin change state each time 1000 writes have been made, then another test that does something similar with if(0). You'll have to work out the details.

I think my answer, while not exactly what you asked is closely related and is a direct answer to subject . In any case, usually there's a lot more going on that simply writing to or not writing to a pin, usually there's a whole load of other code the might or might not run first before the pin is or is not written to. Writing to the pin is the end of a chain of other events, so we are not just talking about whether you should allow the pin to be written to many times or not, we are (in many cases) talking about whether all that other code should be run or not.

You also have to consider how you are writing to the pin; The Arduino environment comes with the convenient digitalWrite() function, which makes it easy for people new to all this to write to pins, and makes code portable as it is works the same regardless of processor. DigitalWrite() hides the hardware from you, you don't need to worry about how it changes the state of a pin, that's been sorted out for you. That comes at a cost though, there's a whole load of code that you wouldn't need if you manipulated the port registers directly. If you write directly to the port your code will be faster, whether it's worth the bother only you can decide.

My solution to this is to (try to) never do something that doesn't need to be done, so I would not repeatedly write to a pin if that write would not change its state. Maybe in many cases it doesn't matter, but it'd a good habit to get into. There will, of course, be exceptions.

If you are looking to a concrete answer, there isn't one beyond use your judgement in the program you have.

Thanks Perry, I appreciate the in-depth response. That is what I wanted to know.