Pages: [1]   Go Down
Author Topic: Problem with performing fractions with Arduino UNO R3  (Read 831 times)
0 Members and 1 Guest are viewing this topic.
Udine
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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]

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.

If anyone had and solved this problem, could please help me?[/size]
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1259
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Leeds, UK
Offline Offline
Edison Member
*
Karma: 78
Posts: 1719
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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:
unsigned long timeDifference = CurrentTime - PrevTime;
unsigned long distanceChage = CurrDist - PrevDist;
calc = -((float)distanceChage/(float)timeDifference);

The same goes for this one:
Code:
float Vobst= long(PrevDist-CurrDist)/(long(CurrentTime-PrevTime))*1000;
And this one:
Code:
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.
« Last Edit: July 25, 2012, 04:25:53 am by TCWORLD » Logged

~Tom~

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 78
Posts: 1719
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I guess I misunderstood how it decides whether or not to use floating point division. Nevermind.
Logged

~Tom~

Ontario
Offline Offline
God Member
*****
Karma: 24
Posts: 862
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Udine
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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

Thanks in advance[/size]
Logged

Pages: [1]   Go Up
Jump to: