8 years, 2 months ago.

I2C modules conflict

Hi all!

I'm developing an easy gyrocompass with FXOS8700 and FXAS21002 mounted on FRDM-K64F. Sensors are connected to different I2C: PTE24/PTE25 and PTD2/PTD3. When I try to enable both sensors, FXAS21002 falls off and its I2C module always receives NACK. FXOS8700 works properly. When I use only FXAS21002, it works properly.

Mbed version 111. Any clues?

FXAS header

#ifndef FXAS21002_H
#define FXAS21002_H
#include "mbed.h"
#include "Vector3.h"


#define FXAS21002_I2C_ADDRESS 0x40
 
#define FXAS21002_STATUS 0x00
#define FXAS21002_WHO_AM_I 0x0C
#define FXAS21002_CTRL_REG0 0x0D
#define FXAS21002_CTRL_REG1 0x13
#define FXAS21002_WHO_AM_I_VALUE 0xD7

class FXAS21002
{
public:

	FXAS21002(PinName sda, PinName scl);
	  
	bool isConnected();

	void config(void);
		
	void calibrate();

	bool isDataReady();

	void read(Vector3 &data);

private:
	void readReg( char reg, char * d, int len);


	I2C gyroi2c;
	Vector3 biases;
};

#endif

FXAS code

#include "FXAS21002.h"
#include "mbed.h"

FXAS21002::FXAS21002(PinName sda, PinName scl) : gyroi2c(sda,scl)
 {
	 
 }
    
 bool FXAS21002::isConnected()
 {
	 char d = 0;
	 readReg(FXAS21002_WHO_AM_I, &d, 1);
	 
	 return d == FXAS21002_WHO_AM_I_VALUE;
 }
 
 void FXAS21002::config(void)
 {
   char d[2];
   d[0] = FXAS21002_CTRL_REG1;                       //Puts device in standby mode
   d[1] = 0x08;
   gyroi2c.write(FXAS21002_I2C_ADDRESS, d,2);   
          
   
   d[0] = FXAS21002_CTRL_REG0;                       //sets FS =+/- 2000 dps
   d[1] = 0x00;
   gyroi2c.write(FXAS21002_I2C_ADDRESS, d, 2);   
           
   
   d[0] = FXAS21002_CTRL_REG1;                       //Puts device in active mode with ODR 200 Hz
   d[1] = 0x0A;
   gyroi2c.write(FXAS21002_I2C_ADDRESS, d,2);   
      
 }
 
 void FXAS21002::calibrate()
 {
	 int i = 0;
	 int nsamples = 200;
	 Vector3 tmp, bias_tmp;
	 
	 
	 while( i < nsamples)
	 {
		 if(isDataReady())
		 {
			 read(tmp);
			 bias_tmp = bias_tmp + tmp;
			 i++;
		 }
	 }	
	biases = bias_tmp / nsamples;
 }
 
 bool FXAS21002::isDataReady()
 {
	 char d = 0;
	 readReg(FXAS21002_STATUS, &d, 1);
	 
	 return d & (1 << 3);		 
 }
 
 void FXAS21002::read(Vector3 &data)
 {
  
	char data_bytes[7] = {0};

	readReg(FXAS21002_STATUS, data_bytes, 7);

	data.x =  (float)((int16_t)((data_bytes[1]*256) + (data_bytes[2]))) * 0.0625f - biases.x;
	data.y =  (float)((int16_t)((data_bytes[3]*256) + (data_bytes[4]))) * 0.0625f - biases.y;
	data.z =  (float)((int16_t)((data_bytes[5]*256) + (data_bytes[6]))) * 0.0625f - biases.z;

 }
 
void FXAS21002::readReg( char reg, char * d, int len)
{
	char cmd[1] = {reg};    
	gyroi2c.write( FXAS21002_I2C_ADDRESS, cmd, 1, true);
	gyroi2c.read ( FXAS21002_I2C_ADDRESS, d, len);
}


Question relating to:

1 Answer

8 years, 2 months ago.

Checking the schematic of the board or the datasheet of the K64 will show that both PTE24/PTE25 and PTD2/PTD3 connect to the same I2C engine (I2C_0). The onboard device is connected to PTE24/PTE25. Declaring another I2C object on PTD2/PTD3 will need the same I2C engine and disable the connection to PTE24/PTE25. You either need to connect both devices to PTE24/PTE25 or use I2C_1 to get two independent I2C engines. I2C_1 is connected to pins PTC10 (SCL) and PTC11(SDA).

Accepted Answer

Thank you very much! You've saved a lot of time for me!

posted by Borys Tymchenko 07 Feb 2016