Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : QMC5883L
Author | Message | ||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
I've got a QMC5883L compass incorporated in a GPS module a Matek Neo M9N-5883 which the GPS works beautifully I cannot however figure out how to get the compass working Does anyone have any code for this module that I could use? OR Can anyone "translate" from Arduino? I found Arduino code here With the compass.h here and the compass.cpp here Example code for direction here This I believe uses N,W, E and W where I'd prefer to use 8 points of the compass rather than 4 Anyone able to decipher and translate or have any code for this module? I did have a go at it myself but completely got lost and couldn't make head nor tail of what I was trying to do The only thing I can say for definite is it needs to be in continious mode Continuous Mode Setup Example Write Register 0BH by 0x01 (Define Set/Reset period) Write Register 09H by 0x1D (Define OSR = 512, Full Scale Range = 8 Gauss, ODR = 200Hz, set continuous measurement mode) 7.2 Measurement Example Check status register 06H[0] ,"1" means ready. Read data register 00H ~ 05 |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
it's a compass ic |
||||
SimpleSafeName Senior Member Joined: 28/07/2019 Location: United StatesPosts: 286 |
What platform and language do you plan to run the compass on? Whose compass board are you using? Taking a quick look at it and it doesn't seem too bad. First off have you seen how to operate it in the Arduino world? https://belchip.by/sitedocs/10882.pdf Let me know the board and more importantly, the platform that you want to use it on, and I'll give it a shot. John |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
It's going on a Picomite it's part of a GPS program, the compass is built into the GPS module I know nothing about Arduino and I'm pretty cr@p at programming using MM as well |
||||
SimpleSafeName Senior Member Joined: 28/07/2019 Location: United StatesPosts: 286 |
So I took the plunge last night and dropped $7 bucks on a compass module to get the ball rolling. The important thing is that we are using the same chipset. When it gets here I'll see about programming it to work with a CMM2. That will get you close. |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
Thanks :) |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
I've spent a few hours on this (using the same integrated GPS/Compass Matek Neo module as Lewis) and am stymied. I'm reasonably sure the following should read the raw data: Option base 0 Option default none Option explicit on Const MAG_ADDRESS = &h0D SetPin GP0, GP1, I2C I2C OPEN 100, 1000 qmc5883l.init() Do qmc5883l.read() Pause 100 Loop Sub qmc5883l.init() qmc5883l.writeReg(&h0A, &h80) ' Reset the chip qmc5883l.read() qmc5883l.writeReg(&h0B, &h01) qmc5883l.read() ' Continuous (0x01), 200Hz (0x0C), 8G (0x10), OSR=512 (0x00) ' qmc5883l.writeReg(&h09, &h01 Or &h0C Or &h10 Or &h00) qmc5883l.writeReg(&h09, &h1D) qmc5883l.read() End Sub Sub qmc5883l.writeReg(reg%, value%) I2C Write MAG_ADDRESS%, 1, 1, reg% If MM.I2C Then Error I2C Write MAG_ADDRESS%, 0, 1, value% If MM.I2C Then Error End Sub Sub qmc5883l.read() I2C Write MAG_ADDRESS%, 1, 1, &h00 If MM.I2C Then Error Local buf$ I2C Read MAG_ADDRESS%, 0, 14, buf$ If MM.I2C Then Error Local i% For i% = 1 To 14 Print Asc(Mid$(buf$, i%, 1)); Next End Sub But all I get when RUNning is: > RUN 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 ... The datasheet describes register &h0C, the one with the '1' as both "Reserved" and a "Status register", but doesn't say what its contents actually means ... presumably a value of 1 means "the monkey is doing it wrong" ? Does anyone have any ideas before I order a standalone QMC5883L module to try with ... Lewis does it give the same non-result for you ? Best wishes, Tom Edited 2022-02-06 02:09 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
Sorry Tom only just saw this I get this error > RUN [33] If MM.I2C Then Error Error > I did change this SetPin GP4, GP5, I2C after it failed the first time as that's where my i2c pins are I did see in the manual that it says I2C WRITE addr, option, sendlen, senddata [,sendata ....] but you have I2C Write MAG_ADDRESS%, 1, 1, reg% I see that MAG_ADDRESS% is &h0D but I can't find what reg% or value% actually are? |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
No worries. Interesting. Anyway, I think I have it working now, try the code below instead. Yes, I temporarily removed your PCB from the equation and just wired directly to the first available SDA and SCL pins, GP0 & GP1. Working (?) code - the output is just raw for the moment, no post-processing at all, but it seems to behave appropriately when I mess with the module orientation, not sure about the temperature reading though, perhaps needs calibrating ? Option base 0 Option default none Option explicit on Const qmc5883l.I2C_ADDR% = &h0D SetPin GP4, GP5, I2C I2C OPEN 100, 1000 Dim mag_x%, mag_y%, mag_z%, temp% Print "Initialising..." qmc5883l.init() Print "Running..." Do ' qmc5883l.read_all() qmc5883l.read(mag_x%, mag_y%, mag_z%, temp%) Print mag_x%, mag_y%, mag_z%, temp% Pause 1000 Loop ' Initialises the QMC5883L. Sub qmc5883l.init() ' Reset the chip. qmc5883l.write_register(&h0A, &h80) qmc5883l.read_all() qmc5883l.write_register(&h0B, &h01) qmc5883l.read_all() ' Continuous (0x01), 200Hz (0x0C), 8G (0x10), OSR=512 (0x00) ' qmc5883l.write_register(&h09, &h01 Or &h0C Or &h10 Or &h00) qmc5883l.write_register(&h09, &h1D) qmc5883l.read_all() End Sub ' Writes value to a QMC5883L register. Sub qmc5883l.write_register(register%, value%) ' Address the slave and write two bytes, the register and the value. I2C Write qmc5883l.I2C_ADDR%, 0, 2, register%, value% If MM.I2C Then Error qmc5883l.get_i2c_error$() End Sub ' Gets string corresponding to MM.I2C error code. Function qmc5883l.get_i2c_error$() Select Case MM.I2C Case 0 : qmc5883l.get_i2c_error$ = "None" Case 1 : qmc5883l.get_i2c_error$ = "NACK" Case 2 : qmc5883l.get_i2c_error$ = "Timeout" Case Else : qmc5883l.get_i2c_error$ = "Unexpected error: " + Str$(MM.I2C) End Select End Function ' Reads X, Y, Z from the magnetic sensor and also the temperature. Sub qmc5883l.read(mag_x%, mag_y%, mag_z%, temp%) ' TODO: should probably check if data ready bit/register is set. ' Address the slave and send the first register address to read (0x00). I2C Write qmc5883l.I2C_ADDR%, 1, 1, &h00 If MM.I2C Then Error qmc5883l.get_i2c_error$() ' Read 8 registers/bytes (0x00 .. 0x07). Local buf$ I2C Read qmc5883l.I2C_ADDR%, 0, 8, buf$ If MM.I2C Then Error qmc5883l.get_i2c_error$() mag_x% = Peek(Var buf$, 1) Or (Peek(Var buf$, 2) << 8) mag_y% = Peek(Var buf$, 3) Or (Peek(Var buf$, 4) << 8) mag_z% = Peek(Var buf$, 5) Or (Peek(Var buf$, 6) << 8) temp% = Peek(Var buf$, 8) Or (Peek(Var buf$, 9) << 8) End Sub ' Reads and dumps the contents of all 14 QMC5883L registers. Sub qmc5883l.read_all() ' Address the slave and send the first register address to read (0x00). I2C Write qmc5883l.I2C_ADDR%, 1, 1, &h00 If MM.I2C Then Error qmc5883l.get_i2c_error$() ' Read 14 registers/bytes (0x00 .. 0x0D). Local buf$ I2C Read qmc5883l.I2C_ADDR%, 0, 14, buf$ If MM.I2C Then Error qmc5883l.get_i2c_error$() Local i% For i% = 1 To 14 ' Print Hex$(Asc(Mid$(buf$, i%, 1)), 2) " "; Print Asc(Mid$(buf$, i%, 1)); Next End Sub Edited 2022-02-06 23:02 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
DaveJacko Regular Member Joined: 25/07/2019 Location: United KingdomPosts: 52 |
This seemed to work for me, The Text commands are for the old LCD micromite backpack. Change to 'print' for other platforms. hope this is informative.. ' test code for Q not H =QMC5883L ' 3 axis digital Magnetometer ' DPJ 2020 addr = &h0D 'mfr says 3C=write 3D=read ie 1E Dim buf(6) As integer bit15=&h8000 k6=65536 CLS 'LCD stuff Font 1,2 '16x32 Colour RGB(0,255,255),0 rd=RGB(255,0,0) Text 0,0,"mag fld demo DPJ 2020",,,1 I2C OPEN 100,100,PU 'speed kHz,timeout ms,pullup ' ---- init hmc5883 see pdf I2C write addr,0,2,&h09,&h1D 'sensitivity etc I2C write addr,0,2,&h0B,&h01 'needed Pause 100 mlp: I2C write addr,0,1,&h00 'select reg 0 I2C read addr,0,6,buf() 'read datas xm=buf(0)+256*buf(1) If xm And bit15 Then xm=xm-k6 ym=buf(2)+256*buf(3) If ym And bit15 Then ym=ym-k6 zm=buf(4)+256*buf(5) If ym And bit15 Then zm=zm-k6 Text 0,20,Str$(xm) Text 0,60,Str$(ym) Text 0,100,Str$(zm) Pause 1000 GoTo mlp Function atn2(y,x) If x > 0 Then atn2 = Atn(y/x) ElseIf y >= 0 And x < 0 Then atn2 = Pi + Atn(y/x) ElseIf y < 0 And x < 0 Then atn2 = Atn(y/x) - Pi ElseIf y > 0 And x = 0 Then atn2 = Pi / 2 ElseIf y < 0 And x = 0 Then atn2 = Pi / -2 EndIf If atn2 < 0 Then atn2 = atn2 + 2 * Pi EndIf End Function |
||||
lew247 Guru Joined: 23/12/2015 Location: United KingdomPosts: 1676 |
Just to confirm both sets of codes work I had to alter the 2nd slightly to match the Pico but it does work Now to read the datasheet and find out what the numbers actually mean :) |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
Great. Note that @DaveJacko's code accounts for the fact that the returned 16-bit numbers (pairs of bytes) may be -ve (in 2's complement), I didn't handle that in what I posted. The Arduino code you linked to in your original post shows how to translate the numbers into compass directions. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Bill.b Senior Member Joined: 25/06/2011 Location: AustraliaPosts: 225 |
Hi all I used a compass in my robot car using picaxe to decode the 5 bytes of data received. this picaxe code mite help in decoding the data. serin CompassSerialIn, cmpbaud, b14, b15, b50, b51, b52, b53, b54, b55 dspdir: '****************** Display Commpass Readings *************** serout OLED,Baud,(254,128) serout OLED,Baud,(" Heading " ) serout OLED,Baud,(254,192) if b50 = 30 then serout OLED,Baud,(" ", b51, b52, b53, b54, 210," ") Else serout OLED,Baud,(" ",b50, b51, b52, b53, b54, 210," ") endif heading = b50 - 48 * 10 + b51 - 48 * 10 + b52 - 48 select case heading case 0 to 10 serout OLED,Baud,("N ") case 11 to 32 serout OLED,Baud,("NNE ") case 33 to 55 serout OLED,Baud,("NE ") case 56 to 80 serout OLED,Baud,("ENE ") case 81 to 101 serout OLED,Baud,("E ") case 102 to 122 serout OLED,Baud,("ESE ") case 123 to 149 serout OLED,Baud,("SE ") case 150 to 170 serout OLED,Baud,("SSE ") case 171 to 190 serout OLED,Baud,("S ") case 191 to 212 serout OLED,Baud,("SSW ") case 213 to 235 serout OLED,Baud,("SW ") case 236 to 258 serout OLED,Baud,("WSW ") case 259 to 280 serout OLED,Baud,("W ") case 281 to 302 serout OLED,Baud,("WNW ") case 303 to 325 serout OLED,Baud,("NW ") case 336 to 347 serout OLED,Baud,("NNW ") case 348 to 360 serout OLED,Baud,("N ") END SELECT return Bill Edited 2022-02-08 06:48 by Bill.b In the interests of the environment, this post has been constructed entirely from recycled electrons. |
||||
Print this page |