PSoC 5LP + Adafruit LSM303 magnetometer (compass) module + Frozen data

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
keko_4647076
Level 1
Level 1
5 sign-ins First reply posted First question asked

Hi everyone,

I tried replicating "https://jimmyutterstrom.com/blog/2015/07/12/psoc-tutorial-adafruit-lsm303-magnetometer-compass-modul... onto PSoC5LP.

I got readings from the compass module, but it is always the same value and does not change while the PSoC plugged in.

When i remove and plug in the PSoC again, the heading value changes to what is expected but it does not update when i move the compass along. I feel like there's something wrong with the I2C communication, that the value is not being updated. Any help / guidance on how to solve this issue is greatly appreciated.

 

#include <project.h>
#include <math.h>
#include <stdio.h>

#define LSM303_ADDRESS_ACCEL          (0x32 >> 1)
#define LSM303_ADDRESS_MAG            (0x3C >> 1)

#define LSM303_REGISTER_ACCEL_CTRL_REG1_A   0x20
#define LSM303_REGISTER_MAG_MR_REG_M        0x02
#define LSM303_REGISTER_MAG_OUT_X_H_M       0x03
#define LSM303_REGISTER_ACCEL_OUT_X_L_A     0x28

typedef struct Vector3{
    int x;
    int y;
    int z;
} Vector3;

void LSM303_Init() {
    
    //Start the I2C component.
    LSM303_I2C_Start();
    
    /*------------ Accelerometer ------------*/
    
    //Send start command for write mode.
    LSM303_I2C_MasterSendStart(LSM303_ADDRESS_ACCEL, LSM303_I2C_WRITE_XFER_MODE);

    //Specify which register we want to write to.
    //This register is written to for enabling x, y and z
    //output as well as setting datarate and powermode.
    LSM303_I2C_MasterWriteByte(LSM303_REGISTER_ACCEL_CTRL_REG1_A);
    
    //Set the required bits in the register.
    LSM303_I2C_MasterWriteByte(0x27u);
    
    /*------------ Magnetometer ------------*/
   
    //This register is written to for setting data output rates
    //and controlling measurement flow.
    LSM303_I2C_MasterWriteByte(LSM303_REGISTER_MAG_MR_REG_M);
    LSM303_I2C_MasterWriteByte(0x00u);
        
    LSM303_I2C_MasterSendStop();

}

void LSM303_ReadMag(Vector3 *magData) {
    uint8 data[6];
    

    //Prepare the module for magnetometer output.
    LSM303_I2C_MasterSendStart(LSM303_ADDRESS_MAG, LSM303_I2C_WRITE_XFER_MODE);

    LSM303_I2C_MasterWriteByte(LSM303_REGISTER_MAG_OUT_X_H_M);    
        
    LSM303_I2C_MasterSendStop();
    //--
    
    //Start the communication in read mode.
    LSM303_I2C_MasterSendStart(LSM303_ADDRESS_MAG, LSM303_I2C_READ_XFER_MODE);   
    
    //Read databytes.
    data[0] = LSM303_I2C_MasterReadByte(LSM303_I2C_ACK_DATA);
    data[1] = LSM303_I2C_MasterReadByte(LSM303_I2C_ACK_DATA);
    data[2] = LSM303_I2C_MasterReadByte(LSM303_I2C_ACK_DATA);
    data[3] = LSM303_I2C_MasterReadByte(LSM303_I2C_ACK_DATA);
    data[4] = LSM303_I2C_MasterReadByte(LSM303_I2C_ACK_DATA);
    
    //Notice that we are here using "NAK_DATA". It's to tell the 
    //LSM303 that we're done and don't want to read anymore data.
    data[5] = LSM303_I2C_MasterReadByte(LSM303_I2C_NAK_DATA);
    
    //Put together the different data bytes to form complete
    //integers for storing the output values.
    magData->x = (int16_t)(data[1] | (data[0] << 8));
    magData->y = (int16_t)(data[5] | (data[4] << 8));   
    magData->z = (int16_t)(data[3] | (data[2] << 8));
 
    LSM303_I2C_MasterSendStop();

}

int main()
{  
    Vector3 magData;
    char output[4]; //String for storing uart output.
    
    PC_UART_Start();      
    LSM303_Init();   

    for(;;)
    {
        LSM303_ReadMag(&magData);
        
        //Calculate heading using arctan on the Y and X vectors.
        //And convert from radians to degrees.
        float h = (atan2(magData.y, magData.x) * 180.0) / 3.14159265359;
        
        //Map the value to comply with the standard system where the heading
        //is specified as an angle between 0 - 360 degrees.
        if(h < 0) {
            h = 360 + h;   
        }  
        
        //Output the heading through our UART component.
        sprintf(output, "%i\r\n", (int)(h+0.5));
        PC_UART_PutString(output);
        
        //Update heading at 1 Hz
        CyDelay(1000);

    }    
}

/* [] END OF FILE */
0 Likes
1 Reply