Skip to content

Commit

Permalink
I2C Updates (#126)
Browse files Browse the repository at this point in the history
* Add support for skipping OLED panel initialization.
* Add support for SHT4x series temperature and humidity sensors.
* Add support for SHT3x series temperature and humidity sensors.
* Add support for MS8607 Temperature, Pressure, and Humidity sensor.
  • Loading branch information
tjko authored Sep 28, 2024
1 parent 073015f commit 43d1874
Show file tree
Hide file tree
Showing 13 changed files with 823 additions and 36 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@ add_executable(fanpico
src/i2c_lps22.c
src/i2c_lps25.c
src/i2c_mcp9808.c
src/i2c_ms8607.c
src/i2c_pct2075.c
src/i2c_shtc3.c
src/i2c_sht3x.c
src/i2c_sht4x.c
src/i2c_stts22h.c
src/i2c_tmp102.c
src/i2c_tmp117.c
Expand Down
8 changes: 6 additions & 2 deletions commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1167,8 +1167,8 @@ Sensor numbering:

Supporte I2C sensors:

Sensor Model|Possible Addresses|Notes
------------|------------------|-----
Sensor Model|Possible Addresses|Description|Notes
------------|------------------|-----------|-----
ADT7410|0x48, 0x49, 0x4a, 0x4b|16bit, 0.5C accuracy
AHT1x||AHT1x (AHT10, AHT11 ,...)
AHT2x||AHT2x (AHT20, AHT21 ,...)
Expand All @@ -1179,7 +1179,10 @@ DPS310|0x77, 0x76|24bit, 0.5C accuracy
LPS22|0x5d, 0x5c|Temperature and Pressure sensor
LPS25|0x5d, 0x5c|Temperature and Pressure sensor, 2C accuracy
MCP9808||13bit, 0.25C accuracy
MS8607|0x77|Temperature, Humidity and Pressure Sensor
PCT2075||11bit, 1C accuracy
SHT3x|0x44, 0x34|SHT3x Series Temperature and Humidity sensors (SHT30, SHT31, SHT35)|Not always found when scanning bus (SYS:I2C:SCAN?)
SHT4x|0x44|SHT4x Series Temperature and Humidity sensors (SHT40, SHT41, SHT43, SHT45)|Not always found when scanning bus (SYS:I2C:SCAN?)
SHTC3|0x70|Temperature and Humidity sensor, 0.2C accuracy
STTS22H|0x38, 0x3c, 0x3e, 0x3f|16bit, 0.5C accuracy
TMP102|0x48, 0x49, 0x4a, 0x4b|12bit, 2C accuracy
Expand Down Expand Up @@ -1729,6 +1732,7 @@ Currently supported values:
Value|Description|Notes
-----|-----------|-----
default|Use default settings (auto-detect).
none|Disable OLED support|Skips scanning for OLED panel.
128x64|OLED 128x64 module installed.|OLED
128x128|OLED 128x128 module installed.|OLED
132x64|OLED 132x64 installed (some 1.3" 128x64 modules need this setting!)|OLED
Expand Down
11 changes: 9 additions & 2 deletions src/display_oled.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,11 @@ void oled_display_init()
if (args) {
tok = strtok_r(args, ",", &saveptr);
while (tok) {
if (!strncmp(tok, "132x64", 6))
if (!strncmp(tok, "none", 4))
dtype = -1;
else if (!strncmp(tok, "132x64", 6))
dtype = OLED_132x64;
if (!strncmp(tok, "128x128", 7)) {
else if (!strncmp(tok, "128x128", 7)) {
dtype = OLED_128x128;
oled_height = 128;
r_lines = 10;
Expand All @@ -164,6 +166,11 @@ void oled_display_init()
}
}

if (dtype < 0) {
log_msg(LOG_NOTICE, "OLED display support disabled.");
return;
}

if (strlen(cfg->display_layout_r) > 1) {
parse_r_layout(cfg->display_layout_r);
} else {
Expand Down
87 changes: 64 additions & 23 deletions src/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ void* mcp9808_init(i2c_inst_t *i2c, uint8_t addr);
int mcp9808_start_measurement(void *ctx);
int mcp9808_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

/* i2c_ms8607.c */
void* ms8607_init(i2c_inst_t *i2c, uint8_t addr);
int ms8607_start_measurement(void *ctx);
int ms8607_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

/* i2c_pct2075.c */
void* pct2075_init(i2c_inst_t *i2c, uint8_t addr);
int pct2075_start_measurement(void *ctx);
Expand All @@ -88,6 +93,16 @@ void* shtc3_init(i2c_inst_t *i2c, uint8_t addr);
int shtc3_start_measurement(void *ctx);
int shtc3_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

/* i2c_sht3x.c */
void* sht3x_init(i2c_inst_t *i2c, uint8_t addr);
int sht3x_start_measurement(void *ctx);
int sht3x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

/* i2c_sht4x.c */
void* sht4x_init(i2c_inst_t *i2c, uint8_t addr);
int sht4x_start_measurement(void *ctx);
int sht4x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

/* i2c_stts22h.c */
void* stts22h_init(i2c_inst_t *i2c, uint8_t addr);
int stts22h_start_measurement(void *ctx);
Expand All @@ -104,23 +119,26 @@ int tmp117_start_measurement(void *ctx);
int tmp117_get_measurement(void *ctx, float *temp, float *pressure, float *humidity);

static const i2c_sensor_entry_t i2c_sensor_types[] = {
{ "NONE", NULL, NULL, NULL }, /* this needs to be first so that valid sensors have index > 0 */
{ "ADT7410", adt7410_init, adt7410_start_measurement, adt7410_get_measurement },
{ "AHT1x", aht1x_init, aht_start_measurement, aht_get_measurement },
{ "AHT2x", aht2x_init, aht_start_measurement, aht_get_measurement },
{ "AS621x", as621x_init, as621x_start_measurement, as621x_get_measurement },
{ "BMP180", bmp180_init, bmp180_start_measurement, bmp180_get_measurement },
{ "BMP280", bmp280_init, bmp280_start_measurement, bmp280_get_measurement },
{ "DPS310", dps310_init, dps310_start_measurement, dps310_get_measurement },
{ "LPS22", lps22_init, lps22_start_measurement, lps22_get_measurement },
{ "LPS25", lps25_init, lps25_start_measurement, lps25_get_measurement },
{ "MCP9808", mcp9808_init, mcp9808_start_measurement, mcp9808_get_measurement },
{ "PCT2075", pct2075_init, pct2075_start_measurement, pct2075_get_measurement },
{ "SHTC3", shtc3_init, shtc3_start_measurement, shtc3_get_measurement },
{ "STTS22H", stts22h_init, stts22h_start_measurement, stts22h_get_measurement },
{ "TMP102", tmp102_init, tmp102_start_measurement, tmp102_get_measurement },
{ "TMP117", tmp117_init, tmp117_start_measurement, tmp117_get_measurement },
{ NULL, NULL, NULL, NULL }
{ "NONE", NULL, NULL, NULL, false }, /* this needs to be first so that valid sensors have index > 0 */
{ "ADT7410", adt7410_init, adt7410_start_measurement, adt7410_get_measurement, false },
{ "AHT1x", aht1x_init, aht_start_measurement, aht_get_measurement, false },
{ "AHT2x", aht2x_init, aht_start_measurement, aht_get_measurement, false },
{ "AS621x", as621x_init, as621x_start_measurement, as621x_get_measurement, false },
{ "BMP180", bmp180_init, bmp180_start_measurement, bmp180_get_measurement, false },
{ "BMP280", bmp280_init, bmp280_start_measurement, bmp280_get_measurement, false },
{ "DPS310", dps310_init, dps310_start_measurement, dps310_get_measurement, false },
{ "LPS22", lps22_init, lps22_start_measurement, lps22_get_measurement, false },
{ "LPS25", lps25_init, lps25_start_measurement, lps25_get_measurement, false },
{ "MCP9808", mcp9808_init, mcp9808_start_measurement, mcp9808_get_measurement, false },
{ "MS8607", ms8607_init, ms8607_start_measurement, ms8607_get_measurement, true },
{ "PCT2075", pct2075_init, pct2075_start_measurement, pct2075_get_measurement, false },
{ "SHTC3", shtc3_init, shtc3_start_measurement, shtc3_get_measurement, false },
{ "SHT3x", sht3x_init, sht3x_start_measurement, sht3x_get_measurement, true },
{ "SHT4x", sht4x_init, sht4x_start_measurement, sht4x_get_measurement, true },
{ "STTS22H", stts22h_init, stts22h_start_measurement, stts22h_get_measurement, false },
{ "TMP102", tmp102_init, tmp102_start_measurement, tmp102_get_measurement, false },
{ "TMP117", tmp117_init, tmp117_start_measurement, tmp117_get_measurement, false },
{ NULL, NULL, NULL, NULL, false }
};

static bool i2c_bus_active = false;
Expand All @@ -138,9 +156,11 @@ static int i2c_init_sensor(uint8_t type, uint8_t addr, void **ctx)
return -1;

/* Check for a device on given address... */
if (i2c_read_timeout_us(i2c_bus, addr, buf, 1, false,
I2C_READ_TIMEOUT(1)) < 0)
if (!i2c_sensor_types[type].no_scan) {
if (i2c_read_timeout_us(i2c_bus, addr, buf, 1, false,
I2C_READ_TIMEOUT(1)) < 0)
return -2;
}

/* Initialize sensor */
*ctx = i2c_sensor_types[type].init(i2c_bus, addr);
Expand Down Expand Up @@ -189,7 +209,8 @@ inline bool i2c_reserved_address(uint8_t addr)
}


int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len)
int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len,
uint32_t read_delay_us)
{
int res;

Expand All @@ -201,6 +222,9 @@ int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t
return -1;
}

if (read_delay_us > 0)
sleep_us(read_delay_us);

res = i2c_read_timeout_us(i2c, addr, buf, len, false,
I2C_READ_TIMEOUT(len));
if (res < len) {
Expand All @@ -226,7 +250,7 @@ int i2c_read_register_u24(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint32_t *
int res;

DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val);
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf));
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0);
if (res) {
DEBUG_PRINT("failed to read register\n");
return -1;
Expand All @@ -245,7 +269,7 @@ int i2c_read_register_u16(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint16_t *
int res;

DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val);
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf));
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0);
if (res) {
DEBUG_PRINT("failed to read register\n");
return -1;
Expand All @@ -264,7 +288,7 @@ int i2c_read_register_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *va
int res;

DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val);
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf));
res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0);
if (res) {
DEBUG_PRINT("failed to read register\n");
return -1;
Expand Down Expand Up @@ -391,6 +415,23 @@ int i2c_write_raw_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t cmd, bool nostop)
}


int i2c_write_raw_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t cmd, bool nostop)
{
int res;

DEBUG_PRINT("args=%p,%02x,%04x\n", i2c, addr, cmd);

res = i2c_write_timeout_us(i2c, addr, &cmd, 1, nostop,
I2C_WRITE_TIMEOUT(1));
if (res < 1) {
DEBUG_PRINT("write failed (%d)\n", res);
return -1;
}

return 0;
}


uint get_i2c_sensor_type(const char *name)
{
int type = -1;
Expand Down
9 changes: 6 additions & 3 deletions src/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
#if I2C_DEBUG > 0
#define DEBUG_PRINT(fmt, ...) \
do { \
uint64_t t = to_us_since_boot(get_absolute_time()); \
uint64_t ttt = to_us_since_boot(get_absolute_time()); \
printf("[%6llu.%06llu] %s:%d: %s(): " fmt, \
(t / 1000000), (t % 1000000), \
(ttt / 1000000), (ttt % 1000000), \
__FILE__, __LINE__, __func__, \
##__VA_ARGS__); \
} while (0)
Expand Down Expand Up @@ -65,11 +65,13 @@ typedef struct i2c_sensor_entry {
i2c_init_func_t *init;
i2c_start_measurement_func_t *start_measurement;
i2c_get_measurement_func_t *get_measurement;
bool no_scan;
} i2c_sensor_entry_t;


/* Helper functions for reading/writing sensor registers */
int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len);
int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len,
uint32_t read_delay_us);
int i2c_read_register_u24(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint32_t *val);
int i2c_read_register_u16(i2c_inst_t *i2c, uint8_t i2c_addr, uint8_t reg, uint16_t *val);
int i2c_read_register_u8(i2c_inst_t *i2c, uint8_t i2c_addr, uint8_t reg, uint8_t *val);
Expand All @@ -79,6 +81,7 @@ int i2c_write_register_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t va

int i2c_read_raw(i2c_inst_t *i2c, uint8_t addr, uint8_t *buf, size_t len, bool nostop);
int i2c_write_raw_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t cmd, bool nostop);
int i2c_write_raw_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t cmd, bool nostop);

int32_t twos_complement(uint32_t value, uint8_t bits);

Expand Down
2 changes: 1 addition & 1 deletion src/i2c_bmp180.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void* bmp180_init(i2c_inst_t *i2c, uint8_t addr)


/* Read calibration data */
res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 22);
res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 22, 0);
if (res)
goto panic;

Expand Down
4 changes: 2 additions & 2 deletions src/i2c_bmp280.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void* bmp280_init(i2c_inst_t *i2c, uint8_t addr)


/* Read calibration data */
res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 26);
res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 26, 0);
if (res)
goto panic;

Expand Down Expand Up @@ -197,7 +197,7 @@ int bmp280_get_measurement(void *ctx, float *temp, float *pressure, float *humid


/* Read Pressure & Temperature registers */
res = i2c_read_register_block(c->i2c, c->addr, REG_PRESS_MSB, buf, 6);
res = i2c_read_register_block(c->i2c, c->addr, REG_PRESS_MSB, buf, 6, 0);
if (res)
return -2;

Expand Down
2 changes: 1 addition & 1 deletion src/i2c_dps310.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void* dps310_init(i2c_inst_t *i2c, uint8_t addr)
goto panic;

/* Read calibration coefficients */
res = i2c_read_register_block(i2c, addr, REG_COEF, buf, 18);
res = i2c_read_register_block(i2c, addr, REG_COEF, buf, 18, 0);
if (res)
goto panic;

Expand Down
2 changes: 1 addition & 1 deletion src/i2c_lps22.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ int lps22_get_measurement(void *ctx, float *temp, float *pressure, float *humidi
return 1;

/* Get Measurement */
res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL, buf, sizeof(buf));
res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL, buf, sizeof(buf), 0);
if (res)
return -2;

Expand Down
2 changes: 1 addition & 1 deletion src/i2c_lps25.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ int lps25_get_measurement(void *ctx, float *temp, float *pressure, float *humidi
return 1;

/* Get Measurement */
res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL | 0x80, buf, sizeof(buf));
res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL | 0x80, buf, sizeof(buf), 0);
if (res)
return -2;

Expand Down
Loading

0 comments on commit 43d1874

Please sign in to comment.