0
votes

I am writing a delay function for Arduino to be used in a project. The reason is that TIMER0 (the default timer used for Arduino delay) is occupied with PWM control. The test code for the delay function is as follows:

int count;
unsigned long int sec;

void delay_ms (uint16_t millisecond) {
  sec = ((16000000/12)/1000)*millisecond;
  for (count = 0; count < sec; count ++);
}

void setup (){
Serial.begin(9600);
}

void loop (){
  Serial.println('a');
  delay_ms(1000);
  Serial.println('b');
  delay_ms(1000);
}

This setup simply prints a and b with a 1-second delay between each. It's working properly but before that there were other setups I used that did not work. The changes are:

  • Declaring count as an unsigned long => This led to the delay function working properly but only for the first time.
  • Declaring and intializing count as an int in the initialization step of the for loop => The delay function does not work as intended, at all.

Based on the knowledge provided by Arduino Reference on Unsigned Long and Int, I'd thought that they are essentially the same in this case. Therefore, I'd like to get some clarification in terms of how the data is processed by the loop as well as the delay function.

1

1 Answers

3
votes

You tagged the question with arduino-uno, and the link you provide for int explicitly say that int on an Uno is 16 bits, with a range of -32768 to 32767:

On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value. This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1).

Now ((16000000/12)/1000)*1000 (for a delay of 1000) is 1333333, which is way over the limit of an int (even an unsigned int). That means your int variable count will overflow in the loop and you will have undefined behavior.

What happens practically when count overflow is that it becomes negative (since the Uno is using two's complement for negative numbers). Then you count up to zero and the possitive number until it overflows again, leading to count < sec to always be true and give you an infinite loop.

The solution is, of course, to use types which can handle such large numbers as yours without problems. Like e.g. unsigned long.


Oh, and stop using global variables. Both count and sec should be local inside your delay function. And stop making your own delay functions, AFAIK the Arduino framework should have delay functions you can use. Lastly, Arduino is programmed in C++, not C, although without the full and proper standard library (it uses its own framework instead).