harden sensor acquisition after audit

This commit is contained in:
Jay
2026-08-17 09:48:05 -04:00
parent f1ac20fb4f
commit b8fe233ba6
11 changed files with 376 additions and 50 deletions
+56 -6
View File
@@ -3,10 +3,16 @@
#include <stddef.h>
#define ADXL345_REG_DEVID 0x00
#define ADXL345_REG_OFSX 0x1E
#define ADXL345_REG_OFSY 0x1F
#define ADXL345_REG_OFSZ 0x20
#define ADXL345_REG_BW_RATE 0x2C
#define ADXL345_REG_POWER_CTL 0x2D
#define ADXL345_REG_INT_ENABLE 0x2E
#define ADXL345_REG_INT_SOURCE 0x30
#define ADXL345_REG_DATA_FORMAT 0x31
#define ADXL345_REG_DATAX0 0x32
#define ADXL345_REG_FIFO_CTL 0x38
#define ADXL345_DEVID_VALUE 0xE5
#define ADXL345_BW_RATE_100_HZ 0x0A
@@ -46,7 +52,8 @@ esp_err_t adxl345_init(adxl345_t *sensor, i2c_master_bus_handle_t bus, uint32_t
*sensor = (adxl345_t){0};
static const uint8_t candidate_addresses[] = {0x53, 0x1D};
for (size_t i = 0; i < sizeof(candidate_addresses); ++i) {
for (size_t i = 0;
i < sizeof(candidate_addresses) / sizeof(candidate_addresses[0]); ++i) {
const i2c_device_config_t config = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = candidate_addresses[i],
@@ -74,8 +81,24 @@ esp_err_t adxl345_init(adxl345_t *sensor, i2c_master_bus_handle_t bus, uint32_t
return ESP_ERR_NOT_FOUND;
}
// Configure while in standby, then enter measurement mode.
// The ADXL345 is not reset by an ESP32 warm reboot. Establish every state
// that could otherwise survive from an earlier firmware run.
esp_err_t err = write_register(sensor->device, ADXL345_REG_POWER_CTL, 0x00);
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_INT_ENABLE, 0x00);
}
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_FIFO_CTL, 0x00);
}
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_OFSX, 0x00);
}
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_OFSY, 0x00);
}
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_OFSZ, 0x00);
}
if (err == ESP_OK) {
err = write_register(sensor->device, ADXL345_REG_DATA_FORMAT, ADXL345_FORMAT_FULL_8G);
}
@@ -95,17 +118,45 @@ esp_err_t adxl345_init(adxl345_t *sensor, i2c_master_bus_handle_t bus, uint32_t
err = verify_register(sensor->device, ADXL345_REG_POWER_CTL, ADXL345_POWER_MEASURE);
}
if (err != ESP_OK) {
adxl345_deinit(sensor);
}
return err;
}
esp_err_t adxl345_read_raw(const adxl345_t *sensor, adxl345_sample_t *sample)
esp_err_t adxl345_deinit(adxl345_t *sensor)
{
if (sensor == NULL || sensor->device == NULL || sample == NULL) {
if (sensor == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (sensor->device == NULL) {
sensor->address = 0;
return ESP_OK;
}
esp_err_t err = i2c_master_bus_rm_device(sensor->device);
if (err == ESP_OK) {
*sensor = (adxl345_t){0};
}
return err;
}
esp_err_t adxl345_read_raw(const adxl345_t *sensor, adxl345_sample_t *sample,
uint8_t *interrupt_source)
{
if (sensor == NULL || sensor->device == NULL || sample == NULL ||
interrupt_source == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = read_registers(sensor->device, ADXL345_REG_INT_SOURCE,
interrupt_source, 1);
if (err != ESP_OK) {
return err;
}
uint8_t data[6] = {0};
esp_err_t err = read_registers(sensor->device, ADXL345_REG_DATAX0, data, sizeof(data));
err = read_registers(sensor->device, ADXL345_REG_DATAX0, data, sizeof(data));
if (err != ESP_OK) {
return err;
}
@@ -120,4 +171,3 @@ uint8_t adxl345_address(const adxl345_t *sensor)
{
return sensor != NULL ? sensor->address : 0;
}
+9 -3
View File
@@ -20,15 +20,21 @@ typedef struct {
int16_t z;
} adxl345_sample_t;
#define ADXL345_INT_SOURCE_DATA_READY 0x80
#define ADXL345_INT_SOURCE_OVERRUN 0x01
/** Detect, identify, and configure an ADXL345 for 100 Hz, full-resolution +/-8 g. */
esp_err_t adxl345_init(adxl345_t *sensor, i2c_master_bus_handle_t bus, uint32_t bus_speed_hz);
/** Read one sensor-native, uncalibrated XYZ sample. */
esp_err_t adxl345_read_raw(const adxl345_t *sensor, adxl345_sample_t *sample);
/** Remove the sensor from its I2C bus. Safe to call on an uninitialized handle. */
esp_err_t adxl345_deinit(adxl345_t *sensor);
/** Read INT_SOURCE followed by one sensor-native, uncalibrated XYZ sample. */
esp_err_t adxl345_read_raw(const adxl345_t *sensor, adxl345_sample_t *sample,
uint8_t *interrupt_source);
uint8_t adxl345_address(const adxl345_t *sensor);
#ifdef __cplusplus
}
#endif
+9 -3
View File
@@ -20,15 +20,21 @@ typedef struct {
int16_t z;
} l3g4200d_sample_t;
#define L3G4200D_STATUS_ZYXDA 0x08
#define L3G4200D_STATUS_ZYXOR 0x80
/** Detect, identify, and configure an L3G4200D for 100 Hz, 25 Hz BW, +/-500 dps. */
esp_err_t l3g4200d_init(l3g4200d_t *sensor, i2c_master_bus_handle_t bus, uint32_t bus_speed_hz);
/** Read one sensor-native, uncalibrated XYZ sample. */
esp_err_t l3g4200d_read_raw(const l3g4200d_t *sensor, l3g4200d_sample_t *sample);
/** Remove the sensor from its I2C bus. Safe to call on an uninitialized handle. */
esp_err_t l3g4200d_deinit(l3g4200d_t *sensor);
/** Read STATUS_REG followed by one sensor-native, uncalibrated XYZ sample. */
esp_err_t l3g4200d_read_raw(const l3g4200d_t *sensor, l3g4200d_sample_t *sample,
uint8_t *status);
uint8_t l3g4200d_address(const l3g4200d_t *sensor);
#ifdef __cplusplus
}
#endif
+40 -6
View File
@@ -8,11 +8,13 @@
#define L3G4200D_REG_CTRL3 0x22
#define L3G4200D_REG_CTRL4 0x23
#define L3G4200D_REG_CTRL5 0x24
#define L3G4200D_REG_STATUS 0x27
#define L3G4200D_REG_OUT_X_L 0x28
#define L3G4200D_WHO_AM_I_VALUE 0xD3
#define L3G4200D_CTRL1_100_HZ 0x1F
#define L3G4200D_CTRL4_500_DPS 0x90
#define L3G4200D_CTRL5_LPF2_OUT 0x02
#define L3G4200D_AUTO_INCREMENT 0x80
#define L3G4200D_TIMEOUT_MS 100
@@ -48,7 +50,8 @@ esp_err_t l3g4200d_init(l3g4200d_t *sensor, i2c_master_bus_handle_t bus, uint32_
*sensor = (l3g4200d_t){0};
static const uint8_t candidate_addresses[] = {0x69, 0x68};
for (size_t i = 0; i < sizeof(candidate_addresses); ++i) {
for (size_t i = 0;
i < sizeof(candidate_addresses) / sizeof(candidate_addresses[0]); ++i) {
const i2c_device_config_t config = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = candidate_addresses[i],
@@ -89,7 +92,9 @@ esp_err_t l3g4200d_init(l3g4200d_t *sensor, i2c_master_bus_handle_t bus, uint32_
err = write_register(sensor->device, L3G4200D_REG_CTRL4, L3G4200D_CTRL4_500_DPS);
}
if (err == ESP_OK) {
err = write_register(sensor->device, L3G4200D_REG_CTRL5, 0x00);
// Route LPF2 to the output. CTRL1 BW=01 selects its 25 Hz cutoff.
err = write_register(sensor->device, L3G4200D_REG_CTRL5,
L3G4200D_CTRL5_LPF2_OUT);
}
if (err == ESP_OK) {
// 100 Hz ODR, 25 Hz bandwidth, normal mode, all axes enabled.
@@ -101,19 +106,49 @@ esp_err_t l3g4200d_init(l3g4200d_t *sensor, i2c_master_bus_handle_t bus, uint32_
if (err == ESP_OK) {
err = verify_register(sensor->device, L3G4200D_REG_CTRL4, L3G4200D_CTRL4_500_DPS);
}
if (err == ESP_OK) {
err = verify_register(sensor->device, L3G4200D_REG_CTRL5,
L3G4200D_CTRL5_LPF2_OUT);
}
if (err != ESP_OK) {
l3g4200d_deinit(sensor);
}
return err;
}
esp_err_t l3g4200d_read_raw(const l3g4200d_t *sensor, l3g4200d_sample_t *sample)
esp_err_t l3g4200d_deinit(l3g4200d_t *sensor)
{
if (sensor == NULL || sensor->device == NULL || sample == NULL) {
if (sensor == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (sensor->device == NULL) {
sensor->address = 0;
return ESP_OK;
}
esp_err_t err = i2c_master_bus_rm_device(sensor->device);
if (err == ESP_OK) {
*sensor = (l3g4200d_t){0};
}
return err;
}
esp_err_t l3g4200d_read_raw(const l3g4200d_t *sensor, l3g4200d_sample_t *sample,
uint8_t *status)
{
if (sensor == NULL || sensor->device == NULL || sample == NULL || status == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = read_registers(sensor->device, L3G4200D_REG_STATUS, status, 1);
if (err != ESP_OK) {
return err;
}
uint8_t data[6] = {0};
uint8_t start_register = L3G4200D_REG_OUT_X_L | L3G4200D_AUTO_INCREMENT;
esp_err_t err = read_registers(sensor->device, start_register, data, sizeof(data));
err = read_registers(sensor->device, start_register, data, sizeof(data));
if (err != ESP_OK) {
return err;
}
@@ -128,4 +163,3 @@ uint8_t l3g4200d_address(const l3g4200d_t *sensor)
{
return sensor != NULL ? sensor->address : 0;
}