Skip to content

Commit

Permalink
I2C and 1-Wire Updates (#113)
Browse files Browse the repository at this point in the history
* Add support for TMP102 temperature sensor.
* Add support for STTS22H Temperature sensor.
* Add AS621x (AS6212/AS6214/AS6128) temperature sensor support.
* Add AHT1x sensor support.
* Update I2C initialization timings.
* Skip 1-wire initialization if any device using phantom power.
  • Loading branch information
tjko authored Aug 24, 2024
1 parent 234a233 commit a45521a
Show file tree
Hide file tree
Showing 8 changed files with 426 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
10 changes: 5 additions & 5 deletions src/fanpico.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
}
}
}

Expand Down
21 changes: 20 additions & 1 deletion src/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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 }
};
Expand Down Expand Up @@ -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 {
Expand Down
138 changes: 138 additions & 0 deletions src/i2c_as621x.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* i2c_as621x.c
Copyright (C) 2024 Timo Kokkonen <[email protected]>
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 <https://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}


119 changes: 119 additions & 0 deletions src/i2c_stts22h.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* i2c_stts22h.c
Copyright (C) 2024 Timo Kokkonen <[email protected]>
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 <https://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}


Loading

0 comments on commit a45521a

Please sign in to comment.