Go Down

Topic: Problem with performing fractions with Arduino UNO R3 (Read 935 times) previous topic - next topic

Cristian_C

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]

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]

marco_c

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

Tom Carpenter

#2
Jul 25, 2012, 11:24 am Last 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

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

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

gardner


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

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


Thanks in advance[/size]

Go Up