diff --git a/CMakeLists.txt b/CMakeLists.txt index d496ea6..5be4c95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,11 +99,14 @@ add_executable(fanpico src/i2c.c src/i2c_adt7410.c src/i2c_aht.c + src/i2c_as621x.c src/i2c_bmp180.c src/i2c_bmp280.c src/i2c_dps310.c src/i2c_mcp9808.c src/i2c_pct2075.c + src/i2c_stts22h.c + src/i2c_tmp102.c src/i2c_tmp117.c src/onewire.c src/filters.c diff --git a/commands.md b/commands.md index 06b59ed..986391b 100644 --- a/commands.md +++ b/commands.md @@ -1126,11 +1126,16 @@ Supporte I2C sensors: Sensor Model|Possible Addresses|Notes ------------|------------------|----- ADT7410|0x48, 0x49, 0x4a, 0x4b|16bit, 0.5C accuracy +AHT1x||AHT1x (AHT10, AHT11 ,...) +AHT2x||AHT2x (AHT20, AHT21 ,...) +AS621x||AS621x series: AS6212 (0.2C), AC6214 (0.4C), AC6218 (0.8C) BMP180||16bit, 0.5C accuracy BMP280|0x76, 0x77|20bit, 0.5C accuracy DPS310|0x77, 0x76|24bit, 0.5C accuracy MCP9808||13bit, 0.25C accuracy PCT2075||11bit, 1C accuracy +STTS22H|0x38, 0x3c, 0x3e, 0x3f|16bit, 0.5C accuracy +TMP102|0x48, 0x49, 0x4a, 0x4b|12bit, 2C accuracy TMP117|0x48, 0x49, 0x4a, 0x4b|16bit, 0.1C accuracy diff --git a/src/fanpico.c b/src/fanpico.c index fce1705..ba1ef30 100644 --- a/src/fanpico.c +++ b/src/fanpico.c @@ -450,7 +450,7 @@ int main() int64_t delta; int c; int i_ptr = 0; - int i2c_temp_delay = 10000; + int i2c_temp_delay = 1000; set_binary_info(); @@ -525,10 +525,10 @@ int main() /* Update display every 1000ms */ if (time_passed(&t_display, 1000)) { - log_msg(LOG_DEBUG, "udpate display"); + log_msg(LOG_DEBUG, "update display start"); update_system_state(); display_status(fanpico_state, cfg); - log_msg(LOG_DEBUG, "udpate display end"); + log_msg(LOG_DEBUG, "update display end"); } /* Poll I2C Temperature Sensors */ @@ -563,12 +563,12 @@ int main() input_buf[i_ptr++] = c; if (cfg->local_echo) printf("%c", c); } -#if WATCHDOG_ENABLED if (time_passed(&t_watchdog, 1000)) { +#if WATCHDOG_ENABLED log_msg(LOG_DEBUG,"watchdog update"); watchdog_update(); - } #endif + } } } diff --git a/src/i2c.c b/src/i2c.c index 6f4a58f..b0c5981 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -43,6 +43,11 @@ void* aht2x_init(i2c_inst_t *i2c, uint8_t addr); int aht_start_measurement(void *ctx); int aht_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); +/* i2c_as621x.c */ +void* as621x_init(i2c_inst_t *i2c, uint8_t addr); +int as621x_start_measurement(void *ctx); +int as621x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); + /* i2c_bmp180.c */ void* bmp180_init(i2c_inst_t *i2c, uint8_t addr); int bmp180_start_measurement(void *ctx); @@ -68,6 +73,16 @@ void* pct2075_init(i2c_inst_t *i2c, uint8_t addr); int pct2075_start_measurement(void *ctx); int pct2075_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); +int stts22h_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); + +/* i2c_tmp102.c */ +void* tmp102_init(i2c_inst_t *i2c, uint8_t addr); +int tmp102_start_measurement(void *ctx); +int tmp102_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); + /* i2c_tmp117.c */ void* tmp117_init(i2c_inst_t *i2c, uint8_t addr); int tmp117_start_measurement(void *ctx); @@ -76,12 +91,16 @@ int tmp117_get_measurement(void *ctx, float *temp, float *pressure, float *humid 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 }, { "MCP9808", mcp9808_init, mcp9808_start_measurement, mcp9808_get_measurement }, { "PCT2075", pct2075_init, pct2075_start_measurement, pct2075_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 } }; @@ -502,7 +521,7 @@ int i2c_read_temps(struct fanpico_config *config) } sensor = i + 1; if (sensor >= VSENSOR_COUNT) { - wait_time = 15000; + wait_time = 10000; step++; log_msg(LOG_DEBUG, "I2C Temperature measurements complete."); } else { diff --git a/src/i2c_as621x.c b/src/i2c_as621x.c new file mode 100644 index 0000000..6e14ea5 --- /dev/null +++ b/src/i2c_as621x.c @@ -0,0 +1,138 @@ +/* i2c_as621x.c + Copyright (C) 2024 Timo Kokkonen + + SPDX-License-Identifier: GPL-3.0-or-later + + This file is part of FanPico. + + FanPico is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FanPico is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FanPico. If not, see . +*/ + +#include +#include +#include +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/i2c.h" + +#include "i2c.h" + +/* AS621x (AS6212/AS6214/AS6128) Registers */ +#define REG_TVAL 0x00 +#define REG_CONFIG 0x01 +#define REG_T_LOW 0x02 +#define REG_T_HIGH 0x03 + + +#define AS621X_DEVICE_ID 0x117 + +typedef struct as621x_context_t { + i2c_inst_t *i2c; + uint8_t addr; +} as621x_context_t; + + +void* as621x_init(i2c_inst_t *i2c, uint8_t addr) +{ + int res; + uint16_t val = 0; + int16_t temp; + as621x_context_t *ctx = calloc(1, sizeof(as621x_context_t)); + + if (!ctx) + return NULL; + ctx->i2c = i2c; + ctx->addr = addr; + + + /* Check that configuration register reserved bits are set as expected for AS621x */ + + res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); + if (res || (val & 0x601f) != 0x4000) + goto panic; + + + /* Try to detect device by T_HIGH and T_LOW register default values (80C and 75C) */ + + res = i2c_read_register_u16(i2c, addr, REG_T_HIGH, &val); + if (res) + goto panic; + temp = (int16_t)val / 128; + DEBUG_PRINT("T_high = %d\n", temp); + if (temp != 80) + goto panic; + + res = i2c_read_register_u16(i2c, addr, REG_T_LOW, &val); + if (res) + goto panic; + temp = (int16_t)val / 128; + DEBUG_PRINT("T_low = %d\n", temp); + if (temp != 75) + goto panic; + + + /* Set sensor configuration: continuous measruements at 4Hz */ + res = i2c_write_register_u16(i2c, addr, REG_CONFIG, 0x00a0); + if (res) + goto panic; + + sleep_us(100); + + /* Read configuration register */ + res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); + if (res) + goto panic; + + /* Check that confuration is now as expected (excluding read-only reserved bits)... */ + if ((val & 0x9fe0) != 0x00a0) + goto panic; + + return ctx; + +panic: + free(ctx); + return NULL; +} + + +int as621x_start_measurement(void *ctx) +{ + /* Nothing to do, sensor is in continuous measurement mode... */ + + return 250; /* measurement should be available after 250ms */ +} + + +int as621x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) +{ + as621x_context_t *c = (as621x_context_t*)ctx; + int res; + uint16_t val; + + + /* Get Measurement */ + res = i2c_read_register_u16(c->i2c, c->addr, REG_TVAL, &val); + if (res) + return -2; + + *temp = ((int16_t)val) / 128.0; + DEBUG_PRINT("t_raw = %d, temp=%0.2f\n", val, *temp); + + *pressure = -1.0; + *humidity = -1.0; + + return 0; +} + + diff --git a/src/i2c_stts22h.c b/src/i2c_stts22h.c new file mode 100644 index 0000000..3d42aaa --- /dev/null +++ b/src/i2c_stts22h.c @@ -0,0 +1,119 @@ +/* i2c_stts22h.c + Copyright (C) 2024 Timo Kokkonen + + SPDX-License-Identifier: GPL-3.0-or-later + + This file is part of FanPico. + + FanPico is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FanPico is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FanPico. If not, see . +*/ + +#include +#include +#include +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/i2c.h" + +#include "i2c.h" + +/* STTS22H Registers */ +#define REG_DEVICE_ID 0x01 +#define REG_TEMP_H_LIMIT 0x02 +#define REG_TEMP_L_LIMIT 0x03 +#define REG_CTRL 0x04 +#define REG_STATUS 0x05 +#define REG_TEMP_L_OUT 0x06 +#define REG_TEMP_H_OUT 0x07 + +#define STTS22H_DEVICE_ID 0xa0 + +typedef struct stts22h_context_t { + i2c_inst_t *i2c; + uint8_t addr; +} stts22h_context_t; + + +void* stts22h_init(i2c_inst_t *i2c, uint8_t addr) +{ + int res; + uint8_t val = 0; + stts22h_context_t *ctx = calloc(1, sizeof(stts22h_context_t)); + + if (!ctx) + return NULL; + ctx->i2c = i2c; + ctx->addr = addr; + + /* Read and verify device ID */ + res = i2c_read_register_u8(i2c, addr, REG_DEVICE_ID, &val); + if (res || val != STTS22H_DEVICE_ID) + goto panic; + + /* Configure Sensor: set to defaults first */ + res = i2c_write_register_u8(i2c, addr, REG_CTRL, 0x00); + if (res) + goto panic; + + sleep_us(10); + + /* Configure Sensor: avg=00, if_add_inc=1, freerun=1 */ + res = i2c_write_register_u8(i2c, addr, REG_CTRL, 0x0c); + if (res) + goto panic; + + /* Read and check configuration register */ + res = i2c_read_register_u8(i2c, addr, REG_CTRL, &val); + if (res | (val != 0x0c)) + goto panic; + + return ctx; + +panic: + free(ctx); + return NULL; +} + + +int stts22h_start_measurement(void *ctx) +{ + /* Nothing to do, sensor is in continuous measurement mode... */ + + return 50; /* measurement should be available after 40ms (25Hz) */ +} + + +int stts22h_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) +{ + stts22h_context_t *c = (stts22h_context_t*)ctx; + int res; + uint16_t val; + + + /* Get Measurement */ + res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP_L_OUT, &val); + if (res) + return -2; + + val = (val << 8) | (val >> 8); /* reverse byte order */ + *temp = ((int16_t)val) / 100.0; + *pressure = -1.0; + *humidity = -1.0; + + DEBUG_PRINT("raw_temp=%d, temp=%0.2f\n", val, *temp); + + return 0; +} + + diff --git a/src/i2c_tmp102.c b/src/i2c_tmp102.c new file mode 100644 index 0000000..60d645f --- /dev/null +++ b/src/i2c_tmp102.c @@ -0,0 +1,135 @@ +/* i2c_tmp102.c + Copyright (C) 2024 Timo Kokkonen + + SPDX-License-Identifier: GPL-3.0-or-later + + This file is part of FanPico. + + FanPico is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + FanPico is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with FanPico. If not, see . +*/ + +#include +#include +#include +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/i2c.h" + +#include "i2c.h" + +/* TMP102 Registers */ +#define REG_TEMP_RESULT 0x00 +#define REG_CONFIG 0x01 +#define REG_T_LOW 0x02 +#define REG_T_HIGH 0x03 + + + +typedef struct tmp102_context_t { + i2c_inst_t *i2c; + uint8_t addr; +} tmp102_context_t; + + +void* tmp102_init(i2c_inst_t *i2c, uint8_t addr) +{ + int res; + uint16_t val = 0; + tmp102_context_t *ctx = calloc(1, sizeof(tmp102_context_t)); + + if (!ctx) + return NULL; + ctx->i2c = i2c; + ctx->addr = addr; + + + /* Verify configuration register read-only bits */ + res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); + if (res || ((val & 0x600f) != 0x6000)) + goto panic; + + /* Try to detect device by T_HIGH and T_LOW register default values (80C and 75C) */ + + res = i2c_read_register_u16(i2c, addr, REG_T_HIGH, &val); + if (res) + goto panic; + val = twos_complement((val >> 4), 12) / 16; + DEBUG_PRINT("T_high = %d\n", val); + if (val != 80) + goto panic; + + res = i2c_read_register_u16(i2c, addr, REG_T_LOW, &val); + if (res) + goto panic; + val = twos_complement((val >> 4), 12) / 16; + DEBUG_PRINT("T_low = %d\n", val); + if (val != 75) + goto panic; + + + /* Set sensor configuration: enable EM mode */ + res = i2c_write_register_u16(i2c, addr, REG_CONFIG, 0x00b0); + if (res) + goto panic; + + sleep_us(100); + + /* Read configuration register */ + res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); + if (res) + goto panic; + + /* Check that confuration is now as expected (excluding read-only bits R1/R0)... */ + if ((val & 0x9fff) != 0x00b0) + goto panic; + + return ctx; + +panic: + free(ctx); + return NULL; +} + + +int tmp102_start_measurement(void *ctx) +{ + /* Nothing to do, sensor is in continuous measurement mode... */ + + return 250; /* measurement should be available after 250ms */ +} + + +int tmp102_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) +{ + tmp102_context_t *c = (tmp102_context_t*)ctx; + int res; + uint16_t val; + + + /* Get Measurement */ + res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP_RESULT, &val); + if (res) + return -2; + + val = twos_complement((val >> 3), 13); + *temp = ((int16_t)val) / 16.0; + DEBUG_PRINT("t_raw = %d, temp=%0.2f\n", val, *temp); + + *pressure = -1.0; + *humidity = -1.0; + + return 0; +} + + diff --git a/src/onewire.c b/src/onewire.c index caf9405..5be064f 100644 --- a/src/onewire.c +++ b/src/onewire.c @@ -77,6 +77,7 @@ void onewire_scan_bus() log_msg(LOG_INFO, "All devices in 1-Wire bus have power."); } else { log_msg(LOG_INFO, "1-Wire bus has devices requiring 'phantom' power."); + return; } /* Search for devices... */