# Arduino Serial Output Gone Wild!

I'm having a slight problem that I'm unable to work out. I am using an arduino Uno to print an incremental, but predefined wheel circumference. This is all working beautifully except it gives a negative reading during execution, and then runs into the positive etc. Without being exact, the output is something like the following:

1.85, 3.71, 5.56, 7.41, 9.27, 11.15....

When this multiple reaches 32.00 or greater, it then counts negatively back down to zero, then positively up to 32.00 again.

I can't quite work out why this would be, so hoping that one of you guys would be able to shed some light. The code is as follows:

``````#include <Arduino.h>

int InterruptPin = 2;
int circ = 1854; //mtrs
int km = 0;

void calculate(){
km = km + circ;
//float temp = km / 1000;
float temp = (float)km / (float)1000;
Serial.println(temp);
}

void setup(){
pinMode(InterruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(2), calculate, RISING);
Serial.begin(9600);
}

void loop(){

}
``````

`km` is never reset but continously incremented.

``````km = km + circ;
``````

This leads to an overflow of the value after some time.

When you declare `int km;`, then `int` on an Arduino Uno is `int16_t`, it thus has a maximum positive value of `2^15 - 1 = 32767`. Since `circ` is constant `1854`, after executing the ISR a total of `CEIL(32767 / 1854) = 18` times, `km` becomes greater than that maximum positive value. Thus an integer overflow occurs which takes you back to the maximum negative value of the `int16_t`. (See https://en.wikipedia.org/wiki/Integer_overflow)

You might want to use `uint32_t` or similiar from `stdint.h` if you want to cover a greater value range. I think however your underlying algorithm is flawed, since even then `km` will overflow after some later time. You must reset it at some point or only store the number of revolutions, which is a much smaller number. If you want to get the traveled distance then, you take the number of revolutions and multiply it by the circumference.

Also you should not not use any `Serial` printing within in interrupt service routine! And you should also declare your used interrupt variables as `volatile`. Read this article for more info.

• I would recommend `unsigned long` for large integer values. (it is uint32_t on 8-bit AVR) – Juraj Apr 14 '18 at 20:09
• Thanks, some very constructive critisism and a brilliant explanation. – user4163554 Apr 14 '18 at 20:36