Strange error

I'm trying to write a simple library to control the motors of my robotics team's Arduino Mega 2560 robot (I didn't build it! I just program it) with Arduino 1.0.2 on Windows 7.

~~Am using advice here for building and linking: http://provideyourown.com/2011/advanced-arduino-including-multiple-libraries/~~ -- Apparently this was partially incorrect according to WizenedEE, but I always try to ask questions the smart way and that meant searching before asking.

My library builds on the BMSerial library available from Pololu - RoboClaw 2x5A

Halp!! Why am I getting this weird error when I try to build!?

path on my computer lol/arduino-1.0.2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o: In function `__vector_default':
(.vectors+0xdc): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_55' defined in .text.__vector_55 section in core.a(HardwareSerial.cpp.o)

Here is the library:

#ifndef CollectronMotors_h
#define CollectronMotors_h
#include "Arduino.h"
#include "BMSerial.h"
// Requires BMSerial to be installed in your Arduino libraries folder
// BMSerial is bundled with the RoboClaw library availible at: http://www.pololu.com/catalog/product/1495/resources
/*
For linking purposes, using this library requires #include "BMSerial.h" in your sketch in addition to #include "collectronMotors.h"
*/

class CollectronMotors
{
private:
	BMSerial _serial;
	int _inPin;
	int _motorPin;

public:
	// Thanks to http://arduino.cc/forum/index.php/topic,41137.0.html for helping resolve syntax questions.
	CollectronMotors(int inPin, int motorPin) : _serial(_inPin, _motorPin)
	{
		_inPin = inPin;
		_motorPin = motorPin;
	}
	
	int getInPin()
	{
		return _inPin;
	}
	
	int getMotorPin()
	{
		return _motorPin;
	}

	enum Speed
	{
		Fast=0, 
		Medium=1,
		Slow=2
	};

	int divider (Speed speed=Fast)
	{
		switch (speed)
		{
		case Slow: return 10;
		case Medium: return 5;
		default: return 1;
		}
	}

	void Stop(){
		_serial.write(64);
		_serial.write(192);
		return;
	}

	void Foward(Speed speed=Fast)
	{
		_serial.write(64+32/divider(speed));   // channel 1
		_serial.write(192+32/divider(speed));  // channel 2
		return;
	}

	void Backward(Speed speed=Fast){
		_serial.write(64-32/divider(speed));   // channel 1
		_serial.write(192-32/divider(speed));  // channel 2
		return;
	}

	void SmallCorrectionLeft(Speed speed=Fast){
		_serial.write(64+20/divider(speed));   // channel 1
		_serial.write(192+32/divider(speed));  // channel 2
		return;
	}

	void SmallCorrectionRight(Speed speed=Fast){
		_serial.write(64+32/divider(speed));   // channel 1
		_serial.write(192+20/divider(speed));  // channel 2
		return;
	}

	void TurnLeft(Speed speed=Fast){
		_serial.write(64/divider(speed));   // channel 1
		_serial.write(192+32/divider(speed));  // channel 2
		return;
	}

	void TurnRight(Speed speed=Fast){
		_serial.write(64/divider(speed));   // channel 1
		_serial.write(192+32/divider(speed));  // channel 2
		return;
	}

	void RotateLeft(Speed speed=Fast){
		_serial.write(64-32/divider(speed));   // channel 1
		_serial.write(192+32/divider(speed));  // channel 2
		return;
	}

	void RotateRight(Speed speed=Fast){
		_serial.write(64+32/divider(speed));   // channel 1
		_serial.write(192-32/divider(speed));  // channel 2
		return;
	}

};

#endif

Here is a sketch, the only relevant goal being to get this thing to compile/build:

#include "collectronMotors.h"
#include "BMSerial.h"

int motorInPin = 5;
int motorPin = 6;
CollectronMotors motors(motorInPin, motorPin);

void setup()
{
}

void loop()
{
}

[quote author=webpage linked]The remedy is simple – provide a directory specification to the file to include. In this example, to include the “Bounce.h” file, we specify the relative file path this way:

#include "../Bounce/Bounce.h"
That is the relative path in Linux. In Windows, you may need to use backslashes (‘\’) instead. The ‘../’ indicates the parent directory of the current one which is “MyLibrary”. If we followed the path specifier, we go up one directory, which puts us in the library directory, and then down into the Bounce directory. Lastly, we then specify the filename to include.[/quote]

Please don't do any of this. A simple "#include <Bounce.h>" or "#include "Bounce.h"" will work fine once you put the same include in the sketch, and it's possible ../Bounce/Bounce.h won't work since there's two possible places to put libraries. Also, forward slashes work in paths on windows as well, but don't on unix.

Once you've done that, please post compilable code (so the library plus a sketch) so we can get the same error and mess with it a little to try to debug it. Also post for what board you are compiling, because I think I've seen something like this error before and it depends on the board.

WizenedEE:

[quote author=webpage linked]The remedy is simple – provide a directory specification to the file to include. In this example, to include the “Bounce.h” file, we specify the relative file path this way:

#include "../Bounce/Bounce.h"
That is the relative path in Linux. In Windows, you may need to use backslashes (‘\’) instead. The ‘../’ indicates the parent directory of the current one which is “MyLibrary”. If we followed the path specifier, we go up one directory, which puts us in the library directory, and then down into the Bounce directory. Lastly, we then specify the filename to include.

Please don't do any of this. A simple "#include <Bounce.h>" or "#include "Bounce.h"" will work fine once you put the same include in the sketch, and it's possible ../Bounce/Bounce.h won't work since there's two possible places to put libraries. Also, forward slashes work in paths on windows as well, but don't on unix.

Once you've done that, please post compilable code (so the library plus a sketch) so we can get the same error and mess with it a little to try to debug it. Also post for what board you are compiling, because I think I've seen something like this error before and it depends on the board.[/quote]OK. Changed. I modified the original post to reflect your suggestions and added the do-nothing sketch. The error persists.

Compiling for the Arduino Mega 2560.

I'm glad you searched; it's just you found the wrong thing :wink:

On my system, this compiled fine for me (after I commented out the sonar one and fixed the capitalization issue with the other include).

Actually, are you sure that's an error? Will it still upload? I seem to remember that you could safely ignore that message, but if it gives a compile error you obviously can not.

Besides that I don't have a solution, sorry. You could try getting a new version of the compiler, but that's tricky on windows.

It's a compilation error. Won't compile and therefore won't upload either.

I changed the capitalization and still no change on my end. What setup do you have under which it compiled correctly?

I believe this is a frequently asked question. Here's my understanding of the answer.

To use one library from another, it is necessary to include both libraries from the sketch, and make any references to the libraries from sketch-based code. (This can be awkward…) The Bitlash examples that include other libraries are structured this way: bitlash/examples at master · billroy/bitlash · GitHub and yes it can lead to ugly things like passing around function pointers.

I've had no luck including one library directly in another. I hope someone will correct my understanding if it's wrong.

-br

billroy, I may be misunderstanding you, but are you saying it can't be done? Which basically means that the language in the Arduino software is not really C++, but is some craptarded subset of C++?

Well first of all, all I'm sayin' is I don't know how to do it directly, but have found a workaround, and I believe if you search the forum you will find other threads on the subject.

I think your characterization might be a little harsh. This is a feature of the Arduino build environment, not C++. Building sketches based on libraries is easy, in this system. Building libraries that cross-reference each other: I don't know how.

But don't give up. Your post says you've put the BMSerial library in the Arduino libraries/ folder in the usual place. Is there any reason you can't put it directly into your library folder and ship it with your library? I've found #includes work within the library's folder.

(I am still puzzling about why this would be causing a relocation error…)

-br

Oh sure I can throw it in my library folder, since this library I'm writing isn't going to get distributed.

But here is some interesting information I have come up with.

If I take all the members of this library and put them into a sketch with the private data members as global variables and the public methods as loose functions, it builds fine and avr-size says this:

AVR Memory Usage
----------------
Device: Unknown

Program:     666 bytes
(.text + .data + .bootloader)

Data:          9 bytes
(.data + .bss + .noinit)

But the above sketch with library produces these results:

AVR Memory Usage
----------------
Device: Unknown

Program:    4622 bytes
(.text + .data + .bootloader)

Data:        123 bytes
(.data + .bss + .noinit)

As I understand how compilation and linking works, there should not be much of a significant difference between the two versions except for two additional ints. So something is really screwed up about the way Arduino builds.

OK throwing BMSerial in the same folder with my library lets me get rid of the #include "BMSerial.h" in my sketch. But it produces the same cryptic error message.

At this point I'd file an issue here: Issues · arduino/Arduino · GitHub

Provide a link back to the forum thread...

-br

OK, issue filed. Strange error · Issue #1173 · arduino/Arduino · GitHub