Shop Learn
TAQOZ Reloaded v2.8 - Reading the QMC5883 magnetic field sensor — Parallax Forums

TAQOZ Reloaded v2.8 - Reading the QMC5883 magnetic field sensor

bob_g4bbybob_g4bby Posts: 257
edited 2021-11-07 20:10 in ForthSpace

This sensor, mounted on a breakout board, is very cheap on ebay. The following code has two demos that can be stopped by pressing any key:-
1. 'XYZtest' displays the raw data from the chip
2. 'COMPASS' displays bearing (degrees) and field strength (raw units)

--- QMC5883 XYZ magnetic field sensor driver for Taqoz 2.8
--- Version 1 Nov 2021 by Bob Edwards

ALIAS I2C.START <I2C                        --- Matches the stop alias, I2C>

--- create constant to hold current i2c chip address 
0 := i2cadr

--- set the i2c address for subsequent i2c transfers ( like PIN does for smartpins )
pub I2CADR  ( n -- )
' i2cadr :=!

--- I2C address of the QMC5883 as reported by Taqoz

--- Read byte at register i2cadr
pub I2CREAD ( adr -- byte )
    <I2C i2cadr I2C! I2C!                   --- select the register at 'addr' 
    <I2C i2cadr 1+ I2C! nakI2C@ I2C>        --- read the contents

--- Write byte to register i2cadr
pub I2CWRITE ( byte adr -- )
    <I2C i2cadr I2C! I2C! I2C! I2C>

--- set QMC5883 for continuous reading  
    1 $B I2CWRITE                           --- define set/reset period
    $11 $9 I2CWRITE                         --- OSR = 512
                                            --- full scale range = 8
                                            --- ODR = 10 Hz
                                            --- continuous mode

--- returns QMC5883 status
pub STATUS@ ( -- status )
    6 I2CREAD

--- wait until a mag field reading is ready
pub RDY?    ( -- )
        STATUS@ 1 AND

--- convert signed 16 bit value to signed long
pub W->L    ( 16bitsigned -- 32bitsigned )
DUP 32767 >
    65536 -

--- read the mag field in 3 axes
pub XYZ@    ( --- X Y Z )
    0 I2CREAD
    1 I2CREAD 8<<
    OR W->L
    2 I2CREAD
    3 I2CREAD 8<<
    OR W->L
    4 I2CREAD
    5 I2CREAD 8<<
    OR W->L

--- read the raw temperature value
pub TEMP@   ( --- temp )
    7 I2CREAD
    8 I2CREAD 8<<

--- test the mag field and temp readings
pub XYZtest
        ." Z="  . SPACE
        ."  Y=" . SPACE
        ."  X=" . SPACE
        ." Temp=" .

--- read and compute the mag field in the XY plane
pub XYvec   (  -- ampl angle )

--- read and compute the mag field in the YZ plane
pub YZvec   ( -- ampl angle )

--- read and compute the mag field in the XZ plane
pub XZvec   ( -- ampl angle )

--- print compass bearing from raw angle output by QVECTOR
pub DEGS.   ( rawangle -- )
    36000 4294967295 U*/
    DUP 100 / DUP 3 .DECS 46 EMIT 100 * -
    DUP 10 <
        48 EMIT
    THEN .

--- test as a compass in the XZ plane
pub COMPASS ( -- )
        ." Mag Field Angle = " DEGS. SPACE  
        ." Mag Field Amplitude = " .  CRLF


  • Many thanks Bob,
    Just looking at I2C coding for another sensor, so this example is really useful.
    Already ordered a QMC5883 from eBay!


  • Nice one Pete, see if it works for you and post any improvements you make. I also have a bmp280 pressure board, which is also i2c, I just need to get the raw data to pressure conversion to work. I have the thermometer on it working. All good fun now the colder days are with us.

  • I've been working too with the BMP280 with no problems and at the same point - applying the calibrations.

    However, I am having problems with another sensor, the CCS811 air quality sensor. It responds as you would expect to single byte register reads - such as the hardware ID, but I cannot get multiple byte reads to work (mailbox mode as they call it). Each time I do a multiple read or a multiple write it generates an error condition and the appropriate read/write error flag is raised. (a multiple byte write to reset the chip does seem to work ???)

    I have tried using multiple I2CREAD/ICWRITE words from your code and using the basic I2C words and each time I get an error condition.

    Have you come across this?
    Cheers, Pete

  • Bob, my QMC5883 turned up and I gave it a try with your program - all working well!
    Many thanks for the demo program,
    Cheers, Pete

  • bob_g4bbybob_g4bby Posts: 257
    edited 2021-11-13 12:48

    Thanks for the endorsement, Pete, it's good to know others can use it. Sorry to hear the CCS811 not responding to auto-addressing.

  • bob_g4bbybob_g4bby Posts: 257
    edited 2021-11-13 14:39


    Have a look at the SI5351 data sheet on page 15, which shows the elements of reading and writing both single value and multiple values. Maybe that throws up something you've missed with the CCS811?

    I used autoincrement-address successfuly in my SI5351 driver, so I know Taqoz supports this.

  • Thanks Bob, the SI5351 register protocol is what I'm used to seeing.

    Just need to find the exact I2C sequence for non-auto addressing (and probably timing).
    Cheers, Pete

  • Managed to sort out the problems I had reading and writing to the CCS811 sensor:

    1) I had not initiated the I2C bus with !I2C, which asserts the SDA and SCL lines but also implements the pull-up resistors for the CCS811 board I have (presumably no onboard pull-ups) - board too tiny for my eyesight!
    2) The other issue was not initialising the chip by writing to an address (with no data).

    Just finishing code for the HDC1080 humidity and temperature sensor.......
    Many thanks for your help.

  • bob_g4bbybob_g4bby Posts: 257
    edited 2021-11-21 08:40

    Good to hear you cracked it. I'm still wrestling with the BMP280 raw data to hPa conversion. As I'm aiming at altimeter use, I'm adding a few 64 bit maths functions to max out the precision.

    Good to see you published your code

Sign In or Register to comment.