So I recently bought an IMU from Pololu (https://www.pololu.com/product/2738). I've used their old versions of IMUs in the past, but now that I got this new one, I am unable to connect to it via I2C. I am not getting anything at all from the accelerometer. By reading the datasheet, it's only a matter of setting a few registers. When I do that, however, nothing happens. Here's the datasheet of the LSM6DSD33 https://www.pololu.com/file/down...
here's my code:
#define F_CPU 14745600 #define IMU_ADDR 0b1101011 // Gyrosensor + Accelerometer address (1101011) #define STATUS_REG 0x20 // Accelerometer #define CTRL9_XL 0x18 // To enable axes #define CTRL1_XL 0x60 // High-performance mode register #define INT1_CTRL 0x01 // Acc Data ready interrupt on INT1 #define OUTX_L_XL 0x28 // Acc out X,l #define OUTX_H_XL 0x29 // Acc out, X,h #include <stdio.h> #include <math.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <avr/eeprom.h> #include <inttypes.h> #include <util/delay.h> // C libraries extern "C" { #include "libs/uart.h" #include "libs/delay.h" } // setups TWI (Two Wire Interface A.K.A I2C) void TWISetup() { // Set up TWI module to 368,640 Hz // SCLfreq = Fclock/(16+2*TWBR*(prescaler)) // Set up TWI but rate to 3 TWBR = 3; // Prescaler to 4 TWSR |= (1 << TWPS0); // Enable TWI TWCR |= (1 << TWEN); } // Start signal function void TWIStart() { // From datasheet page 226 TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // Send start condition while (!(TWCR & (1 << TWINT))); // Wait for TWINT Flag set. This indicates that the START condition has been transmitted } void TWIStop() { TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); // Transmit STOP condition } void TWIWrite(uint8_t data) { //Load SLA_W into TWDR Register. Clear TWINT bit in //TWCR to start transmission of address TWDR = data; TWCR = (1 << TWINT) | (1 << TWEN); //Wait for TWINT Flag set. This indicates that the SLA+W has //been transmitted, and ACK/NACK has been received. while (!(TWCR & (1 << TWINT))); } // Read with ACK (Acknowledge bit) uint8_t TWIReadACK() { //TWI Interrupt Flag, TWI Enable Bit, TWI Enable Acknowledge Bit TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); //Wait for TWINT Flag set. while (!(TWCR & (1 << TWINT))); return TWDR; } //read byte with NACK uint8_t TWIReadNACK() { TWCR = (1 << TWINT) | (1 << TWEN); //Wait for TWINT Flag set. while (!(TWCR & (1 << TWINT))); return TWDR; } // Check status uint8_t TWIReadStatus() { uint8_t status; status = TWSR & 0xF8; return status; } // Read byte int16_t ReadByte(uint8_t DEVADDR, uint8_t regAddress) { //send start TWIStart(); // ST TWIWrite((DEVADDR << 1) | 0); // SAD+W (Slave address) + Write bit TWIWrite(regAddress); // Register adddress (SUB) //send repeated start TWIStart(); // SR TWIWrite((DEVADDR << 1) | 1); // SAD + R int16_t data = TWIReadNACK(); // NMAK TWIStop(); // SP return data; } // Writes one byte void writeByte(uint8_t DEVADDR, uint8_t regAddress, uint8_t data) { TWIStart(); // Starts TWIWrite((DEVADDR << 1) | 0); // SAD+W (Slave address) + Write bit TWIWrite(regAddress); // Register adddress (SUB) TWIWrite(data); // Data to write TWIStop(); // Stops I2C } int main(void) { // init serial port uart_init(); // Serial port FILE uart_stream; uart_stream.put = uart_putchar; uart_stream.get = uart_getchar; uart_stream.flags = _FDEV_SETUP_RW; uart_read(); TWISetup(); writeByte(IMU_ADDR,CTRL9_XL, 0b00111000); // X Y Z access enabled writeByte(IMU_ADDR,CTRL1_XL, 0b01100000); // Acc = 416Hz (High-Performance mode) : ODR_XL [3:0] 0110 writeByte(IMU_ADDR,INT1_CTRL, 0b00000001); // Acc Data Ready interrupt on INT1 uint8_t out_x_a; // Accelerometer output uint8_t STATUS; uint8_t MASK = 0b00000001; printf_P(PSTR("Reading Acc:\r\n")); // "#" Means end of line, "*" is where line begins while (1) { STATUS = ReadByte(IMU_ADDR, STATUS_REG); uint8_t STATUS_LSB = STATUS & MASK; // Get the last bit status if (STATUS_LSB) // Read LSB { printf_P(PSTR("Output Acc")); // "#" Means end of line, "*" is where line begins out_x_a = ReadByte(IMU_ADDR, OUTX_L_XL); printf_P(PSTR(": %d\r\n"), out_x_a); // "#" Means end of line, "*" is where line begins } else { } } return 0; }
According to the dasheet settng the registers is the only thing needed to power on accelerometer
Then it says something about using the STATUS register to expect new data, which I am using too.
So basically I am doing everything I should be doing according to the datasheet... The i2c code I am using should work well on the atmega328p, it's the one I've been using for a while for another IMU... Anyone have worked with the LSM6DSD33? Thanks!