ATMEGA32 + MMA8452q i2C communication

Hi,

i bought the accelerometer MMA8452q and i try to interface it with my atmega32 between i2c commuication and receive data, but, at now, without success.

The problem is that i read the datasheet, but the accelerometer is installed on a breakout board by sparkfun so all is not very clear.

For now i want to start communication between MMA8452q, read data and print on a LCD monitor (ready), but with my code i try to read register 0x23 of MMA8452q but on my LCD i don’t read anything.

Anyone has used this component with an avr microcontroller and can help me?

To start i have 2 questions:

  • breakout board has installed a pull up resistor to i2C communication???

  • accelerometer when is powered starts in standby mode, so i have to initializa it???

  • accelerometer speak in 8bit or 12bit??

thank you for your help

debug86:
Hi,

i bought the accelerometer MMA8452q and i try to interface it with my atmega32 between i2c commuication and receive data, but, at now, without success.

The problem is that i read the datasheet, but the accelerometer is installed on a breakout board by sparkfun so all is not very clear.

So you bought a product without reading the description? The Documents section has everything you will ever need to know about the breakout board.

For now i want to start communication between MMA8452q, read data and print on a LCD monitor (ready), but with my code i try to read register 0x23 of MMA8452q but on my LCD i don’t read anything.

Ok? Without any reference to your code, how would we know how to help? So post you entire code in code tags.

To start i have 2 questions:

  • breakout board has installed a pull up resistor to i2C communication???

  • accelerometer when is powered starts in standby mode, so i have to initializa it???

  • accelerometer speak in 8bit or 12bit??

That’s 3 questions. First question can be answered by clicking on the first link in the Documents section. The answer to the second question can be found by reading the Setup portion of the example sketch:

initMMA8452(); //Test and intialize the MMA8452

The 3 rd question can be answered by reading the description, but the short answer is both.

Dear codlink i’m new in electronic development, so i’m learning to choice component e program avr micro controller.

I will post my code this evening thank you.

Thanks to codLink i have read data from accelerometer with success, but i have a little problem, i read X register and write data on LCD but this data not update during the while loop, why???

If i have understand what say the datasheet, the registers content not updates untill the accelerometer is in active mode, but it have to be toggle from active to standby and so in active again to update register content.

I have well understand???

Thak you for your help.

Here is my code:

Accelerometer.cpp

#include <avr/io.h>
#include <avr/interrupt.h>
#include "MrLCD.h"
#include "defs.h"
#include "i2c.h"
#include "i2c.c"
#include "types.h"

#define ACC_ADDRESS_R 0x3b
#define ACC_ADDRESS_W 0x3a
#define ACC_XYZ_REGISTER 0x01

//Metodi
uint8_t readRegister(uint8_t registro);
uint8_t* readMultipleDataFromRegister(uint8_t registro);
void writeDataOnLcd(uint8_t position_row, uint8_t position_column, uint8_t data, uint8_t base);
void putAccelerometerToActiveMode();
void putAccelerometerToStandByMode();

int main(void) {
	uint8_t receivedByte, receivedByte2, receivedByte3, received_who_am_i;
	uint8_t who_am_i, registerToRead, registerToRead2, registerToRead3;
	
	/* Inizializzo monitor lcd e scrivo il titolo */		
	InitializeMrLCD();
	/* Inizializzo la comunicazione i2C */
	initI2C();

while (1) {	
	who_am_i = 0x0D;
	received_who_am_i = readRegister(who_am_i);
	registerToRead = 0x01;
	receivedByte = readRegister(registerToRead);

	uint8_t* dataX = readMultipleDataFromRegister(registerToRead);
	uint8_t i;
	
	if(received_who_am_i = 0x2A) {
		/* Controllo stato accelerometro */
		GotoMrLCDsLocation(1,1);
		Send_A_String("Status: OK");
	
		for (i=0; i<100; i++) {
			/* Print X POSITION */
			GotoMrLCDsLocation(1,2);
			Send_A_String("MSB:");
			writeDataOnLcd(2,5,dataX[i],10);
			
			GotoMrLCDsLocation(9,2);
			Send_A_String("LSB:");
			writeDataOnLcd(2,7,dataX[i+1],10);
			_delay_ms(1000);
		}
	} else {
		GotoMrLCDsLocation(1,1);
		Send_A_String("Status: NO");
	}
	return(0);
}

}

/* Metodo che scrive un dato sul monitor LCD */
void writeDataOnLcd(uint8_t position_row, uint8_t position_column, uint8_t data, uint8_t base) {
	GotoMrLCDsLocation(position_column,position_row);
	char snum[8];
	//Converto il valore in formato intero preso dal pin ADC in string
	itoa(data, snum, base);
	Send_A_String(snum);
}

/* Metodo che legge un registro dall'accelerometro */
uint8_t readRegister(uint8_t registro) {
		i2cStart();
		i2cSend(ACC_ADDRESS_W);
		i2cSend(registro);
		i2cStart();
		i2cSend(ACC_ADDRESS_R);
		uint8_t data = i2cReadNoAck();
		//receivedByte2 = i2cReadNoAck();
		i2cStop();	
	return data;
}

/* Metodo che legge un registro dall'accelerometro */
uint8_t* readMultipleDataFromRegister(uint8_t registro) {
	uint8_t data[100];
	uint8_t j;
	i2cStart();
	i2cSend(ACC_ADDRESS_W);
	i2cSend(registro);
	i2cStart();
	i2cSend(ACC_ADDRESS_R);
	for(j=0; j<100; j++) {
		data[j]= i2cReadAck();
	}
	//uint8_t data = i2cReadAck();
	//receivedByte2 = i2cReadNoAck();
	i2cStop();
	return data;
}

/* Metodo che legge un registro dall'accelerometro */
uint8_t* readMultipleDataFromMultipleRegisters(uint8_t registro, uint8_t registro2) {
	uint8_t data[100];
	uint8_t j;
	i2cStart();
	i2cSend(ACC_ADDRESS_W);
	i2cSend(registro);
	i2cStart();
	i2cSend(ACC_ADDRESS_R);
	for(j=0; j<50; j+2) {
		data[j]= i2cReadAck();
	}
	//uint8_t data = i2cReadAck();
	//receivedByte2 = i2cReadNoAck();
	i2cStop();
	
	_delay_ms(100);
	
	i2cStart();
	i2cSend(ACC_ADDRESS_W);
	i2cSend(registro);
	i2cStart();
	i2cSend(ACC_ADDRESS_R);
	for(j=1; j<50; j+2) {
		data[j]= i2cReadAck();
	}
	//uint8_t data = i2cReadAck();
	//receivedByte2 = i2cReadNoAck();
	i2cStop();
	
	return data;
}

/* Metodo che mette l'accelerometro in stand by mode */
void putAccelerometerToStandByMode() {
	uint8_t standByRegister = 0x2A;
	uint8_t command = 00000001;
	i2cStart();
	i2cSend(ACC_ADDRESS_W);
	i2cSend(standByRegister);
	//i2cStart();
	i2cSend(command);
	i2cStop();
}

/* Metodo che mette l'accelerometro in active mode */
void putAccelerometerToActiveMode() {
	uint8_t activeRegister = 0x2A;
	uint8_t command = 00000000;
	i2cStart();
	i2cSend(ACC_ADDRESS_W);
	i2cSend(activeRegister);
	//i2cStart();
	i2cSend(command);
	i2cStop();
}

i2c.c

#include "i2c.h"

void initI2C(void) {
TWBR = 32;
  TWCR |= (1 << TWEN);
}

void i2cWaitForComplete(void) {
loop_until_bit_is_set(TWCR, TWINT);
}

void i2cStart(void) {
TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWSTA));
i2cWaitForComplete();
}

void i2cStop(void) {
TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWSTO));
}

uint8_t i2cReadAck(void) {
TWCR = (_BV(TWINT) | _BV(TWEN) | _BV(TWEA));
i2cWaitForComplete();
return (TWDR);
}

uint8_t i2cReadNoAck(void) {
TWCR = (_BV(TWINT) | _BV(TWEN));
i2cWaitForComplete();
return (TWDR);
}

void i2cSend(uint8_t data) {
TWDR = data;
TWCR = (_BV(TWINT) | _BV(TWEN));
i2cWaitForComplete();
}

i2c.h

// Functions for i2c communication 
#include <avr/io.h>

/* Sets pullups and initializes bus speed to 100kHz (at FCPU=8MHz) */
void initI2C(void);

/* Waits until the hardware sets the TWINT flag */
void i2cWaitForComplete(void);

/* Sends a start condition (sets TWSTA) */
void i2cStart(void); 

 /* Sends a stop condition (sets TWSTO) */
void i2cStop(void);

/* Loads data, sends it out, waiting for completion */
void i2cSend(uint8_t data);

/* Read in from slave, sending ACK when done (sets TWEA) */
uint8_t i2cReadAck(void);

/* Read in from slave, sending NOACK when done (no TWEA) */ 
uint8_t i2cReadNoAck(void);

MrLCD.h

#ifndef MrLCD
#define MrLCD

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

#define MrLCDsCrib PORTB
#define DataDir_MrLCDsCrib DDRB
#define MrLCDsControl PORTD
#define DataDir_MrLCDsControl DDRD
#define LightSwitch 5
#define ReadWrite 7
#define BiPolarMood 2

char firstColumnPositionsForMrLCD[4] = {0, 64, 20, 84};

void Check_IF_MrLCD_isBusy(void);
void Peek_A_Boo(void);
void Send_A_Command(unsigned char command);
void Send_A_Character(unsigned char character);
void Send_A_String(char *StringOfCharacters);
void GotoMrLCDsLocation(uint8_t x, uint8_t y);
void InitializeMrLCD(void);

void Check_IF_MrLCD_isBusy()
{
	DataDir_MrLCDsCrib = 0;
	MrLCDsControl |= 1<<ReadWrite;
	MrLCDsControl &= ~1<<BiPolarMood;

	while (MrLCDsCrib >= 0x80)
	{
		Peek_A_Boo();
	}

	DataDir_MrLCDsCrib = 0xFF; //0xFF means 0b11111111
}

void Peek_A_Boo()
{
	MrLCDsControl |= 1<<LightSwitch;
	asm volatile ("nop");
	asm volatile ("nop");
	MrLCDsControl &= ~1<<LightSwitch;
}

void Send_A_Command(unsigned char command)
{
	Check_IF_MrLCD_isBusy();
	MrLCDsCrib = command;
	MrLCDsControl &= ~ ((1<<ReadWrite)|(1<<BiPolarMood));
	Peek_A_Boo();
	MrLCDsCrib = 0;
}

void Send_A_Character(unsigned char character)
{
	Check_IF_MrLCD_isBusy();
	MrLCDsCrib = character;
	MrLCDsControl &= ~ (1<<ReadWrite);
	MrLCDsControl |= 1<<BiPolarMood;
	Peek_A_Boo();
	MrLCDsCrib = 0;
}

void Send_A_String(char *StringOfCharacters)
{
	while(*StringOfCharacters > 0)
	{
		Send_A_Character(*StringOfCharacters++);
	}
}

void GotoMrLCDsLocation(uint8_t x, uint8_t y)
{
	Send_A_Command(0x80 + firstColumnPositionsForMrLCD[y-1] + (x-1));
}

void InitializeMrLCD()
{
	DataDir_MrLCDsControl |= 1<<LightSwitch | 1<<ReadWrite | 1<<BiPolarMood;
	_delay_ms(15);

	Send_A_Command(0x01); //Clear Screen 0x01 = 00000001
	_delay_ms(2);
	Send_A_Command(0x38);
	_delay_us(50);
	Send_A_Command(0b00001110);
	_delay_us(50);
}

#endif

Last question, in main code I print on LCD, 100 X direction datas, but with accelerometer motionless i read all different numbers, why???

And if i move the accelerometer datas not change, why???

I don’t understand.

Post the output you are getting. I don’t see any obvious errors in your code. If I had the accelerometer, I would test your code, but I don’t.

You say it’s printing the same series of numbers when the accelerometer is moving? And that data is being sent to the LCD? Have you tried the accelerometer without the LCD attached? How do you have everything connected? A schematic or drawing would be nice.

For now i try only with lcd connected , yes, when i move the accelerometer i have the same numbers, tomorrow i’ll post them.

This is the connection:

ACCELEROMETER ATMEGA32

SDA -------------------------- SDA

SCL -------------------------- SCL

VCC ---- 3,3V

GND — GND

This is the output when i read:

  • register 0x01 i receive repetitively this 7 number:

4 220 870 164 142 442 042 442

  • register 0x02 i receive repetitively this 7 number:

220 830 180 142 132 032 432

I asked if you could disconnect the LCD and test just the accelerometer. Have the accelerometer print data to a serial monitor.

Not for now, but i have bought atmel stk500 so i have to try this.