TAQOZ Reloaded v2.8 - Reading the QMC5883 magnetic field sensor
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 $1A I2CADR --- 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 pub SETUP 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? ( -- ) BEGIN STATUS@ 1 AND UNTIL ; --- convert signed 16 bit value to signed long pub W->L ( 16bitsigned -- 32bitsigned ) DUP 32767 > IF 65536 - THEN ; --- 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<< OR ; --- test the mag field and temp readings pub XYZtest SETUP BEGIN RDY? XYZ@ ." Z=" . SPACE ." Y=" . SPACE ." X=" . SPACE TEMP@ ." Temp=" . CRLF KEY UNTIL ; --- read and compute the mag field in the XY plane pub XYvec ( -- ampl angle ) XYZ@ DROP QVECTOR ; --- read and compute the mag field in the YZ plane pub YZvec ( -- ampl angle ) XYZ@ ROT DROP QVECTOR ; --- read and compute the mag field in the XZ plane pub XZvec ( -- ampl angle ) XYZ@ SWAP DROP QVECTOR ; --- 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 < IF 48 EMIT THEN . ; --- test as a compass in the XZ plane pub COMPASS ( -- ) SETUP BEGIN RDY? XZvec ." Mag Field Angle = " DEGS. SPACE ." Mag Field Amplitude = " . CRLF KEY UNTIL ;
Comments
Many thanks Bob,
Just looking at I2C coding for another sensor, so this example is really useful.
Already ordered a QMC5883 from eBay!
Cheers
Pete
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
Thanks for the endorsement, Pete, it's good to know others can use it. Sorry to hear the CCS811 not responding to auto-addressing.
@Peter_F
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.
Cheers,
Pete
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