Hi guys,
I recently switched to ESP32 and I am trying to connect an IMU with I2C.
I’ve read several issues that might be related, but I couldn’t figure it out.
I am running on a ESP32 S3 DevKit C Board.
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
There are the packages used
pio pkg list
Resolving esp32dev dependencies...
Platform espressif32 @ 6.5.0 (required: espressif32)
├── framework-arduinoespressif32 @ 3.20014.231204 (required: platformio/framework-arduinoespressif32 @ ~3.20014.0)
├── tool-cmake @ 3.16.4 (required: platformio/tool-cmake @ ~3.16.0)
├── tool-esptoolpy @ 1.40501.0 (required: platformio/tool-esptoolpy @ ~1.40501.0)
├── tool-mkfatfs @ 2.0.1 (required: platformio/tool-mkfatfs @ ~2.0.0)
├── tool-mklittlefs @ 1.203.210628 (required: platformio/tool-mklittlefs @ ~1.203.0)
├── tool-mkspiffs @ 2.230.0 (required: platformio/tool-mkspiffs @ ~2.230.0)
├── tool-ninja @ 1.9.0 (required: platformio/tool-ninja @ ^1.7.0)
├── tool-openocd-esp32 @ 2.1100.20220706 (required: platformio/tool-openocd-esp32 @ ~2.1100.0)
├── toolchain-esp32ulp @ 1.23500.220830 (required: platformio/toolchain-esp32ulp @ ~1.23500.0)
├── toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 (required: espressif/toolchain-riscv32-esp @ 8.4.0+2021r2-patch5)
└── toolchain-xtensa-esp32s3 @ 8.4.0+2021r2-patch5 (required: espressif/toolchain-xtensa-esp32s3 @ 8.4.0+2021r2-patch5)
Libraries
├── FastLED @ 3.6.0 (required: fastled/FastLED @ ^3.6.0)
├── Madgwick @ 1.2.0 (required: arduino-libraries/Madgwick @ ^1.2.0)
├── SCL3300 @ 3.3.1 (required: davidarmstrong/SCL3300 @ ^3.3.1)
└── TFT_eSPI @ 2.5.43 (required: bodmer/TFT_eSPI @ ^2.5.43)
and I am trying to connect LSM6DS3 IMU. I started with the Arduino library, but I moved that code to a custom class for testing.
I am initialising i2c with the following code:
_wire->begin(static_cast<int>(SDA), static_cast<int>(SCL));
if (!(readRegister(LSM6DS3_WHO_AM_I_REG) == 0x6C || readRegister(LSM6DS3_WHO_AM_I_REG) == 0x69))
{
end();
return 0;
}
This is the very same code as used in the original lib.
I am getting this error message, and I cannot understand why this is happening.
[ 803][E][Wire.cpp:526] write(): NULL TX buffer pointer
[ 804][E][Wire.cpp:448] endTransmission(): NULL TX buffer pointer
This seems to be strange, as the allocateWireBuffer
method should output an error message similar to this, if it was not able to allocate memory log_e("Can't allocate memory for I2C_%d rxBuffer", num);
Any ideas?
And the full code of that class is?
Sorry, here it is:
#include "angle.h"
uint8_t Angle::begin()
{
filter.begin(sensorRate);
_wire = &Wire; // need the pointer to make it compatible with the original code
_wire->begin(static_cast<int>(SDA), static_cast<int>(SCL));
if (!(readRegister(LSM6DS3_WHO_AM_I_REG) == 0x6C || readRegister(LSM6DS3_WHO_AM_I_REG) == 0x69))
{
end();
return 0;
}
// set the gyroscope control register to work at 104 Hz, 2000 dps and in bypass mode
writeRegister(LSM6DS3_CTRL2_G, 0x4C);
// Set the Accelerometer control register to work at 104 Hz, 4 g,and in bypass mode and enable ODR/4
// low pass filter (check figure9 of LSM6DS3's datasheet)
writeRegister(LSM6DS3_CTRL1_XL, 0x4A);
// set gyroscope power mode to high performance and bandwidth to 16 MHz
writeRegister(LSM6DS3_CTRL7_G, 0x00);
// Set the ODR config register to ODR/4
writeRegister(LSM6DS3_CTRL8_XL, 0x09);
return 1;
}
uint8_t Angle::lsmAngle(double *angle)
{
float xAcc, yAcc, zAcc;
float xGyro, yGyro, zGyro;
float roll, pitch, heading;
if (accelerationAvailable() && gyroscopeAvailable())
{
readAcceleration(xAcc, yAcc, zAcc);
readGyroscope(xGyro, yGyro, zGyro);
filter.updateIMU(xGyro, yGyro, zGyro, xAcc, yAcc, zAcc);
pitch = filter.getPitch();
float pitchFiltered = 0.1 * pitch + 0.9 * pitchFilteredOld; // low pass filter
pitchFilteredOld = pitchFiltered;
*angle = pitchFiltered;
return true;
}
return false;
}
uint8_t Angle::readRegisters(uint8_t address, uint8_t *data, size_t length)
{
_wire->beginTransmission(_slaveAddress);
_wire->write(address);
if (_wire->endTransmission(false) != 0)
{
return -1;
}
if (_wire->requestFrom(_slaveAddress, length) != length)
{
return 0;
}
for (size_t i = 0; i < length; i++)
{
*data++ = _wire->read();
}
return 1;
}
int Angle::readRegister(uint8_t address)
{
uint8_t value;
if (readRegisters(address, &value, sizeof(value)) != 1)
{
return -1;
}
return value;
}
int Angle::gyroscopeAvailable()
{
if (readRegister(LSM6DS3_STATUS_REG) & 0x02)
{
return 1;
}
return 0;
}
void Angle::end()
{
writeRegister(LSM6DS3_CTRL2_G, 0x00);
writeRegister(LSM6DS3_CTRL1_XL, 0x00);
_wire->end();
}
int Angle::readAcceleration(float &x, float &y, float &z)
{
int16_t data[3];
if (!readRegisters(LSM6DS3_OUTX_L_XL, (uint8_t *)data, sizeof(data)))
{
x = NAN;
y = NAN;
z = NAN;
return 0;
}
x = data[0] * 4.0 / 32768.0;
y = data[1] * 4.0 / 32768.0;
z = data[2] * 4.0 / 32768.0;
return 1;
}
int Angle::accelerationAvailable()
{
if (readRegister(LSM6DS3_STATUS_REG) & 0x01)
{
return 1;
}
return 0;
}
int Angle::readGyroscope(float &x, float &y, float &z)
{
int16_t data[3];
if (!readRegisters(LSM6DS3_OUTX_L_G, (uint8_t *)data, sizeof(data)))
{
x = NAN;
y = NAN;
z = NAN;
return 0;
}
x = data[0] * 2000.0 / 32768.0;
y = data[1] * 2000.0 / 32768.0;
z = data[2] * 2000.0 / 32768.0;
return 1;
}
int Angle::writeRegister(uint8_t address, uint8_t value)
{
_wire->beginTransmission(_slaveAddress);
_wire->write(address);
_wire->write(value);
if (_wire->endTransmission() != 0)
return 0;
return 1;
}
I am just calling the begin
method, and I see the shown error.
That’s why I didn’t post the whole class …
Where is the _slaveAddress
member set? Not in the .cpp
code.
True, sorry, again.
It’s defined in the angle.h
file
#ifndef ANGLE_H
#define ANGLE_H
#include <MadgwickAHRS.h>
#include <Math.h>
#include <Wire.h>
#define LSM6DS3_ADDRESS 0x6A
#define LSM6DS3_WHO_AM_I_REG 0X0F
#define LSM6DS3_CTRL1_XL 0X10
#define LSM6DS3_CTRL2_G 0X11
#define LSM6DS3_STATUS_REG 0X1E
#define LSM6DS3_CTRL6_C 0X15
#define LSM6DS3_CTRL7_G 0X16
#define LSM6DS3_CTRL8_XL 0X17
#define LSM6DS3_OUT_TEMP_L 0X20
#define LSM6DS3_OUTX_L_G 0X22
#define LSM6DS3_OUTX_H_G 0X23
#define LSM6DS3_OUTY_L_G 0X24
#define LSM6DS3_OUTY_H_G 0X25
#define LSM6DS3_OUTZ_L_G 0X26
#define LSM6DS3_OUTZ_H_G 0X27
#define LSM6DS3_OUTX_L_XL 0X28
#define LSM6DS3_OUTX_H_XL 0X29
#define LSM6DS3_OUTY_L_XL 0X2A
#define LSM6DS3_OUTY_H_XL 0X2B
#define LSM6DS3_OUTZ_L_XL 0X2C
#define LSM6DS3_OUTZ_H_XL 0X2D
class Angle
{
protected:
float pitchFilteredOld;
Madgwick filter;
const float sensorRate = 104.00;
TwoWire *_wire;
int _slaveAddress = LSM6DS3_ADDRESS;
uint8_t readRegisters(uint8_t address, uint8_t *data, size_t length);
int readRegister(uint8_t address);
int gyroscopeAvailable();
void end();
int readAcceleration(float &x, float &y, float &z);
int accelerationAvailable();
int readGyroscope(float &x, float &y, float &z);
int writeRegister(uint8_t address, uint8_t value);
public:
uint8_t begin();
uint8_t lsmAngle(double *angle);
};
#endif
I noticed, that I am using LSM6DS3TR-C
which seems to be important, as a few values are different.
The WHO_AM_I
register has an expected value of 0x6A
.
It’s working now. Never mind - thanks for your help ![:slight_smile: :slight_smile:](https://community.platformio.org/images/emoji/twitter/slight_smile.png?v=12)
1 Like