Pages: [1]   Go Down
Author Topic: Arithmetic Operator question  (Read 912 times)
0 Members and 1 Guest are viewing this topic.
Sweden, Malmö
Offline Offline
Full Member
***
Karma: 2
Posts: 200
Rooky
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int Z;

float GZ = analogRead(Z)*0.0048828125 - 1.66;

Hope somebody can help me to understand what is wrong with the above piece of code.
As you know an analog reading is a number between 0-1023.
So let us assume that analogRead(Z) is at a given time 250, that in multiplication with 0.0048828125 will return 1.220703125.
Then 1.220703125 - 1.66 should return -0.439296875.
But it does return a positive number of 0.439296875.
The intresting part to me is that if we go below -1.000 then the value return from the same code will return the correct negativ value of
-1.000.  :-?

This is a part of a bigger code that calculates a analog g-sensor value in to volts and then to g force. Therfore 5/1024 = 0.0048828125 for volt calculation.
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hulk,

Assuming Z is an uninitialized automatic (stack) variable and you are reading from pin Z, you are (potentially) reading from an undefined pin.  Therefore the return from analogRead is unpredictable.

The expression assigned to GZ works fine as long as analogRead() is indeed returning a number between 0 and 1023.

Mikal

Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Hulk, I suspect the problem is elsewhere in your code if the only problem is the sign.

Not sure it will help in your app, but wherever possible I like to convert floating point values to longs by multiplying the value by the number of decimal places necessary to give you the precision you need. This allows the code to be smaller and faster.

 The following gives GZ that is the actual value times 10,000.  

long GZ = analogRead(Z)*488 - 166000;
Logged

Sweden, Malmö
Offline Offline
Full Member
***
Karma: 2
Posts: 200
Rooky
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mikalhart,

You are correct, in my case it is defined so the value is being 0-1023, i can see the value of let us say 250 just by doing a simple serial print command.
In my case the pin is: int Z = 5;
Any other thoughts or did i missunderstand your reply ?
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why do you suspect that the sign is wrong?  I did a local test and it worked fine for all possible values 0-1023.  Like mem, I suspect the problem is elsewhere.

Mikal
Logged

Sweden, Malmö
Offline Offline
Full Member
***
Karma: 2
Posts: 200
Rooky
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

m & m

I have tested and edited my code to get some good results, but...
I did try the long command and it was returning me negative numbers all the time. Could it be the printDouble function i am using or just me as usuall  smiley .
One code below that can be used with serial.print and one with the KS0108 library.

This one will run to 0.3 and then just jump to -1
Code:

  int X = 5;

//////////////////////////////////////////////////////////////////////////
void printDouble( double val, unsigned int precision){

    Serial.print (int(val));  //prints the int part
    Serial.print("."); // print the decimal point
    unsigned int frac;
    if(val >= 0)
      frac = (val - int(val)) * precision;
    else
       frac = (int(val)- val ) * precision;
    int frac1 = frac;
    while( frac1 /= 10 )
        precision /= 10;
    precision /= 10;
    while(  precision /= 10)
        Serial.print("0");
    Serial.println(frac,DEC) ;
}
//////////////////////////////////////////////////////////////////////////


void setup(){

Serial.begin(9600);

}


void loop(){

  float GX = analogRead(X)*0.0048828125 - 1.66;
  GX = GX / 0.333;
  printDouble(GX, 4);
  delay(100);
  
  }

This one will go all the way from 0-0.99 and then suddenly go to correct negativ value of -1.0.....
Code:

#include <Arial14.h>
#include <ks0108.h>

  int X = 5;
  
///////////////////////////////////////////////////////////////////////////////////// printDouble
 void printDouble( double val, byte precision){
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

  GLCD.PrintNumber( (long)val);  //prints the int part
  if( precision > 0) {
    GLCD.PutChar('.');
    unsigned long frac;
    unsigned long mult = 1;
    byte padding = precision -1;
    while(precision--)
       mult *=10;
      
    if(val >= 0)
      frac = (val - int(val)) * mult;
    else
      frac = (int(val)- val ) * mult;
    unsigned long frac1 = frac;
    while( frac1 /= 10 )
      padding--;
    while(  padding--)
      GLCD.PutChar('0');
    GLCD.PrintNumber(frac) ;
  }
}

float drawSine(int angle){
  float sine;
//    if(angle <= 0)  
        sine = sin(PI / 180 * angle);
  return sine;              
}
//////////////////////////////////////////////////////////////////////////


void setup(){
  
GLCD.Init(NON_INVERTED);
GLCD.SelectFont(Arial_14);
Serial.begin(9600);

}


void loop(){

  float GX = analogRead(X)*0.0048828125 - 1.66;
  GX = GX / 0.333;
  GLCD.FillRect(04, 45, 100, 15, WHITE);
  GLCD.GotoXY(05, 45);
  printDouble(GX, 2);
  delay(100);
  
  }


Good to have you back mem and thanks for the fast reply mikalhart!
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For your serial output, try the code in reply #6: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1207226548

The GLCD version is due to a 'feature' in the library. The PrintNumber integer print routine does not put a sign if the value is 0, which it will be when value is less than 1. But the fractional part of the print routine assumes the sign has been printed.

A temporary hack is to add the following before the call to GLCD.PrintNumber
if ( val > -1.0 && val < 0)
    GLCD.PutChar('-');


A better fix is to always print a minus sign on negative values and pass the abs value to PrintNumber

I am not quite back, I return to the UK on the weekend
« Last Edit: October 22, 2008, 05:01:31 pm by mem » Logged

Sweden, Malmö
Offline Offline
Full Member
***
Karma: 2
Posts: 200
Rooky
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mem,

I see, thanks.
Will there possibly be a change of the KS0108 library in the future or the temporary solution is here to stay ?
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will include the fix in the next version of the library
Logged

Pages: [1]   Go Up
Jump to: