CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

please help! QMC5883L compass library. upg: SOLVED!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

please help! QMC5883L compass library. upg: SOLVED!
PostPosted: Sat Aug 28, 2021 9:41 am     Reply with quote

Hi everyone!

I have qmc5883L (address is 0x0d) compass sensor and i need library for ccs c. I use 16F887. I found many libraries on internet which are hmc5883 but they never worked for me at all

one of my friend said that to me " Hmc5883 libraries wont work for the QMC because qmc registers are completely different from the HMC... Even the operating modes are different... The QMC doesn't even have a single measurement mode (i did a really fast datasheet read)... " so it means that I need a new qmc5883 library according to datasheet. this sensor is key part of my project, looking for your help very much!

I do this as a hobby, still learning codes and trying to
understand i2c and i don't know how to read datasheets correctly for now:(
Thats why I need your help, Thank you!


This is a Library of hmc5883L. Maybe we can convert it to a QMC5883 Library according to QMC5883 datasheet ? What do you think?

Code:
// HMC5883 required Registers

#define W_DATA   0x3C     //'Used to perform a Write operation
#define R_DATA   0x3D     //'Used to perform a Read operation
#define CON_A    0x00
#define CON_B    0x01     //'Send continuous MeVARurement mode.
#define MOD_R    0x02     //'Read/Write Register, Selects the operating mode. Default = Single meVARurement
#define X_MSB    0x03     //'Read Register, Output of X MSB 8-bit value.
#define X_LSB    0x04     //'Read Register, Output of X LSB 8-bit value.
#define Z_MSB    0x05     //'Read Register, Output of Z MSB 8-bit value.
#define Z_LSB    0x06     //'Read Register, Output of Z LSB 8-bit value.
#define Y_MSB    0x07     //'Read Register, Output of Y MSB 8-bit value.
#define Y_LSB    0x08     //'Read Register, Output of Y LSB 8-bit value.

void hmc5883_write(int add, int data)
{
         i2c_start();
         i2c_write(W_DATA);
         i2c_write(add);
         i2c_write(data);
         i2c_stop();
 
}
     
int16 hmc5883_read(int add){
         int retval;
         i2c_start();
         i2c_write(W_DATA);
         i2c_write(add);
         i2c_start();
         i2c_write(R_DATA);
         retval=i2c_read(0);
         i2c_stop();
         return retval;
}
 
void hmc5883_init(){
         hmc5883_write(MOD_R,  0x00);
         delay_ms(100);
         hmc5883_write(CON_A,  0x10);
         delay_ms(100);
         hmc5883_write(CON_B,  0x20);
         delay_ms(100);
}


And this is an example:
Code:
#include <16f877A.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES HS                       //Dont change
#use    delay(clock=20MHz) 
#use I2C(master, sda=PIN_d0, scl=PIN_d1, slow)  //You can change, according your board ports
#include "EXLCD.C"  //You can change, according your board ports
#include "HMC5883.C"
#include "math.h"
int8 M_data[6]; //6 units 8 bit Measured datas
int16 Xm=0,Ym=0,Zm=0; //16 bit X,Y,Z variables

void main()
{
delay_ms(2);
lcd_init();
hmc5883_init();   
   
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
printf(lcd_putc,"    HMC5883L    ");
lcd_gotoxy(1,2);
printf(lcd_putc,"Digital Compass ");
delay_ms(1000);
printf(lcd_putc,"\f");

   while(TRUE)
   {
   M_data[0]=hmc5883_read(0x04); //Read X (LSB)
   M_data[1]=hmc5883_read(0x03); //Read X (MSB)
   M_data[2]=hmc5883_read(0x08); //Read Y (LSB)
   M_data[3]=hmc5883_read(0x07); //Read Y (MSB)
   M_data[4]=hmc5883_read(0x06); //Read Z (LSB)
   M_data[5]=hmc5883_read(0x05); //Read Z (MSB)

   Xm=make16(M_data[1],M_data[0]);
   Ym=make16(M_data[3],M_data[2]);
   Zm=make16(M_data[5],M_data[4]);

   float Heading = atan2((signed int16)Ym,(signed int16)Xm)* 180 / pi + 180;
       
   lcd_gotoxy(1,1);
   printf(lcd_putc,"X=%ld  ",Xm);
   lcd_gotoxy(9,1);
   printf(lcd_putc,"Y=%ld  ",Ym);
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Z=%ld  ",Zm);
   lcd_gotoxy(9,2);
   printf(lcd_putc,"H=%f  ",Heading);
   delay_ms(100);

   }
}


I'm looking forward for your helps! Thanks!


Last edited by sercankurt on Sun Aug 29, 2021 2:00 pm; edited 2 times in total
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 10:43 am     Reply with quote

First question:
That PIC is a 5 volt device, and most peripherals today are 3 volt devices so...
do you have logic level conversion between them ??
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 10:49 am     Reply with quote

Also you say 'address is 0xD', this sounds like a 7bit I2C address. If this
is the case the address for PIC I2C would be 1A for a write, and 1B for
reading. Not what you have in your code.
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 12:38 pm     Reply with quote

Ttelmah wrote:
Also you say 'address is 0xD', this sounds like a 7bit I2C address. If this
is the case the address for PIC I2C would be 1A for a write, and 1B for
reading. Not what you have in your code.


Thanks for answering, I tried as you said, but heading is written 180 and doesn't change so didn't work :( Maybe its HMC library can't work because "registers and operating modes ar different" as I mentioned in post my friend said. What do you think ? because even I change to 0x0d, or like you say 0x1a or 0x01b it doesnt works but i realized that heading number turned to 180 and stays like that when i changed address to 1a and 1b

Code:
#define W_DATA   0x1A     // **************
#define R_DATA   0x1B     //'*************
#define CON_A    0x00
#define CON_B    0x01     //'Send continuous MeVARurement mode.
#define MOD_R    0x02     //'Read/Write Register, Selects the operating mode. Default = Single meVARurement
#define X_MSB    0x03     //'Read Register, Output of X MSB 8-bit value.
#define X_LSB    0x04     //'Read Register, Output of X LSB 8-bit value.
#define Z_MSB    0x05     //'Read Register, Output of Z MSB 8-bit value.
#define Z_LSB    0x06     //'Read Register, Output of Z LSB 8-bit value.
#define Y_MSB    0x07     //'Read Register, Output of Y MSB 8-bit value.
#define Y_LSB    0x08     //'Read Register, Output of Y LSB 8-bit value.


Last edited by sercankurt on Sat Aug 28, 2021 12:44 pm; edited 1 time in total
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 12:40 pm     Reply with quote

temtronic wrote:
first question
That PIC is a 5 volt device, and most peripherals today are 3 volt devices so...
do you have logic level conversion between them ??


Thanks for answering! I think its all about library :(
Because I tried on Ardunio it works perfectly with 5 vdc.
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 12:48 pm     Reply with quote

By the way I tried my QMC5883L with ardunio in order to test and works perfectly, with this library and header:

https://github.com/keepworking/Mecha_QMC5883L

Maybe somebody could help me converting this library to ccs library, I think it would be perfect because codes are similar! thanks all!
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 1:04 pm     Reply with quote

Go to 'code library', download PCM P's I2C scanner program, compile and test on PIC. It will tell you the address of the device, if it finds it !!
With any I2C device, this should be done.
Sometimes premade modules will NOT be their 'default' address.

As pointed out ...Ardunio code use 7 bit I2C addresses, CCS uses 8 bit.
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

PostPosted: Sat Aug 28, 2021 1:44 pm     Reply with quote

temtronic wrote:
goto 'code library', download PCM P's I2C scanner program, compile and test on PIC. It will tell you the address of the device ,if it finds it !!
With any I2C device, this should be done.
Sometimes premade modules will NOT be their 'default' address.

As pointed out ...Ardunio code use 7 bit I2C addresses, CCS uses 8 bit.


I did that (with my 16f887) i2c scanner and it found 1A! but it still doesn't work when i write to address in library :(
Code:

#define W_DATA   0x1A     // **************
#define R_DATA   0x1B     //' when I write here 1B, heading written "180"  and just stays like that, this is the only difference
*

and also I tried like

Code:

#define W_DATA   0x1A     // **************
#define R_DATA   0x1A    //'************
*

but doesn't work.. Can you recommend or write or send me a library which could work with QMC5883L ?

can you look at this datasheet, can we write a simpe datasheet according to this? : https://electropeak.com/learn/download/datasheet-qmc5883l/
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sun Aug 29, 2021 9:24 am     Reply with quote

When you used the I2C scanner program, how was the I2C setup?.
Post the setup line you used for this.

Now there is a very significant issue, which comes down to understanding
voltages. The Arduino inputs use TTL threshold levels, so 2.4v is seen as
a logic '1'. On the PIC, the threshold levels depend on the pins being used,
and the peripheral involved. The actual I2C peripheral (if you used the
hardware), has it's '1' threshold as 4v. So a 3.3v device will not ever be
able to generate a logic 1. However if you set the hardware I2C to
SMBUS mode, this sets the hardware threshold down to a lower level
that should work.
The scanner program never has to actually see a logic '1' from the device
it is instead dependant only on the ACK/NACK bit.

Now you are showing the connections to a software I2C. The pins you show
(D0 & D1), have Schmidt input thresholds, so require the signal (with the
PIC at 5v), to get up to 3.5v, before a '1' will be seen. So not going to work.
Move your compass to connect to any of pins B1 to B5, A0 to A3, or A5.
These are the PIC pins on your chip, that have TTL input thresholds (so
like the Arduino pins).

The thresholds on the D pins, are Schmidt when it is used as a I/O port,
and TTL when used as a PSP port. So Schmitt for your code.

You are not understanding how voltage requirements are not just
dependant on being a 5v or 3.3v device, but depend on the actual pins
involved.
sercankurt



Joined: 28 Aug 2021
Posts: 12

View user's profile Send private message

PostPosted: Sun Aug 29, 2021 1:59 pm     Reply with quote

temtronic wrote:
Go to 'code library', download PCM P's I2C scanner program, compile and test on PIC. It will tell you the address of the device, if it finds it !!
With any I2C device, this should be done.
Sometimes premade modules will NOT be their 'default' address.

As pointed out ...Ardunio code use 7 bit I2C addresses, CCS uses 8 bit.


Ttelmah wrote:
When you used the I2C scanner program, how was the I2C setup?.
Post the setup line you used for this.

Now there is a very significant issue, which comes down to understanding
voltages. The Arduino inputs use TTL threshold levels, so 2.4v is seen as
a logic '1'. On the PIC, the threshold levels depend on the pins being used,
and the peripheral involved. The actual I2C peripheral (if you used the
hardware), has it's '1' threshold as 4v. So a 3.3v device will not ever be
able to generate a logic 1. However if you set the hardware I2C to
SMBUS mode, this sets the hardware threshold down to a lower level
that should work.
The scanner program never has to actually see a logic '1' from the device
it is instead dependant only on the ACK/NACK bit.

Now you are showing the connections to a software I2C. The pins you show
(D0 & D1), have Schmidt input thresholds, so require the signal (with the
PIC at 5v), to get up to 3.5v, before a '1' will be seen. So not going to work.
Move your compass to connect to any of pins B1 to B5, A0 to A3, or A5.
These are the PIC pins on your chip, that have TTL input thresholds (so
like the Arduino pins).

The thresholds on the D pins, are Schmidt when it is used as a I/O port,
and TTL when used as a PSP port. So Schmitt for your code.

You are not understanding how voltage requirements are not just
dependant on being a 5v or 3.3v device, but depend on the actual pins
involved.


Dear Temtronic and Ttelmah, thank you for your all reply!! I just solved it by coincidence ! I found the registers and some i2c numbers(I tried and worked by coincidence:)) ) from datasheet and changed on the library and it works perfectly now. Shame on me that I don't know how to read datasheet correctly, but I will learn by time. I was lucky for now!

I'm sharing the below:

Code:
// HMC5883 required Registers

#define W_DATA   0x1A     //'Used to perform a Write operation
#define R_DATA   0x1B     //'Used to perform a Read operation
#define CON_A    0xA0
#define CON_B    0x0B     //'Send continuous Measurement mode.
#define MOD_R    0x09     //'Read/Write Register, Selects the operating mode. Default = Single meVARurement

#define X_MSB    0x01     //'Read Register, Output of X MSB 8-bit value.
#define X_LSB    0x00     //'Read Register, Output of X LSB 8-bit value.
#define Z_MSB    0X05     //'Read Register, Output of Z MSB 8-bit value.
#define Z_LSB    0X04     //'Read Register, Output of Z LSB 8-bit value.
#define Y_MSB    0X03     //'Read Register, Output of Y MSB 8-bit value.
#define Y_LSB    0X02     //'Read Register, Output of Y LSB 8-bit value.

void hmc5883_write(int add, int data)
{
         i2c_start();
         i2c_write(W_DATA);
         i2c_write(add);
         i2c_write(data);
         i2c_stop();
 
}
     
int16 hmc5883_read(int add){
         int retval;
         i2c_start();
         i2c_write(W_DATA);
         i2c_write(add);
         i2c_start();
         i2c_write(R_DATA);
         retval=i2c_read(0);
         i2c_stop();
         return retval;
}
 
void hmc5883_init(){
         
         hmc5883_write(CON_B,  0x01);
         delay_ms(100);
         hmc5883_write(MOD_R,  0b10011001);
         delay_ms(100);
         hmc5883_write(CON_A,  0b10000001);
         delay_ms(100);
}


and example:

Code:
#include <16F887.h>
#fuses HS, NOWDT, NOPROTECT, NOMCLR
#use delay(clock=20M)
#use I2C(MASTER, sda=PIN_C4, scl=PIN_C3, fast=100000, force_hw)  //You can change, according your board ports
#use RS232(BAUD = 9600, XMIT = PIN_C6, RCV = PIN_C7, STOP = 1, STREAM = Bluetooth)
#include "i2c_flex_lcd.c"
#include "HMC5883.c"
#include "math.h"
int8 M_data[6]; //6 units 8 bit Measured datas
int16 Xm=0,Ym=0,Zm=0; //16 bit X,Y,Z variables

void main()
{
delay_ms(10);
lcd_init(0x7e,16,2);
hmc5883_init();
lcd_clear();

   while(TRUE)
   {
   M_data[0]=hmc5883_read(0x00); //Read X (LSB)
   M_data[1]=hmc5883_read(0x01); //Read X (MSB)
   M_data[2]=hmc5883_read(0x02); //Read Y (LSB)
   M_data[3]=hmc5883_read(0x03); //Read Y (MSB)
   M_data[4]=hmc5883_read(0x04); //Read Z (LSB)
   M_data[5]=hmc5883_read(0x05); //Read Z (MSB)

   Xm=make16(M_data[1],M_data[0]);
   Ym=make16(M_data[3],M_data[2]);
   Zm=make16(M_data[5],M_data[4]);

   float Heading = atan2((signed int16)Ym-360,(signed int16)Xm-310) * 180 / pi + 180;
       
   lcd_gotoxy(1,1);
   printf(lcd_putc,"X=%ld  ",Xm);
   lcd_gotoxy(9,1);
   printf(lcd_putc,"Y=%ld  ",Ym);
   lcd_gotoxy(1,2);
   printf(lcd_putc,"Z=%ld  ",Zm);
   lcd_gotoxy(9,2);
   printf(lcd_putc,"h=%f   ",Heading);
   
   fprintf(bluetooth,"\n h=%f   ",Heading);
   delay_ms(250);
   }
}
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Aug 29, 2021 2:14 pm     Reply with quote

I'm happy you got it working !!!

Jay
cyril.carlita



Joined: 20 Jul 2023
Posts: 5

View user's profile Send private message Visit poster's website

PostPosted: Thu Jul 20, 2023 1:41 pm     Reply with quote

Hello, i tried the first code, it works for me but the direction that indicate the north is not very well.

After i have tried the last code, it doesn't work for me, the lcd indicates
x=-1 y=-1 z=-1 h=49.25


Does the first code good for you? Question
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group