how to fake hmc5883l (qmc5883l) connect to the multiiwii code ???

I have qmc5883l magnetometer sensor. It’s not compatible with multiwii code because of multiwii code support hmc5883l original sensor. qmc5883l sensor registry address different. I attached the datasheet of both sensors.

This is the multiwii code.

// ************************************************************************************************************
// I2C Compass HMC5883
// ************************************************************************************************************
// I2C adress: 0x3C (8bit)   0x1E (7bit)
// ************************************************************************************************************

#if defined(HMC5883)

#define HMC58X3_R_CONFA 0
#define HMC58X3_R_CONFB 1
#define HMC58X3_R_MODE 2
#define HMC58X3_X_SELF_TEST_GAUSS (+1.16)                       //!< X axis level when bias current is applied.
#define HMC58X3_Y_SELF_TEST_GAUSS (+1.16)   //!< Y axis level when bias current is applied.
#define HMC58X3_Z_SELF_TEST_GAUSS (+1.08)                       //!< Y axis level when bias current is applied.
#define SELF_TEST_LOW_LIMIT  (243.0/390.0)   //!< Low limit when gain is 5.
#define SELF_TEST_HIGH_LIMIT (575.0/390.0)   //!< High limit when gain is 5.
#define HMC_POS_BIAS 1
#define HMC_NEG_BIAS 2

#define MAG_ADDRESS 0x1E
#define MAG_DATA_REGISTER 0x03

static int32_t xyz_total[3]={0,0,0};  // 32 bit totals so they won't overflow.

static void getADC() {
  i2c_getSixRawADC(MAG_ADDRESS,MAG_DATA_REGISTER);
  MAG_ORIENTATION( ((rawADC[0]<<8) | rawADC[1]) ,
                   ((rawADC[4]<<8) | rawADC[5]) ,
                   ((rawADC[2]<<8) | rawADC[3]) );
}

static uint8_t bias_collect(uint8_t bias) {
  int16_t abs_magADC;

  i2c_writeReg(MAG_ADDRESS, HMC58X3_R_CONFA, bias);            // Reg A DOR=0x010 + MS1,MS0 set to pos or negative bias
  for (uint8_t i=0; i<10; i++) {                               // Collect 10 samples
    i2c_writeReg(MAG_ADDRESS,HMC58X3_R_MODE, 1);
    delay(100);
    getADC();                                                  // Get the raw values in case the scales have already been changed.
    for (uint8_t axis=0; axis<3; axis++) {
      abs_magADC =  abs(imu.magADC[axis]);
      xyz_total[axis]+= abs_magADC;                            // Since the measurements are noisy, they should be averaged rather than taking the max.
      if ((int16_t)(1<<12) < abs_magADC) return false;         // Detect saturation.   if false Breaks out of the for loop.  No sense in continuing if we saturated.
    }
  }
  return true;
}

static void Mag_init() {
  bool bret=true;                // Error indicator

  // Note that the  very first measurement after a gain change maintains the same gain as the previous setting. 
  // The new gain setting is effective from the second measurement and on.
  i2c_writeReg(MAG_ADDRESS, HMC58X3_R_CONFB, 2 << 5);  //Set the Gain
  i2c_writeReg(MAG_ADDRESS,HMC58X3_R_MODE, 1);
  delay(100);
  getADC();  //Get one sample, and discard it

  if (!bias_collect(0x010 + HMC_POS_BIAS)) bret = false;
  if (!bias_collect(0x010 + HMC_NEG_BIAS)) bret = false;

  if (bret) // only if no saturation detected, compute the gain. otherwise, the default 1.0 is used
    for (uint8_t axis=0; axis<3; axis++)
      magGain[axis]=820.0*HMC58X3_X_SELF_TEST_GAUSS*2.0*10.0/xyz_total[axis];  // note: xyz_total[axis] is always positive

  // leave test mode
  i2c_writeReg(MAG_ADDRESS ,HMC58X3_R_CONFA ,0x70 ); //Configuration Register A  -- 0 11 100 00  num samples: 8 ; output rate: 15Hz ; normal measurement mode
  i2c_writeReg(MAG_ADDRESS ,HMC58X3_R_CONFB ,0x20 ); //Configuration Register B  -- 001 00000    configuration gain 1.3Ga
  i2c_writeReg(MAG_ADDRESS ,HMC58X3_R_MODE  ,0x00 ); //Mode register             -- 000000 00    continuous Conversion Mode
  delay(100);
}

#if !defined(MPU6050_I2C_AUX_MASTER)
static void Device_Mag_getADC() {
  getADC();
}
#endif
#endif

sorry for the bad english .
pls help.

HMC5883L_3-Axis_Digital_Compass_IC.pdf (718 KB)

QMC5883L-Datasheet-1.0 (1).pdf (1020 KB)

Sensors.cpp (59.9 KB)

please help me.

You could ask the people of the multiwii project to add the QMC sensor.
You could buy a real HMC5883L. They cost between 1 and 2 dollars at AliExpress. Be sure not to buy another fake one.
You could hire a professional programmer.
You could try to make it yourself.

For us, without multiwii and without the QMC sensor, it is hard to do that with no testing.

For only 1 or 2 dollars this problem is solved. Use the real HMC5883L and not the fake QMC sensor.

Sorry for replying on such an old thread, but I had to conquer the same problem. There are no informations on the multiwii forum / google - so I tried to find a solution on my own.
Seemingly there’s no way to get one of the real HMC5883LElectronic Compass chips by Honeywell because production has been stopped.
I am really new into Arduino, I2C + everything around so there is NO GUARANTEE for proper function!
I would be pleased if someone could give me hints for better implementation.

I did the following workaround to the Multiwii code:

Navigate to config.h add the line somewhere behind /* I2C magnetometer */:

#define QMC5883

uncomment the other magnetometers

Navigate to sensors.cpp add following somewhere behind the last #endif statement at the magnetometer section:

// ************************************************************************************************************
// I2C Compass QMC5883L
// ************************************************************************************************************
// I2C adress: 0x0D (7bit)
// ************************************************************************************************************
#if defined(QMC5883)

#define MAG_ADDRESS 0x0D
#define MAG_DATA_REGISTER 0x00

//REG CONTROL

#define MAG_CTRL_REG1 0x09
#define QMC_MODE 0xC1 // 11 00 00 01OSR=64(11); Range=2G(00); ODR=10Hz(00); MODE=Cont(01)
#define MAG_CTRL_REG2 0x0A 

void Mag_init() {
  i2c_writeReg(MAG_ADDRESS,0x0B,0x01);
  i2c_writeReg(MAG_ADDRESS,MAG_CTRL_REG1,QMC_MODE);
}


static void getADC() {
  i2c_getSixRawADC(MAG_ADDRESS,MAG_DATA_REGISTER);
  MAG_ORIENTATION( ((rawADC[1]<<8) | rawADC[0]) ,
                   ((rawADC[3]<<8) | rawADC[2]) ,
                   ((rawADC[5]<<8) | rawADC[4]) );
}

#if !defined(MPU6050_I2C_AUX_MASTER)
static void Device_Mag_getADC() {
  getADC();
}
#endif
#endif

Now we need to add the QMC to the MPU6050 I2C Master & Slave functionality:

Search for this comment in sensors.cpp:

//The MAG acquisition function must be replaced because we now talk to the MPU device

Add following lines inside static void Device_Mag_getADC(){} after i2c_getSixRawADC(MPU6050_ADDRESS, 0x49);:

#if defined(QMC5883)
        MAG_ORIENTATION( ((rawADC[1]<<8) | rawADC[0]) ,
                         ((rawADC[3]<<8) | rawADC[2]) ,
                         ((rawADC[5]<<8) | rawADC[4]) );
      #endif

Navigate to def.h search for the MAG 1 definition “#if” clause - add “|| defined(QMC5883)” - like this:

#if defined(HMC5883) || defined(HMC5843) || defined(AK8975) || defined(MAG3110) || defined(QMC5883)
  #define MAG 1
#else
  #define MAG 0
#endif

The original HMC5883 Code has lots of more lines because of some ominous bias and gain settings - the QMC5883 lacks those registers - Unfortunately I don’t have any knowledge about this and its benefits and no time to get into it. The data provided by the sensor seems to be reliable.

bibbosc:
Sorry for replying on such an old thread, but I had to conquer the same problem. There are no informations on the multiwii forum / google - so I tried to find a solution on my own.
Seemingly there’s no way to get one of the real HMC5883LElectronic Compass chips by Honeywell because production has been stopped.
I am really new into Arduino, I2C + everything around so there is NO GUARANTEE for proper function!
I would be pleased if someone could give me hints for better implementation.

I did the following workaround to the Multiwii code:

Navigate to config.h add the line somewhere behind /* I2C magnetometer */:

#define QMC5883

uncomment the other magnetometers

Navigate to sensors.cpp add following somewhere behind the last #endif statement at the magnetometer section:

// ************************************************************************************************************

// I2C Compass QMC5883L
// ************************************************************************************************************
// I2C adress: 0x0D (7bit)
// ************************************************************************************************************
#if defined(QMC5883)

#define MAG_ADDRESS 0x0D
#define MAG_DATA_REGISTER 0x00

//REG CONTROL

#define MAG_CTRL_REG1 0x09
#define QMC_MODE 0xC1 // 11 00 00 01OSR=64(11); Range=2G(00); ODR=10Hz(00); MODE=Cont(01)
#define MAG_CTRL_REG2 0x0A

void Mag_init() {
  i2c_writeReg(MAG_ADDRESS,0x0B,0x01);
  i2c_writeReg(MAG_ADDRESS,MAG_CTRL_REG1,QMC_MODE);
}

static void getADC() {
  i2c_getSixRawADC(MAG_ADDRESS,MAG_DATA_REGISTER);
  MAG_ORIENTATION( ((rawADC[1]<<8) | rawADC[0]) ,
                  ((rawADC[3]<<8) | rawADC[2]) ,
                  ((rawADC[5]<<8) | rawADC[4]) );
}

#if !defined(MPU6050_I2C_AUX_MASTER)
static void Device_Mag_getADC() {
  getADC();
}
#endif
#endif




Now we need to add the QMC to the MPU6050 I2C Master & Slave functionality: 

Search for this comment in sensors.cpp:


//The MAG acquisition function must be replaced because we now talk to the MPU device




Add following lines inside static void Device_Mag_getADC(){} after i2c_getSixRawADC(MPU6050_ADDRESS, 0x49);:


#if defined(QMC5883)
        MAG_ORIENTATION( ((rawADC[1]<<8) | rawADC[0]) ,
                        ((rawADC[3]<<8) | rawADC[2]) ,
                        ((rawADC[5]<<8) | rawADC[4]) );
      #endif




Navigate to def.h search for the MAG 1 definition "#if" clause - add "|| defined(QMC5883)" - like this:


#if defined(HMC5883) || defined(HMC5843) || defined(AK8975) || defined(MAG3110) || defined(QMC5883)
  #define MAG 1
#else
  #define MAG 0
#endif




The original HMC5883 Code has lots of more lines because of some ominous bias and gain settings - the QMC5883 lacks those registers - Unfortunately I don't have any knowledge about this and its benefits and no time to get into it. The data provided by the sensor seems to be reliable.

Old thread??? this is exactly what I was looking for!! many thanks… I’m making my own 5inch multiwii racing drone project atm, and have designed my own PCB…

and had 2 compasses with the IC “DA 5883 6010” that I did not work.
and guess what!! your addon in the sketch workss. only he is quite sensitive, the numbers jumping around
do i still have to adjust that?.

good job :wink:

BlacklineVW

Hey! Glad to help you :slight_smile: Your PCB is amazing!

Since my own drone consists only of my selfmade flightcontroller-board and a frame - I wasn't able to test ist under "real" circumstances. (to little spare time :/)
My values in MultiWiiConf seem to be quiet stable - maybe there are some interferences with conductive elements for example motors have huge magnetic output. You could try to mount your sensor on a bus cable far away from everything that might produce magnetic field.

Another reason could be this "gain adjustment / bias thing"mentioned in my previous post. Maybe someone here with ideas about this!?

QMC5883L vs. HMC5883L

QMC5883L
Wire.write(0x09); // mode register
Wire.write(0x1D); //continuous measurement mode
Wire.write(0x00); // register 3, X MSB register

HMC5883L
Wire.write(0x02); // mode register
Wire.write(0x00); //continuous measurement mode
Wire.write(0x03); // register 3, X MSB register

Request for MMC5883MA sensor too