Hello,
I am using the FXOS8700 as well as the FXAS21002 to log data at 50Hz. The issue I am having is the noise/error with the FXOS8700C. As a simple test I have the unit (FRDM-KL25Z with FRDM-STBC-AGM01 mounted) sitting on my desk not in any motion other than some typing on a keyboard now and then. HOwever under these conditions the accelerometer is reading anywhere from -8g ~ 1g on ALL axis. I an understand 1g on the Z axis but 8g on any channel to me means something is incorrect. I have included graphes of the X, Y and Z axis plotted using GNUPlot and each value multiplied by 0.976mg.
I have also attached my raw data file below with data from the X, Y and Z axis in semi raw form (the two bytes have been concatenated and shifted to get a 14 bit signed number). If the raw hex data would be more helpful I can obtain that and post that file as well. I do not believe it is an issue in my conversions as the Gyro data is almost noiseless (on the 250 dps scale its jumping between 0 ~ 0.25 dps)
If someone can please explain how to resolve this issue it would be very much appreciated. I have also included my full mbed code incase someone may feel there is an issue there.
Thankfully
Kas
#include "mbed.h" #include "SDFileSystem.h" //FXOS8700CQ #define FXOS_ADDRESS_W 0x3C #define FXOS_ADDRESS_R 0x3D #define FXOS_STATUS 0x00 #define FXOS_OUT_X_MSB 0x01 #define FXOS_F_SETUP 0x09 #define FXOS_TRIG_CFG 0x0A #define FXOS_SYS_MOD 0x0B #define FXOS_INT_SOURCE 0x0C #define FXOS_WHO_AM_I 0x0D #define FXOS_ID 0xC7 #define FXOS_XYZ_DATA_CFG 0x0E #define FXOS_TRANSIENT_CFG 0x1D #define FXOS_TRANSIENT_SRC 0x1E #define FXOS_ASLP_COUNT 0x29 #define FXOS_CTRL_REG_1 0x2A #define FXOS_CTRL_REG_2 0x2B #define FXOS_CTRL_REG_3 0x2C #define FXOS_CTRL_REG_4 0x2D #define FXOS_CTRL_REG_5 0x2E #define FXOS_OFF_X 0x2F #define FXOS_OFF_Y 0x30 #define FXOS_OFF_Z 0x31 #define FXOS_TEMP 0x51 #define FXOS_M_CTRL_REG_1 0x5B #define FXOS_M_CTRL_REG_2 0x5C #define FXOS_M_CTRL_REG_3 0x5D //FXAS21002C #define FXAS_ADDRESS_W 0x40 #define FXAS_ADDRESS_R 0x41 #define FXAS_STATUS 0x00 #define FXAS_OUT_X_MSB 0x01 #define FXAS_F_SETUP 0x09 #define FXAS_F_EVENT 0x0A #define FXAS_INT_SRC_FLAG 0x0B #define FXAS_WHO_AM_I 0x0C #define FXAS_ID 0xD7 #define FXAS_CTRL_REG_0 0x0D #define FXAS_RT_CFG 0x0E #define FXAS_TEMP 0x12 #define FXAS_CTRL_REG_1 0x13 #define FXAS_CTRL_REG_2 0x14 #define FXAS_CTRL_REG_3 0x15 //Global variables int FXAS_FIFO_FULL_FLAG = 0; int FXOS_FIFO_FULL_FLAG = 0; char fxos_data_1[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; char fxas_data_1[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Setup UART to PC Serial pc(USBTX, USBRX); //Setup I2C I2C sensors(PTE0, PTE1); //FXOS8700C Control Pins InterruptIn fxos_int1_8700(PTD4); //INT1-8700 InterruptIn fxos_int2_8700(PTA4); //INT2-8700 //FXAS21002C Control Pins InterruptIn fxas_int1_21002(PTA5); //INT1-21002 InterruptIn fxas_int2_21002(PTA13); //INT2-21002 //SD File System SDFileSystem sd(PTD2, PTD3, PTD1, PTD0, "sd"); ////LED Setup DigitalOut led_1(LED1, 1); //red DigitalOut led_2(LED2, 1); //green //DigitalOut led_3(LED3, 1); //blue <- NB!! Wont play nice with SDFileSystem //****************************************************************// //Functions int i2c_write(char address, char device_register, char data){ sensors.start(); sensors.write((char)address); sensors.write((char)device_register); sensors.write((char)data); sensors.stop(); return 0; } int i2c_write(char address, char device_register, int stop){ sensors.start(); sensors.write((char)address); sensors.write((char)device_register); if(stop == 1){ sensors.stop(); } return 0; } char i2c_read(char address, char device_register){ char data; sensors.start(); sensors.write(address); sensors.write(device_register); sensors.start(); sensors.write(address | 0x01); data = (char)sensors.read(0); sensors.stop(); return data; } int i2c_write_verify(char address, char device_register, char data){ char return_data; int return_val; sensors.start(); sensors.write((char)address); sensors.write((char)device_register); sensors.write((char)data); sensors.stop(); sensors.start(); sensors.write(address); sensors.write(device_register); sensors.start(); sensors.write(address | 0x01); return_data = sensors.read(0); sensors.stop(); if (return_data == data){ return_val = 0; } else{ return_val = -1; } return return_val; } int fxas_init() { int return_val = 0; int sensor_id = 0; sensor_id = i2c_read(FXAS_ADDRESS_W, FXAS_WHO_AM_I); // pc.printf("Expected ID from FXAS21002C is 0xD7\n\r"); // pc.printf("Returned value: %X\n\n\r", sensor_id); if (sensor_id == FXAS_ID){ return_val = 0; return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_CTRL_REG_1, 0x00); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_F_SETUP, 0x00); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_F_SETUP, 0x54); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_CTRL_REG_0, 0x03); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_CTRL_REG_2, 0xC2); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_CTRL_REG_3, 0x00); return_val += i2c_write_verify(FXAS_ADDRESS_W, FXAS_CTRL_REG_1, 0x13); } else{ return_val = -1; } return return_val; } int fxos_init() { int return_val = 0; int sensor_id = 0; sensor_id = i2c_read(FXOS_ADDRESS_W, FXOS_WHO_AM_I); // pc.printf("Expected ID from FXOS8700CQ is 0xC7\n\r"); // pc.printf("Returned value: %X\n\n\r", sensor_id); if (sensor_id == FXOS_ID){ return_val = 0; return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_1, 0x00); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_F_SETUP, 0x00); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_F_SETUP, 0x54); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_ASLP_COUNT, 0xFF); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_XYZ_DATA_CFG, 0x02); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_2, 0x00); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_3, 0x02); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_4, 0x41); //Enable FIFO & DRDY Interrupts return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_5, 0x40); //FIFO -> Int_1, DRDY -> Imt_2 return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_M_CTRL_REG_1, 0x00); return_val += i2c_write_verify(FXOS_ADDRESS_W, FXOS_CTRL_REG_1, 0x21); } else{ return_val = -1; } return return_val; } //Interrupt for FXAS21002 INT_1 void read_fxas_data(){ // //Read data from FXAS21002 sensor if(FXAS_FIFO_FULL_FLAG != 2){ FXAS_FIFO_FULL_FLAG = 1; } } //Interrupt for FXOS8700S INT_1 void read_fxos_data(){ //Read data from FXOS8700C sensor if(FXOS_FIFO_FULL_FLAG != 2){ FXOS_FIFO_FULL_FLAG = 1; } } int main() { int initilised = 0; int index = 0; int test_index = 0; int fxos_data_flag_1 = 0; int fxas_data_flag_1 = 0; //Configure interrupts fxas_int1_21002.rise(&read_fxas_data);//FIFO -> Int_1 // fxas_int2_21002.rise(&read_fxas_data);//DRDY -> Int_2 fxos_int1_8700.rise(&read_fxos_data);//FIFO -> Int_1 // fxos_int2_8700.rise(&read_fxos_data);//DRDY -> Int_2 sensors.frequency(450000); pc.baud(115200); mkdir("/sd/sensor_data", 0777); FILE *fp = fopen("/sd/sensor_data/data.txt", "w"); if(fp == NULL) { error("Could not open file for write\n"); } fprintf(fp, "Gyro X,\tGyro Y,\tGyro Z,\t\tAcc X,\tACC Y,\tACC Z\n\r\n\r\n\r\n\r"); fclose(fp); //Initlilise the FXOS8700CQ Accelorometer & the FXAS21002C Gyroscope initilised = fxas_init() & fxos_init(); // pc.printf("Returned value: %d\n\n\r", initilised); while(1) { if (FXOS_FIFO_FULL_FLAG == 1){//0.976mg * (fxos_data >> 2) = total g force (8g scale) FXOS_FIFO_FULL_FLAG = 0; i2c_write(FXOS_ADDRESS_W, FXOS_STATUS, 0); sensors.read(FXOS_ADDRESS_R, fxos_data_1, 139, false);//Reads the status register on every pass 0x06 -> 0x00 fxos_data_flag_1 = 1; } if (FXAS_FIFO_FULL_FLAG == 1){//7.8125mdps * fxas_data = total degrees per second (250dps scale) FXAS_FIFO_FULL_FLAG = 0; i2c_write(FXAS_ADDRESS_W, FXAS_STATUS, 0); sensors.read(FXAS_ADDRESS_R, fxas_data_1, 139, false);//Reads the status register on the first if set to otherwise 0x06 -> 0x01 fxas_data_flag_1 = 1; } if ((fxos_data_flag_1 == 1) && (fxas_data_flag_1 == 1)){ //Store data on SD card if (test_index == 0){// <--------- Just till a proper file closing system can be implemented fp = fopen("/sd/sensor_data/data.txt", "a"); if(fp == NULL) { error("Could not open file for write\n"); } } for (index = 0; index < 139; index += 7){ //move data to SD card fprintf(fp, "%d\t%d\t%d\t\t", ((int16_t)((fxos_data_1[(index + 1)] << 8) | fxos_data_1[(index + 2)]) >> 2), ((int16_t)((fxos_data_1[(index + 3)] << 8) | fxos_data_1[(index + 4)]) >> 2), ((int16_t)((fxos_data_1[(index + 5)] << 8) | fxos_data_1[(index + 6)]) >> 2)); fprintf(fp, "%d\t%d\t%d\n\r\n\r", ((int16_t)((fxas_data_1[(index + 1)] << 8) | fxas_data_1[(index + 2)])), ((int16_t)((fxas_data_1[(index + 3)] << 8) | fxas_data_1[(index + 4)])), ((int16_t)((fxas_data_1[(index + 5)] << 8) | fxas_data_1[(index + 6)]))); } fxos_data_flag_1 = 0; fxas_data_flag_1 = 0; test_index++; // fprintf(fp, "\n\r\n\r\n\r\n\r\n\r\n\r"); if (test_index == 30){// <--------- Just till a proper file closing system can be implemented fclose(fp); test_index = 0;; } for (int i = 0; i < 139; i++){ fxos_data_1[i] = 0; fxas_data_1[i] = 0; } }
Original Attachment has been moved to: data.txt.zip
Solved! Go to Solution.
Hello Kas,
The numbers you are seeing appear to be random. It makes me think that the way you are reading the FIFO is not correct. You should use something like this:
I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 120, AccelData);
The auto-increment address of the OUT_Z_LSB register is actually 0x01 and not 0x00, that is why I am reading 120 bytes (20 X, Y and Z data samples = 20 x 3 x 2) and not 139.
Attached you can find my example code reproducing your settings and the following screenshots illustrate correct behavior.
ODR is set to 50 Hz, so the FIFO interrupt happens every 400 ms (20 ms x 20 samples):
Let me know whether or not this helps, or if you have any other questions.
Regards,
Tomas
PS: If my answer helps to solve your question, please mark it as "Correct". Thank you.
Hello Kas,
The numbers you are seeing appear to be random. It makes me think that the way you are reading the FIFO is not correct. You should use something like this:
I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 120, AccelData);
The auto-increment address of the OUT_Z_LSB register is actually 0x01 and not 0x00, that is why I am reading 120 bytes (20 X, Y and Z data samples = 20 x 3 x 2) and not 139.
Attached you can find my example code reproducing your settings and the following screenshots illustrate correct behavior.
ODR is set to 50 Hz, so the FIFO interrupt happens every 400 ms (20 ms x 20 samples):
Let me know whether or not this helps, or if you have any other questions.
Regards,
Tomas
PS: If my answer helps to solve your question, please mark it as "Correct". Thank you.
Hello Tomas,
Thank you for your response, if I am understanding your comment correctly there is a mistake in the FXOS8700CQ data sheet. On page 25 for OUT_Z_LSB it says auto increments to either 0x00 0r 0x33 depending on CTRL_REG2 [hyb_autoinc_mode].
If this is the case then this is a simple issue to resolve and as you said it will fix both issues at the same time. If you could please confirm the error in the data sheet that would be helpful.
Thankfully
Kas
It appears from my limited testing that in fact the DATASHEET is INCORRECT and it is as Tomas says that the auto increment for the FXOS is to 0x01 and NOT 0x00 as stated in the data sheet.
Freescale please fix the data sheet so as not to cause further confusion to others.
Thankfully
Kas