Go Down

### Topic: Problem with performing fractions with Arduino UNO R3 (Read 1 time)previous topic - next topic

#### Cristian_C

##### Jul 25, 2012, 01:27 am
Hello everyone,
I tried to perform some calculations, in particular fractions, to evaluate the speed knowing the position (from a sensor) at different times.

Code: [Select]
CurrentTime=millis();
float Vobst= long(PrevDist-CurrDist)/(long(CurrentTime-PrevTime))*1000;
Serial.print ("ingresso= ");
Serial.print ("Distanza= ");
Serial.print (CurrDist);
Serial.print("[mm] \t Velocità=");
Serial.print(Vobst);
Serial.println("[mm/s]");
Serial.print("current time=");
Serial.print(CurrentTime);
Serial.print("[ms]  previous time=");
Serial.print(PrevTime);
Serial.println("[ms]");
Serial.print(long(PrevDist-CurrDist));Serial.print("/");Serial.print(CurrentTime-PrevTime);
if((PrevDist-CurrDist)<0){
calc=-1.0*((float(CurrDist-PrevDist))/long((CurrentTime-PrevTime)));
} else {calc=(float(PrevDist-CurrDist))/long((CurrentTime-PrevTime));}
Serial.print("=");Serial.println(calc);
Serial.print("0-1="); Serial.println(0-1);

Serial.println("");
[/size]

As it is possible to see in the following print out of serial monitor, if the 2 operands are both positive, there are no problems. If one is negative, it seems to go in overflow and gives unreliable values.
Quote
ingresso= 106

Distanza= 609[mm]     VelocitÃ =191000.00[mm/s]

current time=5000[ms]  previous time=4999[ms]

191/1=191.00

0-1=-1

ingresso= 111

Distanza= 617[mm]     VelocitÃ =0.00[mm/s]

current time=10071[ms]  previous time=5000[ms]

-8/5071=846966.56

0-1=-1

ingresso= 113

Distanza= 551[mm]     VelocitÃ =0.00[mm/s]

current time=15142[ms]  previous time=10071[ms]

66/5071=0.01

0-1=-1

ingresso= 95

Distanza= 741[mm]     VelocitÃ =0.00[mm/s]

current time=20210[ms]  previous time=15142[ms]

-190/5068=847467.87

0-1=-1
[/size]

Anyone had the same problem?
I tried several times to change formats from long to float and to double. But I didn't notice any improvement or different results. Everytime one operand becomes negative, the value is positive and very high.

#### marco_c

#1
##### Jul 25, 2012, 08:37 am
You need to post all the code because you probably have problems with your variable definitions. For a start you are casting to long and float when you are printing and calculating, which may give you diferent results.
Arduino Libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com
Arduino++ blog https://arduinoplusplus.wordpress.com

#### Tom Carpenter

#2
##### Jul 25, 2012, 11:24 amLast Edit: Jul 25, 2012, 11:25 am by TCWORLD Reason: 1
Code: [Select]
calc=-1.0*((float(CurrDist-PrevDist))/long((CurrentTime-PrevTime)));
You are doing a float divided by a long. In which case it won't use floating point division. Try something like this:
Code: [Select]
unsigned long timeDifference = CurrentTime - PrevTime;
unsigned long distanceChage = CurrDist - PrevDist;
calc = -((float)distanceChage/(float)timeDifference);

The same goes for this one:
Code: [Select]
float Vobst= long(PrevDist-CurrDist)/(long(CurrentTime-PrevTime))*1000;
And this one:
Code: [Select]
calc=(float(PrevDist-CurrDist))/long((CurrentTime-PrevTime));

As you are doing pretty much the same calculation 3 times, you could simplify the calculation by finding 'calc' at the start, just after millis. Then 'Vobst' is simply 1000.0 times it.
~Tom~

#### PaulS

#3
##### Jul 25, 2012, 11:28 am
Quote
You are doing a float divided by a long. In which case it won't use floating point division.

Yes, it will. What makes you think it won't?

#### Tom Carpenter

#4
##### Jul 25, 2012, 12:59 pm
I guess I misunderstood how it decides whether or not to use floating point division. Nevermind.
~Tom~

#### gardner

#5
##### Jul 25, 2012, 03:12 pm

if the 2 operands are both positive, there are no problems. If one is negative, it seems to go in overflow and gives unreliable values.
Quote

-190/5068=847467.87

This is a clue.  -190 is 2^32 - 190 + 1, if you were to cast it to an unsigned long.  (2^32 - 190 + 1) / 5068 = 847,467.8 as you get here.  Given we can't see your code, my guess is that wherever -190 comes from, it is being converted to an unsigned long somewhere before being cast to a float for the division.

#### Cristian_C

#6
##### Jul 25, 2012, 08:32 pm
Hello everybody,
I'm quite new with Arduino and programming with C-like code. So probably I made some mistakes in assigning of variables formats.

Following the complete code. I know that is performing 3 times the same calculation, but during the test of the distance sensor I noticed that something was wrong, so I decided to print out as much as possible and see where the problem arises.
So I started with declaring all variables unsigned long. And then after seeing that the results had no sense I decided to declare variables as float.

Code: [Select]
unsigned long CurrDist;
unsigned long PrevDist;
unsigned long CurrentTime;
unsigned long PrevTime;
unsigned long Vobst;
float calc;

void setup() {
Serial.begin(9600);
delay(5000);
PrevDist=800;
PrevTime=millis();
}
void loop(){
if (in<=81) {CurrDist=800;}
else if (in<=122){CurrDist=800-0.7317*(in-81)*10;}
else if (in<=143){CurrDist=500-0.4762*(in-122)*10;}
else if (in<=184){CurrDist=400-0.2439*(in-143)*10;}
else if (in<=225){CurrDist=300-0.1220*(in-184)*10;}
else if (in<=266){CurrDist=250-0.1220*(in-225)*10;}
else if (in<=327){CurrDist=200-0.0820*(in-266)*10;}
else if (in<=471){CurrDist=150-0.0347*(in-327)*10;}
else if (in<=563){CurrDist=100-0.0217*(in-471)*10;}
else if (in<=604){CurrDist=80-0.0244*(in-563)*10;}
else if (in<=645){CurrDist=70-0.0244*(in-604)*10;}
else {CurrDist=55;}

CurrentTime=millis();
float Vobst= long(PrevDist-CurrDist)/(long(CurrentTime-PrevTime))*1000;
Serial.print ("ingresso= ");
Serial.print ("Distanza= ");
Serial.print (CurrDist);
Serial.print("[mm] \t Velocità=");
Serial.print(Vobst);
Serial.println("[mm/s]");
Serial.print("current time=");
Serial.print(CurrentTime);
Serial.print("[ms]  previous time=");
Serial.print(PrevTime);
Serial.println("[ms]");
Serial.print(long(PrevDist-CurrDist));Serial.print("/");Serial.print(CurrentTime-PrevTime);
calc=(float(PrevDist-CurrDist))/long((CurrentTime-PrevTime));
Serial.print("=");Serial.println(calc);
Serial.print("0-1="); Serial.println(0-1);

Serial.println("");

PrevDist=CurrDist;
PrevTime=CurrentTime;
delay(5000);
}

The thing that seem very strange to me is that even for small negatives values the problem occurs:
Quote
-8/5071=846966.56

Go Up

Please enter a valid email to subscribe