1. ## Formula Problem

I have a formula that gives the correct result in C++ Builder, but not in AVR Studio 6.0. I am at loss as to why this is the case.

Below is the code.

Ray.

Code:
```uint16_t x1, x2, y1, y2;
uint16_t Q11, Q12, Q21, Q22;
uint16_t xAxis, yAxis;
float InterpVal;
uint16_t finalValue;

x1 = 1000;
x2 = 2000;
y1 = 400;
y2 = 600;
Q11 = 0;
Q12 = 0;
Q21 = 100;
Q22 = 200;
xAxis = 1500;
yAxis = 450;

InterpVal = (float)(((x2 - xAxis) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q11) +
(float)(((xAxis - x1) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q21) +
(float)(((x2 - xAxis) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q12) +
(float)(((xAxis - x1) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q22);

finalValue = (uint16_t)InterpVal;    // Gives the value 1753 when 62 is the correct value.``` 2. I don't see anything wrong.
How exactly are you printing the value?
A uint16_t is not necessarily the same as an unsigned short, so if you're just using %hu that could be the problem.
Try
Code:
`    printf("%"PRIu16"\n", finalValue);  // include <inttypes.h>` 3. Originally Posted by oogabooga I don't see anything wrong.
How exactly are you printing the value?
A uint16_t is not necessarily the same as an unsigned short, so if you're just using %hu that could be the problem.
Try
Code:
`    printf("%"PRIu16"\n", finalValue);  // include <inttypes.h>`
The returned value is used in other code that controls a H-Bridge motor. In this case the motor is driven incorectly. When sent via serial USB the value is wrong. When sent to a LCD display it is wrong also.

The same code used in C++ Builder gives the correct value.

This is my full embedded test code that sends the value to a LCD display.

Code:
```#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "lcd.h"

void init_Things(void)
{
lcd_init(LCD_DISP_ON);
lcd_clrscr();

_delay_ms(10);
}

int main(void)
{
init_Things();

char buffer;
char buf;
strcpy(buffer, "Value: ");

uint16_t x1, x2, y1, y2;
uint16_t Q11, Q12, Q21, Q22;
uint16_t xAxis, yAxis;
float InterpVal;
uint16_t finalValue;

x1 = 1000;
x2 = 2000;
y1 = 400;
y2 = 600;
Q11 = 0;
Q12 = 0;
Q21 = 100;
Q22 = 200;
xAxis = 1500;
yAxis = 450;

InterpVal = (float)(((x2 - xAxis) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q11) +
(float)(((xAxis - x1) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q21) +
(float)(((x2 - xAxis) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q12) +
(float)(((xAxis - x1) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q22);

finalValue = (uint16_t)InterpVal;    // Gives the value 1753 when 62 is the correct value.

utoa(finalValue, buf,10);
strcat(buffer, buf);
lcd_gotoxy(0,0);
lcd_puts(buffer);

while(1)
{
}
}``` 4. Try this:
Code:
```utoa((unsigned)finalValue, buf,10);
```

Let me know if it works. 5. Originally Posted by oogabooga Try this:
Code:
```utoa((unsigned)finalValue, buf,10);
```

Let me know if it works.

No change still get 1753.

Ray. 6. After I posted it I realized that it wasn't going to work since the promotion would occur automatically.
I'm stumped. Hopefully someone else can give you an answer.

Are you compiling with the highest warning level available? 7. Take one subexpression from your formula (in this case the numerator portion on line 39 in post #3):
Code:
`((x2 - xAxis) * (y2 - yAxis))`
Substituting values gives:
Code:
`(2000 - 1500) * (600 - 450) = 500 * 150 = 75000`
75000 is too big to fit in a 16 bits. Depending on how the compiler evaluates the different parts of the expression, it may be trying to store that value in a 16 register for further computations. The overflow could mess up the rest of the computation. Try making everything a uin32_t instead and see if that helps.

EDIT: Everything but finalVal I guess, since whatever uses that value expects only 16 bits. 8. My first suggestion would be to break apart that large calculation into individual variables so you can check each part.

Also with the numbers given you can comment out the first and third part of the equation, since they will equal zero with the numbers provided.

Code:
```...
uint16_t first, second, third, fourth;
...
first = xAxis - x1;
second = y2 - yAxis;
third = x2 - x1;
fourth = y2 - y1;

InterpVal = /*(float)(((x2 - xAxis) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q11) + */
(float)(((xAxis - x1) * (y2 - yAxis)) / (float)((x2 - x1) * (y2 - y1)) * Q21) +
/* (float)(((x2 - xAxis) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q12) + */
(float)(((xAxis - x1) * (yAxis - y1)) / (float)((x2 - x1) * (y2 - y1)) * Q22);```
Look at each individual part of the equation, looking for numbers that may overflow the type. Your float casts are spanning several of these calculations so the intermediate calculations may still be a problem.

And be sure that all the required include files have been included. Something like:

Code:
```#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>```
I included stdio.h in order to use printf() but you may not be able to use printf() on your embedded system so you may not need this header.

Jim 9. Originally Posted by anduril462 Take one subexpression from your formula (in this case the numerator portion on line 39 in post #3):
Code:
`((x2 - xAxis) * (y2 - yAxis))`
Substituting values gives:
Code:
`(2000 - 1500) * (600 - 450) = 500 * 150 = 75000`
75000 is too big to fit in a 16 bits. Depending on how the compiler evaluates the different parts of the expression, it may be trying to store that value in a 16 register for further computations. The overflow could mess up the rest of the computation. Try making everything a uin32_t instead and see if that helps.

EDIT: Everything but finalVal I guess, since whatever uses that value expects only 16 bits.

Changed them to uint32_t except for finalVal and I now get the correct value....Very happy..  Popular pages Recent additions 