Solved: Magnetometer QMC5883L + mega328p issue

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I have a problem with initialization the magnetometer sensor QMC5883L on the mega328p on Arduino board. I write a code on a Arduino software and everything works properly. But now I want to change it for the code in C language for AVR. So at the beginning i want to display information from magnetometer by the USART. I based on this tutorial https://www.electronicwings.com/avr-atmega/magnetometer-hmc5883l-interfacing-with-atmega16. This tutorial is dedicated for HMC5883L magnetometer and I tried to change it to the QMC5883L based on datasheet: http://wiki.epalsite.com/images/7/72/QMC5883L-Datasheet-1.0.pdf and Arduino dedicated library. When I initialize magnetometer, the USART did not respond. Nothing happens.

 

Please help. Below is the code:

#define F_CPU 16000000UL
#define FOSC 16000000	// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

#include <avr/io.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "I2C_Master_H_file.h"
#include "USART_irq.h"

#define I2C_READ 1
#define I2C_WRITE 0

#define QMC5883L_ADDR	0x0D							/* Magnetometer QMC5883L Address */

static FILE mystdout = FDEV_SETUP_STREAM(USART0_Transmit_IO, NULL,_FDEV_SETUP_WRITE);

void Magneto_init()										/* Magneto initialize function */
{
	I2C_Start(QMC5883L_ADDR+I2C_WRITE);					/* Start and write SLA+W */
	I2C_Write(0x0B);									/* Defined Set/Reset Period as Default */
	I2C_Write(0x01);									/* Configure register  */
	I2C_Write(0x09);
	I2C_Write(0x12);									/* Configure register OSR = 512, Full Scale Range = 8G(Gauss), ODR = 200HZ, set continuous measurement mode */
 	I2C_Stop();											/* Stop I2C */

}

void Magneto_GetPos(int *x, int *y, int *z)
{

		I2C_Start_Wait(QMC5883L_ADDR+I2C_WRITE);					/* Start and wait for acknowledgment */
		I2C_Write(0x00);											/* Write X register address */										

		I2C_Repeated_Start(QMC5883L_ADDR+I2C_READ);						/* Generate repeat start condition with SLA+R */
		/* Read 16 bit x,y,z value (2’s complement form) */
		*x = ((int)I2C_Read_Ack() | ((int)I2C_Read_Ack()<<8));
		*y = ((int)I2C_Read_Ack() | ((int)I2C_Read_Ack()<<8));
		*z = ((int)I2C_Read_Ack() | ((int)I2C_Read_Nack()<<8));

		I2C_Stop();

}

int main(void)
{

	I2C_Init();											/* Initialize I2C */
	Magneto_init();
    USART0_Init(MYUBRR);								// Calculate baud rate

	sei();				/* Enable interrupts => enable UART interrupts */

	stdout = &mystdout;

	int xAxis = 0 , yAxis = 0, zAxis = 0;
	int i = 0;

    while (1)
    {
		Magneto_GetPos(&xAxis, &yAxis, &zAxis);
		printf("x: %d | y: %d | z: %d | t -> %d\n", xAxis, yAxis, zAxis, i);

		i++;
		_delay_ms(1000);
    }
}

 

 

Last Edited: Sun. Aug 25, 2019 - 12:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arduino board uses a mega328. Are you sure yours is a mega32?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry my mistake. You're right. Arduino uses mega328p

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Change the title and post to avoid confusion.
Isthe uart working?

My guess is your i2c address is not correct for the library you are using. This is a common source of confusion. In some cases you must shift the device address left one bit

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After your suggestion to shift device address, the uart starts working and displays constant numbers, so it helped a little bit. But it doesn't display actual measured values.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I fix it. Now works fine. UART displays actual measured values. I've just replaced lines 

 

I2C_Start(QMC5883L_ADDR+I2C_WRITE);
...
I2C_Start_Wait(QMC5883L_ADDR+I2C_WRITE);
...
I2C_Repeated_Start(QMC5883L_ADDR+I2C_READ);

on these

I2C_Start(((QMC5883L_ADDR)<<1) | I2C_WRITE);
...
I2C_Start_Wait(((QMC5883L_ADDR)<<1) | I2C_WRITE);
...
I2C_Repeated_Start(((QMC5883L_ADDR)<<1) | I2C_READ);

Thank you for your help Kartman smiley.