Shop OBEX P1 Docs P2 Docs Learn Events
HMC5883 code to QMC5883 — Parallax Forums

HMC5883 code to QMC5883

Good Day All,
Hope you all had a Merry Christmas and a Happy New Year.

I am humbly requesting assistance with modifying P1 spin code... specifically, converting spin code from HMC5883 to QMC5883.

Background... I purchased a BN-880 GPS/compass module. The GPS part works good (with spin) and the P1. Problem is with compass part.

I am building a robot based on an ELEGOO smart robot chassis. I ripped out the Arduino UNO R3, and replaced it with a P1 Flip. Got the L298 motor controller working and several sensors.

Want to get the compass part of the BN-880 working.

Discovered that the "compass part" of the BN-880 is actually an QMC5883 (vice a HMC5883... as the advertisement indicated). Verified this with an I2C scanner... address is 0x0D... vice 0x1E... and comments from other disgruntled buyers.

I noticed that the address' for the x,y,z are different, between the QMC and HMC (see pdf). Also, discovered that the read/write opcodes are different.

I made these adjustments in my modified code, but still not working correctly. I am sure it is the way I am manipulating the "raw" data "reads". The HMC reads the MSB first, but the QMC reads the LSB first. I tried a couple of ways, but I only get about 30 degrees of Asmuth.

I downloaded code for the UNO R3 (for the QMC)... it works great... just a slight error... I know that this can be fixed with calibration.

I've attached the original spin code, for the HMC. I also included the modified code... that does not work. I also included a "pdf" that shows the difference between registers.

Any help would be greatly appreciated.

Comments

  • JonnyMacJonnyMac Posts: 9,191
    edited 2025-01-04 19:09

    This seems like a neat project, and somewhat involved, so let me suggest you use an I2C library (mine is attached, and there are others) so that you can make a really clean interface. For example, to read a 16-bit Little-Endian value from the device you might have a method like this:

    pub read16(reg) : result
    
    '' Read signed 16-bit value starting at reg
    
      i2c.start
      i2c.write(QMC5883_WR)
      i2c.write(reg)
      i2c.start 
      i2c.write(QMC5883_RD)
      result.byte[0] := i2c.read(i2c#ACK)
      result.byte[1] := i2c.read(i2c#NAK)
      i2c.stop
    
      ~~result                                                      ' extend sign from bit 15
    

    You might also read X, Y, and Z at once like this:

    pub read_xyz | temp[2]
    
    '' Read X, Y, and Z registers
    
      i2c.start
      i2c.write(QMC5883_WR)
      i2c.write(0)
      i2c.start 
      i2c.write(QMC5883_RD)
      i2c.rd_block(@temp, 6, i2c#NAK)
      i2c.stop
    
    ' update globals
    
      bytemove(@x, @temp.byte[0], 2)                                ' move x from buffer
      ~~x                                                           ' extend sign
      bytemove(@y, @temp.byte[2], 2)
      ~~y                           
      bytemove(@z, @temp.byte[4], 2)
      ~~z
    

    Warning: None of this code is tested (other than I know my I2C library works). That said, I have a lot of experience so I think it's a safe place to start.

    Once you get good coms create a clean object for the device that just lets you configure it and read raw values. Your application can use the math library to convert raw data as needed.

    A few minutes later...

    Something I do with new I2C devices is run my scanner that will identify what devices are on the bus. It's a simple program that will take the guesswork out of new parts. Now... I favor 8-bit style addresses. If you get an address from the Schmarschmino crowd, you need to left-shift it by 1 (they do that inside the Wire library). The output will look something like this:

    The code with my I2C library is in the attached archive.

  • Thanks for your reply, Jon.

    Unfortunately, I am getting the same results with your code. I only get a swing of about 30 degrees (~120 to 150), when I rotate the compass. I also noticed that the xyz values never go negative. Thus, it has to be how I am reading xyz. I have attached my latest. Thanks again.

  • JonnyMacJonnyMac Posts: 9,191

    I don't have that component, so I'll have to trust what you're saying. I have a project coming that could use a compass so I'll order one from Amazon and see what happens.

    My comments about using an I2C library versus hard-coding those elements into your application still stand.

  • Thanks again Jon,
    I indicated earlier that the device that I ordered was a BN-880. It's actually a BE-880. I think they are both the same. I will "re-look" at the Arduino code, next weekend, to see what I may be missing (in the spin code). Take care.
    Al

  • JonnyMacJonnyMac Posts: 9,191
    edited 2025-01-05 20:10

    I ordered the QMC5883L compass module. If it arrives early enough today I'll connect it and give it a poke around. I don't have that math library you use in your code. In future posts, I suggest you archive your project so that others get everything required to assist.

  • Yea... sorry about that. Attached, all 3 files (in a zip).

  • Sorry... missed your i2c library... this zip has it.

  • Jon,
    Had a few minutes to do some research... found a pdf (attached)... it's a manual for the QMC. Only had a few minutes to look it over. Discovered that the Write operation requires 3 steps... first "request write ($1B)"... then send the address of the register ($00)... then the value to place into the register ($00). This seemed to have partially fixed the issue. The x,y values now go negative, but the z value does not. Also, the x,y,z, and azimuth value jump around a lot. Maybe a little progress.

    Off to Raleigh. Hope to work on this some more over the weekend.
    Al

  • JonnyMacJonnyMac Posts: 9,191
    edited 2025-01-07 00:19

    I don't normally post WIP code, but as you have a handle on this part I thought I'd share what I have as of last night. In my case, I am getting positive and negative values on every axis, but I am only reading the raw data.

    Again -- this is WIP code. It reveals my object development process. I start with a template and develop the object code at the bottom, with test code at the top. Once the object is working I remove the test code and save the clean object.

  • Jon,
    This looks very promising. I noticed some changes in your code. I should be able to use some of your methods and get it working. I am still in Raleigh but will be back home on Friday.
    I have not been on this forum for many years. I was introduced to the ESP8266 and then the ESP32, thus I kind of lost interest in the prop. But my daughter gave me a ELEGOO robot in October (Birthday present). I thought... this is perfect for the P1. Got the robot working with the P1, many sensors, and GPS. At this point, the compass was last item to implement. Many thanks for your assistance. When I get it working, will post the code. Take Care.
    Al

  • JonnyMacJonnyMac Posts: 9,191

    When I get it working, will post the code. Take Care.

    If you craft an object out of the code I shared, please take my name off it so I don't get credited for you work.

    Good luck with the robot. Hopefully, too, this is an opportunity to do a fun STEM project with your daughter.

  • Jon and all,

    Spin file "QMC5883L_DEMO" works for me (see attached). Code will show x,y,z, and Heading. It only requires FDS. I copied some of the methods from Jon's great work. As with the Arduino code, I get a slight error. I know a calibration will fix this error. I don't have time this weekend to calibrate... will try next weekend. "JonnyMac Rules".

    I would like to take a quick second to applauded Parallax. I purchase the "What's a Microcontroller"... with the BS2, over a decade ago. Soon, thereafter, I purchased the "Prop-stick USB" kit. I also purchase about 6 "quick-start" boards, and more recently, two FLIPs. All of my P1 purchases still work... I checked them all recently. I have not checked the BS2... but I am willing to bet, it still works.

    As I indicated in an earlier post, I spent some time with the ESP8266 and the ESP32. I purchased about 5 ESP8266's (ESP-1's and ESP-12's). Only one ESP-12 still works. I purchased 4 ESP32 DEV modules... only one still works. I also purchased 2 ESP32 C3's. They do still work... but for how long.

    Thanks, Parallax, for producing fine quality electronics.
    Al

Sign In or Register to comment.