2015-08-18 01:24 PM
Dear Community,
I am trying to setup the LSM6DS3 Accelerometer/Gyrochip. The datasheet states the following startup procedure for this device:
1 Write CTRL9_XL = 38h // Acc X, Y, Z axes enabled
2 Write CTRL1_XL = 60h // Acc = 416Hz (High-Performance mode)
3 Write INT1_CTRL = 01h // Acc Data Ready interrupt on INT1
My interpretation of this procedure is the following code (which runs on aSTM32F302 µC):
//APB1 @36 MHz
//SPI3 setup
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
//IRQ Handler
char Rx_Idx = 0x00;
char Tx_Idx = 0x00;
void SPI3_IRQHandler() {
/* SPI in Master Tramitter mode--------------------------------------- */
if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_TXE) == SET)
{
SPI_SendData8(SPI3, Tx_Idx);
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, DISABLE);
}
// SPI in Master Receiver mode-----------------------------------
if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_RXNE) == SET)
{
Rx_Idx = SPI_ReceiveData8(SPI3);
}
// SPI Error interrupt---------------------------------------
if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_OVR) == SET) {
SPI_ReceiveData8(SPI3);
SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_OVR);
}
}
char SPI_transfer(char data) {
Tx_Idx = data;
//start the SPI interupt handler...
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE); //the send routine disables the interupt if all bytes have been sen
/* Waiting until TX FIFO is empty */
while (SPI_GetTransmissionFIFOStatus(SPI3) != SPI_TransmissionFIFOStatus_Empty)
{}
/* Wait busy flag */
while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY) == SET)
{}
/* Waiting until RX FIFO is empty */
while (SPI_GetReceptionFIFOStatus(SPI3) != SPI_ReceptionFIFOStatus_Empty)
{}
return Rx_Idx;
}
void main() {
//some periph intitialization
Delay1sec();
//Register CTRL9_XL
SPI_transfer(0x18);
//Data
SPI_transfer(0x38);
//Register CTRL1_XL
SPI_transfer(0x10);
//Data
SPI_transfer(0x60);
//Register INT1_CTRL
SPI_transfer(0x0D);
//Data
SPI_transfer(0x01);
while(1) {
// 3 2 1 0
//EV_BOOT TDA GDA XLDA
retn = 0;
while( !(retn & (1 << 0))) {
// Send_Message(retn);
retn = SPI_transfer(0x1E);
}
/*
3 Read OUTX_L_XL 28h
4 Read OUTX_H_XL 29h
5 Read OUTY_L_XL 2Ah
6 Read OUTY_H_XL 2Bh
7 Read OUTZ_L_XL 2CH
8 Read OUTZ_H_XL 2DH
*/
tempX = 0;
tempX = SPI_transfer(0x28);
tempX = tempX + 256* SPI_transfer(0x29);
tempY = 0;
tempY = SPI_transfer(0x2A);
tempY = tempY + 256* SPI_transfer(0x2B);
tempZ = 0;
tempZ = SPI_transfer(0x2C);
tempZ = tempZ + 256* SPI_transfer(0x2D);
Send_X2bytes( tempX); //sends the values to the PC
Send_Y2bytes( tempY);
Send_Z2bytes( tempZ);
Delay100ms();
};
This code pulls out some data from the registers but the values are confusing and have probably nothing to do with acceleration (although the values change if the chip is turned around). I doubt there is a timing issue and I would be glad if someone could give a hint.
2015-09-01 10:26 AM
Dear community,
obviously the code, which posted in my previous post, contains a few mistakes. However after correcting those mistakes I also found that using a wire bonder to custom-patch the contact-pats of the flipped chip is not a good idea, since the wire bonding beneath the pads is very flimsy. For those who are still searching for copy and paste code fragments I’ll give some fragments in the following code section (I was inspired by the great sparkfun homepage and I gas that mysterious “1111 1111�? errors as stated thereare caused if two 8bit read/write attemps are used instead of a single 16bit attemp)
Lprint(''Power ON
'');
Delay(); //min 200 ms
// BOOT
dataToRead = 0;
ReadData16LSM6DS3( 0x1E, &dataToRead);
LSend_value(&dataToRead); // this routine sends dataToRead to a Display
Lprint(''BOOT \0'');
//enable Accelerometer
//CTRL_9 : 0x18
dataToWrite = 0;
dataToWrite = dataToWrite | (1 <<3);
dataToWrite = dataToWrite | (1 <<4);
dataToWrite = dataToWrite | (1 <<5);
WriteData16LSM6DS3(0x18, dataToWrite);
dataToRead = 0;
ReadData16LSM6DS3(0x18, &dataToRead);
LSend_value(&dataToRead);
Lprint(''CTRL_9 \0'');
//enable Gyros
//CTRL_10 : 0x19
dataToWrite = 0;
dataToWrite = dataToWrite | (1 <<3);
dataToWrite = dataToWrite | (1 <<4);
dataToWrite = dataToWrite | (1 <<5);
WriteData16LSM6DS3(0x19, dataToWrite);
dataToRead = 0;
ReadData16LSM6DS3(0x19, &dataToRead);
LSend_value(&dataToRead);
Lprint(''CTRL_10 \0'');
// set sampling rate for the Acceleromter
//CTRL_1 : 0x10
dataToWrite = 0;
dataToWrite = dataToWrite | (1 <<6);
//104 Hz (normal mode)
WriteData16LSM6DS3(0x10, dataToWrite);
dataToRead = 0;
ReadData16LSM6DS3( 0x10, &dataToRead);
LSend_value(&dataToRead);
Lprint(''CTRL_1 \0'');
// set sampling rate for the Gyroscopes
//CTRL_2 : 0x11
dataToWrite = 0;
dataToWrite = dataToWrite | (1 <<6);
//104 Hz (normal mode)
WriteData16LSM6DS3(0x11, dataToWrite);
dataToRead = 0;
ReadData16LSM6DS3( 0x11, &dataToRead);
LSend_value(&dataToRead);
Lprint(''CTRL_2 \0'');
//WHO I AM - needs to be corectly read because otherwise there is e.g. a //contact (pad) issue....
dataToRead = 0;
ReadData16LSM6DS3( 0x0F, &dataToRead);
LSend_value(&dataToRead);
Lprint(''WHO I AM \0'');
while(1) {
//WaitXLDA();
//WaitGDA();
tempXL = 0;
tempYL = 0;
tempZL = 0;
tempXH = 0;
tempYH = 0;
tempZH = 0;
tempGXL = 0;
tempGYL = 0;
tempGZL = 0;
tempGXH = 0;
tempGYH = 0;
tempGZH = 0;
// 3 2 1 0
//EV_BOOT TDA GDA XLDA
// XLDA
dataToRead = 0;
while(!(dataToRead & (1 << 0))) {
Send_Message(dataToRead & 0xFF);
dataToRead = 0;
ReadData16LSM6DS3( 0x1E, &dataToRead);
}
ReadData16LSM6DS3(0x28,&tempXL);
ReadData16LSM6DS3(0x2A,&tempYL);
ReadData16LSM6DS3(0x2C,&tempZL);
ReadData16LSM6DS3(0x29,&tempXH);
ReadData16LSM6DS3(0x2B,&tempYH);
ReadData16LSM6DS3(0x2D,&tempZH);
tempXH = tempXH * 256;
tempXH = tempXH | tempXL;
tempYH = tempYH * 256;
tempYH = tempYH | tempYL;
tempZH = tempZH * 256;
tempZH = tempZH | tempZL;
// 3 2 1 0
//EV_BOOT TDA GDA XLDA
// GDA
dataToRead = 0;
while(!(dataToRead & (1 << 1))) {
Send_Message(dataToRead & 0xFF);
dataToRead = 0;
ReadData16LSM6DS3( 0x1E, &dataToRead);
}
ReadData16LSM6DS3(0x22,&tempGXL);
ReadData16LSM6DS3(0x24,&tempGYL);
ReadData16LSM6DS3(0x26,&tempGZL);
ReadData16LSM6DS3(0x23,&tempGXH);
ReadData16LSM6DS3(0x25,&tempGYH);
ReadData16LSM6DS3(0x27,&tempGZH);
tempGXH = tempGXH * 256;
tempGXH = tempGXH | tempGXL;
tempGYH = tempGYH * 256;
tempGYH = tempGYH | tempGYL;
tempGZH = tempGZH * 256;
tempGZH = tempGZH | tempGZL;
// 3 2 1 0
//EV_BOOT TDA GDA XLDA
// TDA
dataToRead = 0;
while(!(dataToRead & (1 << 2))) {
Send_Message(dataToRead & 0xFF);
dataToRead = 0;
ReadData16LSM6DS3( 0x1E, &dataToRead);
}
ReadData16LSM6DS3(0x20,&TempL);
ReadData16LSM6DS3(0x21,&TempH);
TempH = TempH * 256;
TempH = TempH | TempL;
//here are some routines which send the read values to a display
Send_X2bytes(tempXH);
Send_Y2bytes(tempYH);
Send_Z2bytes(tempZH);
Send_GX2bytes(tempGXH);
Send_GY2bytes(tempGYH);
Send_GZ2bytes(tempGZH);
Send_Temp2bytes(TempH);
Send_Message(dataToRead & 0xFF);
DelaySPI(); //short delay - probably not necessary
}