Shop OBEX P1 Docs P2 Docs Learn Events
HM55B compass module and Javelin — Parallax Forums

HM55B compass module and Javelin

Don FrenchDon French Posts: 126
edited 2005-10-05 22:16 in General Discussion
Has anyone written the Java equivalents of the Basic code that comes with the HM55B compass module?·· So far I only looked at the TestDigitalCompass.bs2 program that comes with the package, and it doesn't look that hard except you need an ATN method and some code to simulate the·*/ (multiply middle) Basic·operator.· It appears that there is an ATN method on the yahoo javelinCode site, so I guess that solves the hardest part.· But if anyone already did the whole thing, I won't need to reinvent the wheel.

Comments

  • Don FrenchDon French Posts: 126
    edited 2005-09-06 00:49
    Ok, I wrote something but it doesn't seem to really work.· Here is my code. I used the atan2 method from the IntegerMath class that is up on the Yahoo site.· x and y are globally defined elsewhere.· I also tried reversing the order of the parameters sent to atan2, with no help.· Any ideas?

    ··· private static void readDirection(){
    ····· int angle;· // Store angle measurement
    ····· int prevAngle = 0;
    ····· while(true){
    ······· getCompassAxes();
    ······· angle = IntegerMath.atan2(-y, x); // Convert x and y to brads
    ······· angle = angle * 1406 / 1000;·· // mult by 1.406 (360/256) to convert to degrees
    ······· if(prevAngle != angle)
    ········· System.out.println(angle);·· // Display axes and degrees
    ······ prevAngle = angle;
    ····· }
    ··· }

    ··· private static void getCompassAxes(){
    ····· int dinDout = CPU.pin9;····· // transceives to/from Din/Dout
    ····· int clkHM55B = CPU.pin11;···· // sends pulses to HM55B's Clk
    ····· int enableHM55B = CPU.pin10;···· // enables HM55B
    ····· int statusHM55B = 0;
    ····· int resetHM55B = 0x0000;········ // Reset command for HM55B
    ····· int measureHM55B = 0x4000;······ // Start measurement (before shifting L)
    ····· int reportHM55B = 0x6000;········ // Get status/axis values (before shifting L)
    ····· int readyHM55B = 0x000C;········ // 1100 -> Done, 00 -> no errors
    ····· int mask = 0x7c00;···················// before shifting left one bit
    ····· mask = mask << 1;················ // to make it 0xF800
    ····· measureHM55B = measureHM55B << 1;· // to make it 0x8000
    ····· reportHM55B = reportHM55B << 1;· // To make it 0xC000
    ····· CPU.writePin(enableHM55B, ON);·· // ON is defined as true, OFF as false. (The enable pin is inverted)
    ····· CPU.writePin(enableHM55B, OFF);· // Prepare the HM55B for a command
    ····· CPU.shiftOut(dinDout, clkHM55B, 4, CPU.SHIFT_MSB, resetHM55B);· // Give it the reset command
    ····· CPU.writePin(enableHM55B, ON);
    ····· CPU.writePin(enableHM55B, OFF);
    ····· CPU.shiftOut(dinDout, clkHM55B, 4, CPU.SHIFT_MSB, measureHM55B);· //·Send the measure command
    ····· statusHM55B = 0x00;······················· // Clear previous status flags

    ····· while( statusHM55B != readyHM55B){··· // Status flag checking loop
    ······· CPU.writePin(enableHM55B, ON);
    ······· CPU.writePin(enableHM55B, OFF);
    ······· CPU.shiftOut(dinDout, clkHM55B, 4, CPU.SHIFT_MSB, reportHM55B);
    ······· statusHM55B = CPU.shiftIn(dinDout, clkHM55B, 4, CPU.POST_CLOCK_MSB );
    ····· }
    ···········
    ······// Cool!· the chip is ready to give up its data

    ···· // The BASIC routine gets all 22 bits with one SHIFTIN, but we have to do two.
    ···· //·· Could this be the problem?

    ····· x = CPU.shiftIn(dinDout, clkHM55B, 11, CPU.POST_CLOCK_MSB);
    ····· y = CPU.shiftIn(dinDout, clkHM55B, 11, CPU.POST_CLOCK_MSB);

    ····· CPU.writePin(enableHM55B, ON);··· //· Disable·chip
    ····· if( (y & 0x400) > 0) y = y | mask;· // if 11-bit is on, propagate the mask bit
    ····· if( (x & 0x400) > 0) x = x | mask;· // ditto
    ··· }
    }

    The Basic·source that I converted to Java·is available here:
    ····· ·http://www.parallax.com/detail.asp?product_id=29123

    So, what happens when I run this program?· I get output but it isn't reasonable.· The angle values range from about -30 to 30.·· Rotating the compass does affect the output, so something is working.· When it just sits still, I get a fair amount of fluctuation.· Here are 100 angles reported without moving the compass (why are they negative?)

    -4
    -8
    -4
    -8
    -4
    -8
    -6
    -8
    -4
    -8
    -3
    -1
    -8
    -14
    -10
    -7
    -1
    -4
    -8
    -1
    -8
    -1
    -14
    -4
    -8
    -1
    -6
    -8
    -1
    -10
    -8
    -10
    -8
    -6
    -10
    -8
    0
    -6
    -4
    -8
    -4
    -8
    -10
    -6
    -8
    -10
    -15
    -4
    -10
    -4
    -6
    -10
    -4
    -8
    -4
    -6
    -10
    -8
    -4
    -7
    -8
    -1
    -6
    -4
    -15
    -8
    -10
    0
    -10
    -6
    -4
    -1
    -6
    -1
    -8
    -7
    -4
    -8
    -6
    -4
    -14
    -8
    -4
    -6
    -4
    -6
    -10
    -6
    -8
    -4
    -10
    -8
    -10
    -1
    0
    -8
    -4
    -7
    -1
    -10
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 03:35
    Found the problem! The statement that converts to degrees was unnecessary (and wrong anyway). It was unnecessary because IntegerMath.atan2() returns degrees, not brads so no conversion was required. It was wrong because 360 * 1406 is 506160 -- easily overflowing a 16-bit integer.

    Unfortunately, the device does not seem very useful. Without it moving at all, I get the the following range of results in a few seconds time:

    43
    50
    45
    50
    45
    47
    45
    50
    47
    50
    45
    47
    50
    45
    47
    51

    This is with the sensor installed on the Javelin prototyping board. Maybe it will improve with it moved away. Anyone get any better results than this?
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-09-06 03:52
    Don,

    ·· I'm glad you got that little problem worked out!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-09-06 04:18
    The info for atan2 shows

    · /**
    ·· * Calculate arctan value of y/x
    ·· *
    ·· * @param y y-value
    ·· * @param x x-value (should not be 0 !!!)
    ·· * @result arctan(y/x)
    ·· */
    · /* absolute value of parameters should */
    · /* be less than 1000 to prevent overflow */
    so you must scale x and y before applying atan2(y,x)

    Your x and y are 11 bits so their range is 0 to 2047 (or -1024 to +1023)
    I suggest to rightshift x and y by 1 bit

    x >>= 1;
    y >>= 1;
    if (x & 0x200 != 0) x |= 0xFC00;· //range -512 to +511
    if (y & 0x200 != 0) y |= 0xFC00; //ditto

    Also note that atan2 is an approxiamation.

    regards peter
    ·
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 05:51
    I haven't examined the code for atan2, but I wonder if +-1000 is really meant to be -1024 to 1023.· I haven't seen an overflow occur yet without doing the shift.

    I have compensated for the fluctions in the angles by averaging over 20 samples.· The average holds to within a degree.

    I found a much more serious problem though.· I quite frequently get an undefined status value·of 8 returned from the module.· Sometimes when I run the program, I get nothing but 8's.· Other times I get 0 (not ready)·for a few iterations and then a 12 (ready to read), which is as expected.· When it works correctly, I can run the program·seemingly forever without having·a problem.··When it works incorrectly, it also does so forever.· Usually, resetting the Javelin does not correct the problem.· Unplugging it and waiting for a while seems to help. ·Any idea what is going on?
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 06:58
    Well, guess what? A status return value of 8 is as good as a 12. I changed the code to loop on status != 0 and it worked fine. Well, almost. My averaging solution introduces a small problem when transiting zero degrees. The sum includes some values around 360 degrees and some around 0 degrees, so the average comes out wrong. Have to think about this one tomorrow, as I am burning out now.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-09-06 09:30
    Average both x and y values, then calculate the angle.
    For example: if 2 angles +1 and +359 are averaged you get +180
    which is 180 degrees in error because you want 0 degrees.
    The x for +1 degree equals the x for +359 degree.
    The y for +1 degree is minus the y for +359 degree so the average y is 0,
    which yields 0 degrees.

    regards peter
    ·
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 15:07
    Thanks, I'll try it.

    Any idea of why the status value the device returns is an 8 for a valid status some of the time and a 12 other times? I haven't tried using the device with a BS yet, but if it works the same way it does with a Javelin, people are going to have problems using the example code Parallax provides.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-09-06 15:44
    According to the datasheet

    http://www.parallax.com/dl/docs/prod/compshop/HM55BDatasheet.pdf

    section 5.2 , 5.3 and 5.4 show

    end··error

    A A· B B

    When AABB = 1100 (eg. 12) measurement is completed without error

    AABB = 1000 (eg. 8) is not defined but also indicates normal completion of measurement

    I think you should test for

    1100 = ok

    1111 = AD overflow

    00XX = not ready

    regards peter
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 16:20
    Peter,

    Don't you mean I should check for 1100 and 1000 as OK conditions?

    I guess in case of overflow you just reset and try again.· Any idea what causes the overflow condition?

    In any case, Parallax should change the sample code they provide for this device if 1100 and 1000 are both valid OK statuses and either one can and does occur.·



    -- Don
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-09-06 17:11
    I think you should test for 1100 (= ok), then use the values for x and y.

    Discard the values read when status is 1111 (AD overflow) or 00XX (not ready).

    Any other value than the above should be treated as invalid, just start

    a new sample sequence.

    regards peter
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 21:00
    If I don't test for 8, I will never get any readings! It loops forever, always giving me an 8, and never a 12. Or at least that is what it does about 80% of the times I run the program. The other 20% of the time it works as advertised. On the plus side, now that I know that an 8 is as good as a 12, I accept it and get good readings every time. But if I limit it to only accepting 12's I would be out of business.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-09-06 21:14
    Maybe you are looping too fast. I have not worked with that module

    but maybe it is wise to study the timing diagrams on the datasheet more closely.

    On the other hand, if status=8 appears to return valid x and y values, use them.

    (but then maybe status=4 is also valid)

    regards peter
  • Don FrenchDon French Posts: 126
    edited 2005-09-06 21:25
    I tried inserting a delay, steadily increasing the delay up to one second, but with no improvement. The odd thing is that when it returns a 12 it continues to return a 12 all day and when it returns an 8 it does that all day (figuratively speaking). It seems like a bug in the hardware, to tell you the truth. Not sure if it is the chip or the module. Of course, most of the time I think something is a hardware problem it turns out to be software. :-\
  • diafysaldiafysal Posts: 92
    edited 2005-09-07 19:58
    This code worked for me to get the raw data.

    Feel free to complete it with the mathematics.

    http://forums.parallax.com/showthread.php?p=544194
  • Don FrenchDon French Posts: 126
    edited 2005-09-07 20:10
    I am not at home where my source is, but it looks to me like the only significant thing different between your code and the code of mine that does not work (most of the time) is this line:

    CPU.writePin(Clk, false); // Initialize Clk for delivering positive pulses.

    Was there an equivalent line in the BASIC code? If so, I must have missed it. I will try this when I get home just to see if that was the problem. But as i have already posted, checking for either an 8 or a 12 status seems to also fix the problem.
  • Don FrenchDon French Posts: 126
    edited 2005-10-05 19:41
    Peter,

    I just checked the approximation method of computing atan2 that I think you pointed me to, and it is pretty good.· The most it ever is off is 1.315 degrees, based on running 10,000 combinations of x and y through it.

    I needed to do this check·because my compass is not giving me good results and I wasn't sure if it was the atan2 approximation.··· I did a test where I rotated my device at a constant speed and took a reading every second.· The difference between readings repeatably varied from 2 degrees per second·to 22 degrees per second, depending on which direction·the compass·was pointing.· I have the motors doing the rotating completely enclosed in the film equivalent of mumetal, so I don't think it is that.· But something is causing this inaccuracy.· I wonder if it could be the presence of a reed relay on a chip·that is near by and which is turned on at the time of rotation.· I will have to do more experiments.· I have the compass mounted on the Javelin Demo board prototype area and there are a few other wires near it.· But they all rotate along with the compass, so I would think that their presence would have a constant effect rather than one that depends on the direction the device is pointing.· My next experiment is to take the compass off the prototype board and put it a foot up in the air away from the Demo board.·

    -- Don
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-10-05 20:50
    Yes, it is pretty good.

    The url mentioned in the class

    http://www.acroname.com/brainstem/examples/math/math.html

    also has plotted curves of the approxiamation (excel spreadsheet)

    regards peter
  • Don FrenchDon French Posts: 126
    edited 2005-10-05 22:16
    Maybe I am wrong, but the spreadsheet for the approximation of atan appears to be plotting a graph of the cot of the angle not the arctan of a number.
Sign In or Register to comment.