Shop OBEX P1 Docs P2 Docs Learn Events
Question about floating point operations... — Parallax Forums

Question about floating point operations...

Michael101Michael101 Posts: 3
edited 2005-11-24 04:25 in General Discussion
Hey guys,

···· I am attempting to measure a pulse width that represents a magnetic heading for an Acroname Devantech Electronic compass.· The pulse range is from 123 to 4228.· If you subtract the total range of the pulses (4228-123) you get 4105.· If you divide 4105, the entire possible pulse range by 360 (degrees in a circle), you receive a conversion factor of 11.4.

···· When the pulse comes in you need to divide the pulse by the conversion factor to receive the correct heading in degrees.· The problem is - no floating point supported by the Javelin, at least not without some work.· I tried a number of different things including using a conversion factor of 114 (divide the actual pulse width by 114) and then multiplying by 10, but the loss of precision is giving me poor heading readings.

····· I also downloaded and successfully ran the Float32 APP mod for the Javelin which works great, however, it uses a lot of memory and processing power to perform a floating point calculation.· I would like to use the Float32 APP mod, however, I fear with an entire robot operating system, it may not have adequate memory or processing power to complete the job.


····· Below is what I coded initially to give you an idea of what I am attempting.· I am new to the Javelin and embedded programming, however, I feel I need an efficient way to get around the non-floating point capability of the chip.· I have other sensors I am adding that also measure pulse width that I would like to convert to meaningful values.

····· On possible solution I could not figure out is how to strip off the sign bit to utilize an integer to its full potential.· The manual mentions using a left bit shift to do this but does not give an adequate (for me)explanation.


···· Thanks,

····· Mike

//11-21-2005
//This converts the pulse width of the compass into degrees
//for the Acroname Electronic Compass

import stamp.core.*;

public class CompassCalibration {
static int pulse;
static int heading;
static int maxPulse = 4228;
static int minPulse = 123;
static int conversion = 11;//coversion factor from pulse width the actual
//to degrees of heading 0-360
//value should be 11.4


public static void main() {


while (true) {
pulse = CPU.pulseIn(15000,CPU.pin14, true);

if(pulse<minPulse || pulse > maxPulse) {
heading = 360;
System.out.print("Heading = ");
System.out.println(heading);

}

else{

heading = (pulse-minPulse)/conversion;

if(heading>360){
heading = 360;
System.out.print("Heading = ");
System.out.println(heading);

}

else{
System.out.print("Heading = ");
System.out.println(heading);


}

}

}
}
}

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-24 02:50
    Dividing by 11.4 is multiplying by 0.087719.

    Take a look a my class UnsignedIntMath.java here

    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/math/

    It allows you to multiply an unsigned integer with an unsigned fraction, without the overhead
    of the floating point class.

    I used it in my ScaledTimer16.java class here

    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/core/

    It has example formulae that show how to use the UnsignedIntMath class.

    regards peter
  • Michael101Michael101 Posts: 3
    edited 2005-11-24 04:07
    Peter,

    ···· Thanks for the link to your code.· It looks like it will work very efficiently for what I need to do.· I will try it tomorrow on the stamp.· In order to multiply·4105·times 0.087719, I would send what parameters to your method?

    int pulseSpread = 4105;
    int conversion = 87719; //obviously too big as a signed integer


    UnsignedIntMath.umulf(pulseSpread,conversion);



    How do I accomplish a bit shift properly?


    Mike


    /**
    * Multiply unsigned int with unsigned fraction.
    *
    * @param value Unsigned int to multiply
    * @param fraction Multiplier (represents Multiplier / 65536)
    * @return value * fraction rounded off integer result
    */
    public static int umulf(int value, int fraction) {
    int i, result=0, rest=0;
    for (i=1; i<17; i++) {
    if (fraction < 0) { //b15 set
    result += (value >>> i); //accumulate integer result
    rest += ( (value & ((1<<i)-1)) << (16-i) ); //accumulate rest R/65536
    if (CPU.carry()) result++; //update result if rest overflows
    }
    fraction <<= 1; //next bit
    }
    if (rest < 0) result++; //roundoff
    return result;
    }

    }

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-24 04:08
    You could also try to multiply by using 5 instead of 10.

    5 * 4105 = 20525·· no overflow (your *10 would give 41050 which is -24886)

    5 * 11.4 = 57

    So try heading = ((value - 123) * 5) / 57

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-24 04:11
    1/11.4 = X / 65536

    X = 65536 / 11.4 = ·5748.77 so your fraction int is 5748 or 5749

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-11-24 04:17
    A << n shifts left value A by n bits, '0' bits shift in at LSB

    A >>> n shifts right value A by n bits, '0' bits shift in at MSB

    A >> n shifts right value A by n bits, preserving the sign bit (b15)

    regards peter
  • Michael101Michael101 Posts: 3
    edited 2005-11-24 04:25
    Peter,


    The formula heading = ((value - 123) * 5) / 57 works perfectly. Now I just need to brush up on my algebra. I am sure I will use your UnsignedMath class as it is very small and efficient if I run into other problems requiring floating point.

    I was looking at the Yahoo site and you have posted some very nice work. I will definately use some of your ideas.

    Thank you again for your help!

    Regards,

    Mike
Sign In or Register to comment.