0

I was experimenting with for loops when I noticed that a simple increment loop executes faster than a decrement loop. I can't think of any reason why it should be like that. Is there something in my code that is causing the different in execution speed?

The code is as follows:

// Global Variables
const int spk = 7;
const int led = 6;
int j = 0; // counter variable

void setup() {

  pinMode(spk, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
} // end of setup

void loop() {


  tone(spk, 300, 500); // first note with duration

  // increment loop
  for (j=0; j <= 500; j = j + 1) {
    digitalWrite(led, HIGH);
    Serial.println(j);
  } // end 1st note loop

  tone(spk, 100, 500); // second note with duration

  // decrement loop

  for (j = 500; j >= 0; j=j-1) {
    digitalWrite(led, LOW);
    Serial.print("the value is=");
    Serial.print("\t");
    Serial.println(j);
  } // end 2nd Note loop


} // end setup

2 Answers 2

1

Comment out these 2 lines

Serial.print("the value is=");
Serial.print("\t");

And report back on the speed difference. Why not add a reading of micros() before and after each loop and see how much difference there really is? All time variables are unsigned long.

startTime = micros();
// your loop
endTime =  micros();
duration = endTime - startTime;
Serial.println (" "); // line break
Serial.print ("duration in uS = ");
Serial.println (duration);

I edited to add some missing )s and a 2nd line break.

3
  • Yes the extra serial prints in the decrement loop were adding the extra time. However, after adding the mircros before and after each loop and removing all extra print statements I still find the decrement loop takes 60 to 80 microsecond longer. Is it usual?
    – Zaffresky
    Commented Mar 27, 2020 at 13:06
  • I don't know. I don't think I've ever used a decrementing for:next loop. Might also be something with setting a pin low vs high. You could try fastdigitalWrite() instead, see if that makes a difference (in the IDE already? maybe have to pull it from guthub?). There is a way to look at the assembly code that is created, see what is actually being run. Nick Gammon used to post examples like that, not sure how he got the assembly out of the compile process.
    – CrossRoads
    Commented Mar 27, 2020 at 15:23
  • Ah it's fine :) Doesn't really make that big of a difference for now. Going after the assembly code would be too complicated and don't even know how to go about it.
    – Zaffresky
    Commented Mar 27, 2020 at 15:31
0

In the code you posted, the decrement loop has two more Serial.print() statements.

Serial.print() takes a lot of time and while it's useful for debugging, it sometimes can cause additional bugs because of the extra delay it introduces if you are running time-sensitive code.

Consider for using Serial.print("the value is=\t" + itoa(j,10));

"itoa" converts an integer to an array of characters (aka string). As Juraj said, it takes another two arguments which are the buffer to store the output string and the base to which it converts the incoming number to be represented by (eg: 10 is decimal, 16 is hexadecimal). It returns a pointer to the output string which is essentially the same as the second argument but AFAIR you can omit the second argument and use it's return value.

1
  • + doesn't concatenate char arrays. itoa has more parameters
    – Juraj
    Commented Mar 17, 2020 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.