¿Por qué puedo leer los datos del acelerómetro y del giroscopio en el LSM9DS1 con SPI, pero no los datos del magnetómetro en el mismo dispositivo?

1

Actualmente estoy trabajando en un dispositivo que utiliza el LSM9DS1, un sensor de movimiento de 9 ejes de ST Microelectronics. Estoy usando un microcontrolador PIC24FJ128GB202 de Microchip y me estoy comunicando con el sensor usando SPI. El LSM9DS1 tiene un acelerómetro y un giroscopio que comparten registros de configuración y pines SDO / SDI, así como un magnetómetro que tiene sus propios registros de configuración y pines SDO / SDI. El SCK se comparte entre todos y los pines CS se dividen entre el magnetómetro y el acelerómetro / giroscopio (por lo que es como si hubiera dos dispositivos separados en un paquete, uno para el magnetómetro y el otro para el acelerómetro / giroscopio). Para probar el dispositivo que estoy usando la placa de evaluación STEVAL MKI159-V1 compatible con la placa de prueba, que ha combinado los dos pines SDO y los dos pines SDI.

El problema que tengo es que soy perfectamente capaz de recibir los datos del acelerómetro / giroscopio, pero usando el mismo proceso, cuando trato de leer los datos del magnetómetro, todo lo que obtengo es todo. 1 para algunos bytes y todos los 0 para los demás (los datos se separan en byte alto y byte bajo para cada uno de los tres ejes). Supuse que tal vez los datos no estén listos, por lo que podría haber sido un problema, pero el dispositivo La ID que se supone que devuelve un valor constante devuelve 0, cada vez que lo leo.

Ya lo he intentado:

  • usando otro sensor del mismo modelo (para probar si el primero se rompió)
  • cambiando los cables para verificar conexiones defectuosas
  • reducir / aumentar la velocidad de transferencia de datos
  • reduciendo la velocidad solo para escribir en los registros (lo que ayudó con un problema con el giro)

¿Alguien ha emitido antes este dispositivo o la placa de evaluación o hay algo que no estoy haciendo bien? No puedo entender por qué una parte del dispositivo funcionaría y la otra no usaría el mismo método exacto, y dudo mucho que el problema sea que ambos están rotos de la misma manera (esa sería la peor suerte de todas. .) No tengo acceso a un osciloscopio, pero he considerado la posibilidad de adjuntar algunos registros de desplazamiento con LED para ver qué se está transfiriendo. Si alguien tiene algún comentario sobre este problema o algún método que pueda usar para resolverlo, le estaré muy agradecido.

Este es el código que se relaciona con la comunicación con el sensor que escribí:

    #define LSM_CS LATBbits.LATB15 
    #define MAG_0_CS LATBbits.LATB14

    #define GET_LSM_CS PORTBbits.RB15         // I added these thinking that                 possibly it was trying to 
    #define GET_MAG_0_CS PORTBbits.RB14   // start reading before the CS was         considered ‘0’

    volatile unsigned char dataOne[64];
    volatile int beginReading = 0;
    volatile int devicesConfigured = 0;
    volatile int i = 0;
    volatile int dataReady;
    volatile int readNew = 1;

/********************* PIN INITIALIZE *******************/
void pinInit(){
TRISA = 0x0000;
TRISB = 0x0002;     //RB1 (pin 5) is input
ANSA = 0x0000;
ANSB = 0x0000;

OSCCON = 0x46;
OSCCON = 0x57;
OSCCONbits.IOLOCK = 0;  //Unlocks PPS for writing

//SET PPS
//Inputs
RPINR20bits.SDI1R = 1;  //Assigned SDI to pin 'RP1' (pin 5) B1

//Outputs
RPOR1bits.RP2R = 7;     //SDO1 is assigned to pin RP2 (pin 6) B2
RPOR1bits.RP3R = 8;     //SCK1OUT is assigned to pin RP3 (pin 7) B3

OSCCON = 0x46;
OSCCON = 0x57;
OSCCONbits.IOLOCK = 1; //Stops write;
}

    /**************************** SPI INITIALIZE ******************************/
    void SPIInit(){
    IFS0bits.SPI1IF = 0;
    IFS0bits.SPI1TXIF = 0;
    IFS3bits.SPI1RXIF = 0;

IEC0bits.SPI1IE = 0;        // SPI1 General Interrupt Disabled
IEC0bits.SPI1TXIE = 0;      // Transmit complete interrupt Disabled
IEC3bits.SPI1RXIE = 0;      // Receive complete interrupt Disabled


/*Clear ON bit*/
SPI1CON1Lbits.SPIEN = 0;

/*Clear receiver buffer*/
int clr = SPI1BUFL;

/*Clear enhanced mode bit*/
SPI1CON1Lbits.ENHBUF = 0;

/*Clear overflow bit*/
SPI1STATLbits.SPIROV = 0;

/*Set master enable*/
SPI1CON1Lbits.MSTEN = 1;

/*Other CON settings*/
SPI1BRGL = 0xFFFF;                //FPB/(2*(SPI1BRGL +1))   7999
SPI1CON1Lbits.MODE = 0x0;       //8-bit data
SPI1CON1Lbits.DISSDO = 0;       //SDO1 controlled by module
SPI1CON1Lbits.DISSDI = 0;       //SDI1 controlled by module
SPI1CON1Lbits.DISSCK = 0;       //SCK1 is controlled by module
SPI1CON1Lbits.CKP = 1;          //Clock idle is high, active low  -----_-_-_-_-_-_-_-----
SPI1CON1Lbits.CKE = 0;          //Transmit from idle to active   
SPI1CON1Lbits.SMP = 0;          //Input sampled at end of data output time

SPI1CON1Hbits.AUDEN = 0;        //Audio protocol is disabled
SPI1CON1Hbits.IGNROV = 1;       //Ignore overflow error
SPI1CON1Hbits.IGNTUR = 1;       //Ignore transmit underrun error
SPI1CON1Hbits.MSSEN = 0;        //Slave select is controlled by I/O
SPI1CON2Lbits.WLENGTH = 0x00;   //Use SPI1CON1Lbits.MODE

//SPI1IMSKLbits.BUSYEN = 1;
//SPI1IMSKLbits.SPIRBFEN = 1;

/*Set on bit*/
SPI1CON1Lbits.SPIEN = 1;

}

/*************************** MAIN *************************/
int main(void)
{   
LSM_CS = 1;
MAG_0_CS = 1;


OSCCON = 0x0000;
while(delay < 1024){delay++;}   // Wait till the oscillator stabilizes

pinInit();

SPIInit();

devicesConfigured = 0;


TRISAbits.TRISA2 = 1;

while(1)
{
        if(devicesConfigured != 1)
        {
            configureDevices();

            SPI1BRGL = 499; // Speed slower prior to ensure correct values written
                            // Clock speed increased here for SPI reading
        }

        buttonRead();  // Used to toggle data reading

        if(beginReading == 1)
        {
            LSM_CS = 0;
            while(GET_LSM_CS == 1);
            dataReady = SPIRead(0x27);
            LSM_CS = 1;
            while(GET_LSM_CS == 0);

            if((dataReady & 0x3) > 0)
            {
                read_Data_XL2();
            }

            MAG_0_CS = 0;
            while(GET_MAG_0_CS == 1);
            dataReady = SPIRead(0x27);
            MAG_0_CS = 1;
            while(GET_MAG_0_CS == 0);

            if((dataReady & 0x0F) > 0)
            {
                read_Data_M2();
            }

            LATBbits.LATB5 = 1;   
            }
        }
        else
        {
            dimmingLED();
        }

}
}

/********************* INITIAL CONFIGURATION ********************/
void configureDevices()
{    
configureLSM();

configureMagnetometer0(); 

devicesConfigured = 1;
}

void SPIWrite(int address, int data){

int clr;

/*Enable SPI*/

/*Write address + write (0) to SPI1BUF*/
SPI1BUFL = address;

/*Wait for the transfer buffer to empty*/
while(SPI1STATLbits.SPITBF);

/*Wait for the receive buffer to fill*/
while(SPI1STATLbits.SPIRBE);

/*Read value in buffer to clear it*/
clr = SPI1BUFL;

/*Write data to SPI1BUF*/
SPI1BUFL = data;

/*Wait for the transfer buffer to empty*/
while(SPI1STATLbits.SPITBF);

/*Wait for the receive buffer to fill*/
while(SPI1STATLbits.SPIRBE);

/*Read value in buffer to clear it*/
clr = SPI1BUFL;

/*Disable SPI*/    

}

void configureLSM()
{
int checkDevice = 0;

/* CTRL_REG1_G */         
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x10, 0xC8);  //1100 1000 0xC8
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG2_G */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x11, 0x00);
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG3_H */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x12, 0x00); //0000 0000
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG4 */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x1E, 0x38);  //0011 1000
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG5_XL */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x1F, 0x38);  //0011 1000
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG6_XL */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x20, 0xD0);  //1101 0000 0xD0
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG7_XL */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x21, 0x00);  //0000 0000
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG8_XL */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x22, 0x00);
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG9 */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x23, 0x04); //0000 0100
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* CTRL_REG10 */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x24, 0x00);
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* ORIENT_CFG_G */
LSM_CS = 0;
while(GET_LSM_CS == 1); 
SPIWrite(0x13, 0x00);
LSM_CS = 1;
while(GET_LSM_CS == 0);

/* FIFO CTRL */
LSM_CS = 0;
while(GET_LSM_CS == 1);
SPIWrite(0x2E, 0x00);
LSM_CS = 1;
while(GET_LSM_CS == 0);

/*Return 41h*/
LSM_CS = 0;
while(GET_LSM_CS == 1); 
checkDevice = SPIRead(0x0F); //WHO_AM_I
LSM_CS = 1;
while(GET_LSM_CS == 0);

dataOne[21] = checkDevice;
}

void configureMagnetometer0()
{ 
int checkDevice = 0;

/* CTRL_REG3_M */
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1); 
SPIWrite(0x22, 0x84);  //1000 0100 
MAG_0_CS = 1;

/* CTRL_REG1_M */ 
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1);
SPIWrite(0x20, 0xDC);  //1101 1100
MAG_0_CS = 1;

/* CTRL_REG2_M */
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1);
SPIWrite(0x21, 0x00);  //0000 0000
MAG_0_CS = 1;

/* CTRL_REG4_M */ //0000 00 0 0
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1);
SPIWrite(0x23, 0x08); //0000 1000 
MAG_0_CS = 1;

/* CTRL_REG5_M */ 
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1);
SPIWrite(0x24, 0x40); 
MAG_0_CS = 1;

/* WHO_AM_I */
MAG_0_CS = 0;
while(GET_MAG_0_CS == 1);
checkDevice = SPIRead(0x0F); 
MAG_0_CS = 1;

dataOne[22] = checkDevice;
}

/************************** READING DATA *************************/

unsigned char SPIReadSingle(unsigned char address){    

address = address | 0x80;

/*Write address + read (1) to SPI1BUF*/
SPI1BUFL = address;
while(!SPI1STATLbits.SPITBE);   // Wait till data has shifted to shift register
while(!SPI1STATLbits.SPIRBF);   // Wait until receive buffer has new data (not in SR technically)
while(SPI1STATLbits.SPIBUSY);   // Wait for SPI to be completely ready 
// USE DELAY HERE IF NOT WORKING (note to myself)
address = SPI1BUFL;             // Read data to clear receive buffer
SPI1BUFL = 0x00;                // Shift data out of sensor

while(!SPI1STATLbits.SPITBE);   // Wait till data has shifted to SR
while(!SPI1STATLbits.SPIRBF);   // Wait until receive buffer has new data not in SR technically
while(SPI1STATLbits.SPIBUSY);   // Wait for SPI to be completely ready 
// USE DELAY HERE IF NOT WORKING
return SPI1BUFL;                // Return new data to main
}


void read_Data_XL2()
{         

/* LSM9DS1*/    
LSM_CS = 0;
dataOne[0] = SPIReadSingle(0x0F); //Read Who_Am-I, 
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[1] = SPIReadSingle(0x29); //Read Acc0 x-High
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[2] = SPIReadSingle(0x2B); //Read Acc0 y-High
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[3] = SPIReadSingle(0x2D); //Read Acc0 z-High
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[4] = SPIReadSingle(0x19); //Read Gyro0 x-High
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[5] = SPIReadSingle(0x1B); //Read Gyro0 y-High
LSM_CS = 1;
while(GET_LSM_CS == 0);
LSM_CS = 0;
dataOne[6] = SPIReadSingle(0x1D); //Read Gyro0 z-High
LSM_CS = 1;
}

void read_Data_M2()
{        
MAG_0_CS = 0;
dataOne[7] = SPIReadSingle(0x28); //Read Mag0 x-Low
MAG_0_CS = 1;
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[8] = SPIReadSingle(0x29); //Read Mag0 x-High
MAG_0_CS = 1;
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[9] = SPIReadSingle(0x2A); //Read Mag0 y-Low
MAG_0_CS = 1;
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[10] = SPIReadSingle(0x2B); //Read Mag0 y-High
MAG_0_CS = 1;
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[11] = SPIReadSingle(0x2C); //Read Mag0 z-Low
MAG_0_CS = 1;
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[12] = SPIReadSingle(0x2D); //Read Mag0 z-High
MAG_0_CS = 1; 
while(GET_MAG_0_CS == 0);
MAG_0_CS = 0;
dataOne[13] = SPIReadSingle(0x0F); //Read Mag0 WHO_AM_I
MAG_0_CS = 1; 

}
    
pregunta Jules C

1 respuesta

0

Lo he descubierto. La hoja de datos dice que ingrese '0' en la ubicación 2 (etiquetada como "SIM") del Registro de Control 3 del magnetómetro, pero ingresé '1' solo por desesperación y funciona. Tal vez la hoja de datos sea incorrecta, pero si alguien tiene este dispositivo y se comunica con SPI y obtiene el mismo resultado, entonces ese sería un buen indicador de que ese es el problema. También dejé I2C habilitado aunque no lo esté usando y todavía funciona bien.

    
respondido por el Jules C

Lea otras preguntas en las etiquetas