I’ve run into a strange problem when trying to use the abs() function in a sketch that includes both the
SPI and SoftwareSerial libraries (IDE v1.0.1, UnoR3).
With both of those libraries included, feeding a long variable to abs() results in abs() treating the input
like an int and overflowing if the value was greater than 32,767.
The minimal example is as follows:
// Including SPI and SoftwareSerial at the same time
// appears to make the abs() function fail.
#include <SPI.h>
#include <SoftwareSerial.h>
void setup(void)
{
Serial.begin(115200);
}
void loop(void)
{
long myLong = -35001;
long myLong2;
long myLong3;
Serial.print("myLong: ");
Serial.println(myLong);
if (myLong < 0) {
myLong2 = -myLong;
}
Serial.print("myLong * -1: ");
Serial.println(myLong2);
myLong3 = abs(myLong);
Serial.print("abs(myLong): ");
Serial.println(myLong3);
while(1); // pause permanently
}
The output I get from that sketch is:
myLong: -35001
myLong * -1: 35001
abs(myLong): 30535
However, if I comment out either the SPI.h or SoftwareSerial.h include (leaving the other intact), the abs() function begins working correctly:
myLong: -35001
myLong * -1: 35001
abs(myLong): 35001
One solution is already present in the code, just replace abs() with an if statement to switch sign when the value of myLong is less than zero. This works fine in every instance.
My question is: can anyone comment on why this behavior with abs() is popping up when using this particular combination of libraries? A quick glance at SoftwareSerial.cpp and SPI.cpp didn’t show anything glaring, but I don’t feel like I know enough to pick out the problem even if it’s staring me in the face.
// Arduino 0012 workaround
#undef int
#undef char
#undef long
#undef byte
#undef float
#undef abs
#undef round
Normally, #include <Arduino.h> is inserted before the first line of c code (so after all includes). However, SPI.h includes Arduino.h first, which is then undefined in SoftwareSerial.h
I see, so if I had happened to simply put #include <SoftwareSerial.h> before#include <SPI.h>, I wouldn’t have run into this problem. Either way, it looks like one more reason to just avoid using abs() in my code, and use other methods, as you suggest.
Either way, it looks like one more reason to just avoid using abs() in my code
Or, be sure to explicitly include Arduino.h in your sketch, after all other include files.
That 0012 workaround in SoftwareSerial.h should earn someone an ass kicking. If those symbols cause a problem in 0012, the undef'ing should occur inside a #ifdef/#endif block.
Either way, it looks like one more reason to just avoid using abs() in my code
Or, be sure to explicitly include Arduino.h in your sketch, after all other include files.
Won't work...
#ifndef Arduino_h
#define Arduino_h
...
#endif
As Arduino.h is included at the beginning of the sketch by the IDE, the second (manual) inclusion in your sketch will have no effect whatsoever.
That 0012 workaround in SoftwareSerial.h should earn someone an ass kicking. If those symbols cause a problem in 0012, the undef'ing should occur inside a #ifdef/#endif block.