Shop OBEX P1 Docs P2 Docs Learn Events
Multiple objects for HM5883L Magnetometer — Parallax Forums

Multiple objects for HM5883L Magnetometer

HughHugh Posts: 362
edited 2014-05-25 15:48 in Propeller 1
I have tied myself in a knot.

I have been trying to use the Parallax code for the HM5883 Demo as the basis for trying to read two magnetometers simultaneously. By changing the pin numbers to reflect the hardware I can use the standard code to read data from either magnetometer attached to the prop - getting it to read two seems to have caused me to come unstuck.

The code has been pruned back to what I think is the minimum and a file 'TopObj.spin" written to start the two instances of the HM5883L object (passing the two pin numbers) and receive the x, y and z components from the magnetometers. These (six values) are then sent to the Serial terminal. The only values received are all '0'.

The attachment is the code as it currently is - trying to get a single magnetometer to working using this approach.

Any ideas welcome. I've spent the whole day working in VB.net so may be 'code blind'!

TopObj - Archive [Date 2014.05.12 Time 18.23].zip

Comments

  • Mike GMike G Posts: 2,702
    edited 2014-05-12 10:46
    In topObj, one HMC5883L_Demo object is started. Are you are trying to use the same bus I2C bus for the two devices? If so, each device needs a distinct address otherwise you'll need to allocate more 2 pins for the second HMC5883L device.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 10:59
    Hugh,

    The HM5883L isn't set up to be used as a child object.

    I haven't tested the attached code, but I'm hoping it will allow you to access the values from the child object.

    Let me know if it doesn't work and I'll test it out myself.

    I was just looking from some HM588L code I previously wrote (this was before seeing this thread). Once I find it, I'll clean it up and post it. My version uses F32 to compute heading.
  • HughHugh Posts: 362
    edited 2014-05-12 11:00
    Mike G wrote: »
    In topObj, one HMC5883L_Demo object is started. Are you are trying to use the same bus I2C bus for the two devices? If so, each device needs a distinct address otherwise you'll need to allocate more 2 pins for the second HMC5883L device.

    At the moment I am only trying to get one object / magnetometer started (to start with), then will expand the approach to two. The only difference (I hope) will be the pin numbers passed to each object.

    Thanks
    Hugh
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 11:06
    To elaborate a bit on what I did in the above code, I had the "StartMag" method return the address of the first vector variable.
    VAR
    
    long x
    long y
    long z
    
    
    
    
    byte datapin
    byte clockPin
    
    
    
    
    PUB startMag(dpin,  cpin)          ' Receive the datapin and clockpin IDs from the calling object
     
       datapin  := dpin                ' Update the references in this file         
       clockpin := cpin
       setcont                         ' Set the compass to continuous output mode
       [B]result := @x[/B]
       
    
    
    

    The top object uses this value to find the data after the raw data is read.
  • Mike GMike G Posts: 2,702
    edited 2014-05-12 11:07
    At the moment I am only trying to get one object / magnetometer started (to start with), then will expand the approach to two.
    The code is pretty rough. The top level object is calling mag[1].GetData(x1,y1,z1). The child object is assigning nothing (???) to the methods input parameters.
    PUB GetData (xa, ya, za)     
        setpointer(OUTPUT_X_MSB)
        getraw
        xa := x
        ya := y
        za := z
    

    I'm guessing you really want the follwoing?
    PUB GetData (xa, ya, za)     
        setpointer(OUTPUT_X_MSB)
        getraw
        x1 := x
        y1 := y
        z1 := z
    

    But then there are no getters in HMC5883L_Demo to pass the value back to the top level object.

    Edit: Are you trying to use pointers?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 11:13
    I remember the first time I read the HM5883L demo code, I thought it was kind of strangely written. Looking at it again, and after having just translated several Arduino programs to Spin, it looks like the demo code is a quick (possibly automated) translation of Arduino code to Spin. IMO, not very well done (though I've written worse).

    I thought I was lacking in some understanding why this piece of code existed:
    x := x 
      z := z 
      y := y
    

    After translating several C programs, it looks like some artifact caused by the difference between C and Spin. The above code does nothing useful.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 11:16
    Mike G wrote: »
    Edit: Are you trying to use pointers?

    I think the Arduino code used as a guide used pointers. The demo is Parallax's code not Hugh's.

    I have a better version. I'll find it and post it.
  • HughHugh Posts: 362
    edited 2014-05-12 11:17
    Duane Degn wrote: »
    Hugh,

    The HM5883L isn't set up to be used as a child object.

    I haven't tested the attached code, but I'm hoping it will allow you to access the values from the child object.

    Let me know if it doesn't work and I'll test it out myself.

    I was just looking from some HM588L code I previously wrote (this was before seeing this thread). Once I find it, I'll clean it up and post it. My version uses F32 to compute heading.

    Thanks Duane - that works brilliantly... ...but... the serial terminal is now showing three 'sensible' values and on the next row three larger values, three sensible values, three odd values, etc., , i.e.,

    "-71,37,-642-18435,9727,32256"

    I'm not sure whether this is happening as a result of different results on alternate calls.

    I expanded your code to two magnetometers (below) and, with the exception of the good data / bad data rows, it works brilliantly! :thumb:


    PUB Main | x1, y1, z1, x2, y2, z2
    
    
      address[0] := mag[0].startMag(17, 16)
      address[1] := mag[1].startMag(13, 14)
      
    
    
      waitcnt(clkfreq/100_000 + cnt)      'Wait while compass has time to startup.
    
    
      term.start(31, 30, 0, 9600)         'start a terminal Object (rxpin, txpin, mode, baud rate)
      repeat 
         mag[0].GetRaw
         longmove(@x1, address[0], 3)
         mag[1].GetRaw
         longmove(@x2, address[1], 3)
        
         term.dec(x1)
         term.tx(44)
         term.dec(y1)
         term.tx(44)
         term.dec(z1)
         term.tx(44)
         term.dec(x2)
         term.tx(44)
         term.dec(y2)
         term.tx(44)
         term.dec(z2)
         term.tx(13)
    

    (Output now:
    -641,-71,40,-529,-142,66
    32512,-17923,10495,-4864,28925,18431)
  • HughHugh Posts: 362
    edited 2014-05-12 11:19
    Duane Degn wrote: »
    I think the Arduino code used as a guide used pointers. The demo is Parallax's code not Hugh's.

    I have a better version. I'll find it and post it.

    The TopObj code is mine. Yes, it is rough - I've started getting splinters from it...!

    I cut the Parallax code down because I couldn't fully understand it.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 11:31
    Hugh, try adding a delay to the loop. You might not be giving the sensor enough time between reads.
  • HughHugh Posts: 362
    edited 2014-05-12 11:32
    (I think there must be some sort of timing/delimiting issue with the output which is shifting to the right with each output (I have edited out the big numbers between these lines)

    output.png


    In the code they all have trailing commas, expect the final number that has a <CR>.)
    202 x 210 - 10K
  • HughHugh Posts: 362
    edited 2014-05-12 11:33
    No change, I'm afraid Duane - even at 1Hz :-)
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 13:36
    Hugh, instead of calling the method "GetRaw", try your original version of "GetData". "GetData" probably will work better. It doesn't matter what three variables you use with the call since they won't change. You'll still need to use the "longmove" statements to move the data to the parent object.

    I found my HM5883L object. I'm trying to add enough comments so it can be used by others. I'll be posting it later today.

    My version includes the heading averaged over several readings (even if the reading is near the rollover). It also includes a "field angle from horizontal" value.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-12 15:03
    Hugh,

    I uploaded my version here.

    It's pretty complicated in order to overcome the rollover issue when averaging readings. I'll likely make a pared down version with just the basics sometime soon.

    Edit: I also added a simplified version of the code.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2014-05-25 10:10
    Hugh,

    As I was trying to round out my HMC5883L code to allow the various registers on the sensor to be set, I found one of the setting was for the gain.

    The default gain is set to 0.92 milli-Gauss per unit but it can be increased to 0.73 mG/unit.

    This gain setting also allows the sensitivity to be decreased (down to 4.35 mG/unit).

    There are a couple of other settings you may find useful. The default sample rate is 7.5Hz but this can be adjust down to 0.75Hz or increased up to 75Hz.

    The sensor can average multiple readings internally. The default averages (if the the word even applies) a single reading but this can be increased to averaging 8 samples (all the averaging numbers are powers of 2 (1, 2, 4 & 8).

    I think the demo program adequately shows how these various settings can be accessed. Hopefully these features will be useful to you.

    The latest version is available in post #2 of the thread I linked to in my previous post (#15). I still intend to add a few more methods to the object before submitting it to the OBEX but I think the object is usable as it is now.
  • HughHugh Posts: 362
    edited 2014-05-25 15:48
    Duane,

    Wow! That is something I need to play with. Excellent work - thank you! ;-)
Sign In or Register to comment.