Go Down

### Topic: Problem with performing fractions with Arduino UNO R3 (Read 2159 times)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.println(analogRead(A0));  //Serial.println(pow(analogRead(A0),(-1,26)));  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]

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 https://github.com/MajicDesigns?tab=Repositories
Parola for Arduino https://github.com/MajicDesigns/Parola
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);  Serial.println("Ready");  delay(5000);  PrevDist=800;  PrevTime=millis();}void loop(){    int in=analogRead(A0);  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.println(analogRead(A0));  //Serial.println(pow(analogRead(A0),(-1,26)));  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