Math.h AVR problem

I am totally new to this type of stuff, so maybe you could enlighten me a little.
I am writing a program to get input from a 3-axis accelerometer and a gyroscope,
but I’m having trouble getting my code to work. Every time I try to build the code below,
I get an error:

c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5\libc.a(fp_powsodd.o): In function `__fp_powsodd':
(.text.fplib+0x10): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_mul_sf.o)
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5\libc.a(fp_powsodd.o): In function `__fp_powsodd':
(.text.fplib+0x20): relocation truncated to fit: R_AVR_13_PCREL against symbol `__mulsf3' defined in .text section in c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr5\libgcc.a(_mul_sf.o)
make: *** [XYZ.elf] Error 1
Build failed with 1 errors and 0 warnings...

I don’t know what to do, and I don’t know what this error means.

#include <avr/io.h>
#include <pololu/orangutan.h>
#include <stdlib.h>
#include <math.h>

double vX0 = 0;
double vY0 = 0;
double vZ0 = 0;

double velocityX = 0;
double velocityY = 0;
double velocityZ = 0;

double trueVX = 0;
double trueVY = 0;

double deltaT = .01;					//Assumes data comes in at .01 sec intervals.
const double PI = 3.141592;
int choosing;

double xDisplacement = 0;
double yDisplacement = 0;
double zDisplacement = 0;

long byteX, byteY, byteZ, byteTheta;

double xAcceleration = 0;
double yAcceleration = 0;
double zAcceleration = 0;

double totalDisplacementXY = 0;
double angleRotated = 0;
double theta = 0;

int sensorX()
	int byte = analog_read(PORTC5);
   	return byte;

int sensorY()
   	int byte = analog_read(PORTC4);
   	return byte;

int sensorZ()
   	int byte = analog_read(PORTC3);
	return byte;

int sensorTheta()
   int byte = analog_read(PORTC2);
   return byte;
void getData()
	byteX = sensorX();
	byteY = sensorY();
	byteZ = sensorZ();
	byteTheta = sensorTheta();

	xAcceleration = (5*byteX)/1023;					//This converts a value from 0 to 1023 to g's of acceleration.
	yAcceleration = (5*byteY)/1023;
	zAcceleration = (5*byteZ)/1023;
	theta = (.0033/100)*(((5*byteTheta)/1023)-1.65);//This converts from a number between 0 and 1023 to degrees / cs (hundredth of a second)
 													// and the value of the coefficient divider is equal to the number of decimal places
}													// .0033 needs to be set back (to deciseconds, centiseconds, milliseconds, ect...)
double getTrueVelocity( int chooser ){
	if(angleRotated!=0 && chooser == 1)
			angleRotated += theta;
			trueVX = velocityX * cos ((angleRotated*PI/180));
			return trueVX;
	else if (angleRotated !=0 && chooser == 2)
			angleRotated += theta;
			trueVY = velocityY * cos ((angleRotated*PI/180));
			return trueVY;
		return 0.0;

double getX(){
	choosing = 1;
	velocityX = vX0 + (xAcceleration*9.8*deltaT);			//Consider using just xAcceleration
	vX0 = velocityX;
	return getTrueVelocity(choosing);
double getY(){
	choosing = 2;
	velocityY = vY0 + (yAcceleration*9.8*deltaT);			//Consider using just yAcceleration
	vY0 = velocityY;
	return getTrueVelocity(choosing);
double getZ(){
	velocityZ = vZ0 + (zAcceleration*9.8*deltaT);
	vZ0 = velocityZ;
	return velocityZ;
void getTotalDisplacement(){
	totalDisplacementXY = sqrt ((xDisplacement*xDisplacement)+(yDisplacement*yDisplacement)); //a^2 + b^2 = c^2

int main (int argc, char * const argv[]) {

		xDisplacement += (getX()*deltaT);
		yDisplacement += (getY()*deltaT);
		zDisplacement += (getZ()*deltaT);
		lcd_goto_xy(0, 1);
		while (1){
			xDisplacement += (getX()*deltaT);
			yDisplacement += (getY()*deltaT);
			zDisplacement += (getZ()*deltaT);
			lcd_goto_xy(0, 0);
			print("Dx= ");
			long integer_xDisplacement = xDisplacement / 100;
        	long x_decimal = xDisplacement - integer_xDisplacement * 100;
        	if (x_decimal < 10)
			lcd_goto_xy(0, 1);
			print("Dy= ");
			long integer_yDisplacement = yDisplacement / 100;
        	long y_decimal = yDisplacement - integer_yDisplacement * 100;
        	if (y_decimal < 10)
			//Print stuff out
    return 0;

Any help with getting input would be greatly appreciated.


I googled your error message for about 1 minute and found that the thing to do is to add libm.a to the libraries in your project. Go to Project-> Configuration Options -> Libraries and click add on libm.a.

- Ryan


I have split your post off into its own thread because it really had nothing to do with the thread to which you originally added it. For future reference, you should provide more background about what you’re doing when asking questions like this, such as the controller board you are using (or at least the microcontroller) along with your computer system, compiler, IDE, etc. Finally, it’s a bit much to ask someone to debug such a long, complicated program. It wouldn’t be hard for you to strip away code until the error disappears so that you can at least identify the lines that are causing the error. This would allow you to create a small, simple program that produces this error and is easy for readers to parse.

Like Ryan, when I googled your error, I found this thread almost immediately: … ic&t=76959

(google can really help with mysterious compiler errors).

- Ben

Thanks so much for your help. I just was being stupid and never thought to google the error.
The code compiled after I changed the libraries.

I do have one last question though:
I was wondering what the code for the pins on the Orangutan 328p is from left to right. The code that I wrote isn’t getting
any input from the first five i/o lines (left to right), and I was wondering whether or not it was the sensor and my code, or if it was the fact that I have them connected in the wrong pins.

It’s a bit vague to ask for “the code for the pins” since it really depends on what you are trying to do with them.

The pins are:

The corresponding bit of the PINx register tells you the digital input value of the pin. For example, bit 0 of PINC corresponds to PC0. You can check the value by masking for this particular bit:

if (PINC & (1 << 0))
// pin PC0 value is high

Note that you can use the #defines PORTxx. For example:

if (PINC & (1 << PORTC0))
// pin PC0 value is high

Does this answer your questions? If not, can you post your code (only the relevant portion, please) and a better description of what you’re trying to do?

- Ben

Well, no quiet. I need to read analog input from a 3-axis accelerometer connected to PORTC5, PORTC4, and PORTC3. I have tried using the code I posted in my first post, but I don’t see any change in the data displayed on the screen. I have also tried multiplying the output number by 10,000 to see if it was just a problem with the numbers being too small, but nothing changed, so I assume that I’m just not getting any voltage from the accelerometer.

Well, it should be easy to find the source of your problem. Disconnect your accelerometer and then first connect your analog input to Vcc and then to ground. If your program shows you a 5V reading followed by a 0V reading, the problem is your sensor. If it shows an unchanging value, it’s your code.

You should also get a multimeter for helping to debug situations like this. An oscilloscope would be better, but a multimeter would at least let you see if your sensor is outputting anything (for example, you should be able to see gravitational acceleration as a fixed voltage on the appropriate axis).

- Ben

Yup. The problem is in the sensor. Thanks for all your help.