diff --git a/aht.c b/aht.c index 41e1c2c..08e4009 100644 --- a/aht.c +++ b/aht.c @@ -5,16 +5,16 @@ static const uint8_t AHT_MEASURE[3] = {0xAC, 0x33, 0x00}; -void getAHTData(double *t, double *h) { +void getAHTData(i2c_inst_t *i2c, double *t, double *h) { uint8_t result[6]; uint32_t temperature; uint32_t humidity; - i2c_write_blocking(i2c_default, AHT_ADDR, AHT_MEASURE, 3, + i2c_write_blocking(i2c, AHT_ADDR, AHT_MEASURE, 3, false); // trigger measurement // now we must delay ~100ms sleep_ms(100); - i2c_read_blocking(i2c_default, AHT_ADDR, result, 6, + i2c_read_blocking(i2c, AHT_ADDR, result, 6, false); // read 6 bytes back humidity = (result[1] << 12) | (result[2] << 4) | (result[3] & 0xF0) >> 4; temperature = (result[3] & 0x0F) << 16 | (result[4] << 8) | result[5]; diff --git a/aht.h b/aht.h index 3e14683..63480a7 100644 --- a/aht.h +++ b/aht.h @@ -1,10 +1,11 @@ #ifndef AHT_H #define AHT_H +#include "hardware/i2c.h" #include #define AHT_ADDR 0x38 -void getAHTData(double *t, double *h); +void getAHTData(i2c_inst_t *i2c, double *t, double *h); #endif // AHT_H diff --git a/bmp.c b/bmp.c index cb89fc6..ad00658 100644 --- a/bmp.c +++ b/bmp.c @@ -2,11 +2,6 @@ // SPDX-License-Identifier: MIT #include "./bmp.h" -static const uint8_t BMP_RESET[2] = {0x7E, 0xB6}; -static const uint8_t BMP_CAL_DATA[21]; -static const uint8_t BMP_SETUP[6] = {0x1C, 0x0B, 0x1D, 0x08, 0x1F, 0x0A}; -static const uint8_t BMP_START[2] = {0x1B, 0x33}; - float bmp_cal_data_fp[15]; int getBMPData(i2c_inst_t *i2c, float *temperature, float *pressure) { @@ -75,44 +70,50 @@ int getBMPCalData(i2c_inst_t *i2c, bmp_cal_data_t *calData) { calData->NVM_PAR_T1 = (uint16_t)((rawValues[1] << 8) | rawValues[0]); calData->NVM_PAR_T2 = (uint16_t)((rawValues[3] << 8) | rawValues[2]); calData->NVM_PAR_T3 = (int8_t)(rawValues[4]); - calData->NVM_PAR_P1 = (int16_t)((rawValues[6] << 8) | rawValues[5]); - calData->NVM_PAR_P2 = (int16_t)((rawValues[8] << 8) | rawValues[7]); + calData->NVM_PAR_P1 = ((int16_t)(rawValues[6] << 8) | (int16_t)rawValues[5]); + calData->NVM_PAR_P2 = ((int16_t)(rawValues[8] << 8) | (int16_t)rawValues[7]); calData->NVM_PAR_P3 = (int8_t)(rawValues[9]); calData->NVM_PAR_P4 = (int8_t)(rawValues[10]); calData->NVM_PAR_P5 = (uint16_t)((rawValues[12] << 8) | rawValues[11]); calData->NVM_PAR_P6 = (uint16_t)((rawValues[14] << 8) | rawValues[13]); calData->NVM_PAR_P7 = (int8_t)(rawValues[15]); calData->NVM_PAR_P8 = (int8_t)(rawValues[16]); - calData->NVM_PAR_P9 = (int16_t)((rawValues[18] << 8) | rawValues[17]); + calData->NVM_PAR_P9 = + ((int16_t)(rawValues[18] << 8) | (int16_t)rawValues[17]); calData->NVM_PAR_P10 = (int8_t)(rawValues[19]); calData->NVM_PAR_P11 = (int8_t)(rawValues[20]); // convert cal values to floating point, adjusted values - bmp_cal_data_fp[PAR_T1] = (float)calData->NVM_PAR_T1 / pow(2, -8); - bmp_cal_data_fp[PAR_T2] = (float)calData->NVM_PAR_T2 / pow(2, 30); - bmp_cal_data_fp[PAR_T3] = (float)calData->NVM_PAR_T3 / pow(2, 48); + bmp_cal_data_fp[PAR_T1] = (float)calData->NVM_PAR_T1 * 256.0f; + bmp_cal_data_fp[PAR_T2] = (float)calData->NVM_PAR_T2 / 1073741824.0f; + bmp_cal_data_fp[PAR_T3] = (float)calData->NVM_PAR_T3 / 281474976710656.0f; bmp_cal_data_fp[PAR_P1] = - ((float)calData->NVM_PAR_P1 - pow(2, 14)) / pow(2, 20); + ((float)calData->NVM_PAR_P1 - 16384.0f) / 1048576.0f; bmp_cal_data_fp[PAR_P2] = - ((float)calData->NVM_PAR_P2 - pow(2, 14)) / pow(2, 29); - bmp_cal_data_fp[PAR_P3] = (float)calData->NVM_PAR_P3 / pow(2, 32); - bmp_cal_data_fp[PAR_P4] = (float)calData->NVM_PAR_P4 / pow(2, 37); - bmp_cal_data_fp[PAR_P5] = (float)calData->NVM_PAR_P5 / pow(2, -3); - bmp_cal_data_fp[PAR_P6] = (float)calData->NVM_PAR_P6 / pow(2, 6); - bmp_cal_data_fp[PAR_P7] = (float)calData->NVM_PAR_P7 / pow(2, 8); - bmp_cal_data_fp[PAR_P8] = (float)calData->NVM_PAR_P8 / pow(2, 15); - bmp_cal_data_fp[PAR_P9] = (float)calData->NVM_PAR_P9 / pow(2, 48); - bmp_cal_data_fp[PAR_P10] = (float)calData->NVM_PAR_P10 / pow(2, 48); - bmp_cal_data_fp[PAR_P11] = (float)calData->NVM_PAR_P11 / pow(2, 65); + ((float)calData->NVM_PAR_P2 - 16384.0f) / 536870912.0f; + bmp_cal_data_fp[PAR_P3] = (float)calData->NVM_PAR_P3 / 4294967296.0f; + bmp_cal_data_fp[PAR_P4] = (float)calData->NVM_PAR_P4 / 137438953472.0f; + bmp_cal_data_fp[PAR_P5] = (float)calData->NVM_PAR_P5 * 8.0f; + bmp_cal_data_fp[PAR_P6] = (float)calData->NVM_PAR_P6 / 64.0f; + bmp_cal_data_fp[PAR_P7] = (float)calData->NVM_PAR_P7 / 256.0f; + bmp_cal_data_fp[PAR_P8] = (float)calData->NVM_PAR_P8 / 32768.0f; + bmp_cal_data_fp[PAR_P9] = (float)calData->NVM_PAR_P9 / 281474976710656.0f; + bmp_cal_data_fp[PAR_P10] = (float)calData->NVM_PAR_P10 / 281474976710656.0f; + bmp_cal_data_fp[PAR_P11] = + (float)calData->NVM_PAR_P11 / 36893488147419103232.0f; return 0; } int initBMP(i2c_inst_t *i2c) { - bmp_cal_data_t bmpRawCalValues, *bmpRawCalValues_t = &bmpRawCalValues; + static const uint8_t BMP_RESET[2] = {0x7E, 0xB6}; + static const uint8_t BMP_SETUP[6] = {0x1C, 0x0B, 0x1D, 0x08, 0x1F, 0x0A}; + static const uint8_t BMP_START[2] = {0x1B, 0x33}; + + bmp_cal_data_t bmpRawCalValues; i2c_write_blocking(i2c, BMP_ADDR, BMP_RESET, 2, false); // send reset sleep_ms(2); // wait for reset to complete - getBMPCalData(i2c, bmpRawCalValues_t); + getBMPCalData(i2c, &bmpRawCalValues); i2c_write_blocking(i2c, BMP_ADDR, BMP_SETUP, 6, false); // set up sampling parameters i2c_write_blocking(i2c, BMP_ADDR, BMP_START, 2, diff --git a/bmp.h b/bmp.h index 87faa92..0e95082 100644 --- a/bmp.h +++ b/bmp.h @@ -2,7 +2,6 @@ #define BMP_H #include "hardware/i2c.h" -#include #include #define BMP_ADDR 0x77 @@ -10,10 +9,6 @@ static const uint8_t BMP_STATUS = 0x03; static const uint8_t BMP_DATA = 0x04; static const uint8_t BMP_CAL_ADDR = 0x31; #define BMP_CAL_LEN 21 -static const uint8_t BMP_RESET[2]; -static const uint8_t BMP_CAL_DATA[21]; -static const uint8_t BMP_SETUP[6]; -static const uint8_t BMP_START[2]; // instead of a bunch of defines enum { diff --git a/ens.c b/ens.c index 0b97db8..3d6fc96 100644 --- a/ens.c +++ b/ens.c @@ -6,34 +6,34 @@ static const uint8_t ENS_ACTIVATE[2] = {0x10, 0x02}; static const uint8_t ENS_IDLE[2] = {0x10, 0x01}; -void activateENS(void) { - i2c_write_blocking(i2c_default, ENS_ADDR, ENS_ACTIVATE, 2, false); +void activateENS(i2c_inst_t *i2c) { + i2c_write_blocking(i2c, ENS_ADDR, ENS_ACTIVATE, 2, false); return; } -void deactivateENS(void) { - i2c_write_blocking(i2c_default, ENS_ADDR, ENS_IDLE, 2, false); +void deactivateENS(i2c_inst_t *i2c) { + i2c_write_blocking(i2c, ENS_ADDR, ENS_IDLE, 2, false); return; } -uint8_t getENSData(double *t, double *h, uint8_t *AQI, uint16_t *TVOC, +uint8_t getENSData(i2c_inst_t *i2c, double *t, double *h, uint8_t *AQI, uint16_t *TVOC, uint16_t *ECO2, uint16_t *ETOH) { uint16_t K = (uint16_t)((*t + 273.15) * 64.0); // convert to ENS format - uint16_t RH = (uint16_t)*h * 512; + uint16_t RH = (uint16_t)(*h * 512.0); uint8_t inputData[5] = {0x13, (uint8_t)(K & 0x00FF), (uint8_t)(K >> 8), (uint8_t)(RH & 0x00FF), (uint8_t)(RH >> 8)}; uint8_t result[7]; uint8_t dataReg = ENS_AQI; uint8_t valid; - i2c_write_blocking(i2c_default, ENS_ADDR, inputData, 5, false); + i2c_write_blocking(i2c, ENS_ADDR, inputData, 5, false); sleep_ms(100); - i2c_write_blocking(i2c_default, ENS_ADDR, &dataReg, 1, true); - i2c_read_blocking(i2c_default, ENS_ADDR, result, 7, false); + i2c_write_blocking(i2c, ENS_ADDR, &dataReg, 1, true); + i2c_read_blocking(i2c, ENS_ADDR, result, 7, false); *AQI = result[0]; *TVOC = (result[2] << 8) | result[1]; *ECO2 = (result[4] << 8) | result[3]; *ETOH = (result[6] << 8) | result[5]; dataReg = 0x20; // status register - i2c_write_blocking(i2c_default, ENS_ADDR, &dataReg, 1, true); - i2c_read_blocking(i2c_default, ENS_ADDR, result, 1, false); + i2c_write_blocking(i2c, ENS_ADDR, &dataReg, 1, true); + i2c_read_blocking(i2c, ENS_ADDR, result, 1, false); valid = (result[0] & ENS_STATUS_MASK) == 0 ? 1 : 0; // check if we are in warm-up or normal mode diff --git a/ens.h b/ens.h index 16221f1..fa400e5 100644 --- a/ens.h +++ b/ens.h @@ -13,9 +13,11 @@ #define ENS_ECO2 0x24 #define ENS_ETOH 0x26 -void activateENS(void); -void deactivateENS(void); -uint8_t getENSData(double *t, double *h, uint8_t *AQI, uint16_t *TVOC, +#include "hardware/i2c.h" + +void activateENS(i2c_inst_t *i2c); +void deactivateENS(i2c_inst_t *i2c); +uint8_t getENSData(i2c_inst_t *i2c, double *t, double *h, uint8_t *AQI, uint16_t *TVOC, uint16_t *ECO2, uint16_t *ETOH); #endif // ENS_H diff --git a/main.c b/main.c index e9c4cf6..812e16e 100644 --- a/main.c +++ b/main.c @@ -44,14 +44,6 @@ #define WIFI_PASSWORD "WIFI_PASSWORD" #define MQTT_KEEP_ALIVE_SECONDS 60 -// MQTT Topics -static const char temp_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.temperature"; -static const char humi_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.humidity"; -static const char aqi_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.aqi"; -static const char tvoc_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.tvoc"; -static const char etoh_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.etoh"; -static const char eco2_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.eco2"; - static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { LWIP_UNUSED_ARG(client); @@ -65,7 +57,7 @@ static float average_float(const float *samples, uint8_t count) { for (uint8_t i = 0; i < count; i++) { sum += samples[i]; } - return sum / count; + return sum / (float)count; } static double average_double(const double *samples, uint8_t count) { @@ -73,7 +65,7 @@ static double average_double(const double *samples, uint8_t count) { for (uint8_t i = 0; i < count; i++) { sum += samples[i]; } - return sum / count; + return sum / (double)count; } static uint16_t average_uint16(const uint16_t *samples, uint8_t count) { @@ -81,10 +73,18 @@ static uint16_t average_uint16(const uint16_t *samples, uint8_t count) { for (uint8_t i = 0; i < count; i++) { sum += samples[i]; } - return (uint16_t)((sum + (uint32_t)count / 2) / (uint32_t)count); + return (uint16_t)((sum + (uint32_t)count / 2UL) / (uint32_t)count); } -int main() { +int main(void) { + // MQTT Topics + static const char temp_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.temperature"; + static const char humi_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.humidity"; + static const char aqi_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.aqi"; + static const char tvoc_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.tvoc"; + static const char etoh_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.etoh"; + static const char eco2_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.eco2"; + static const char prs_topic[] = "ADAFRUIT_IO_USERNAME/feeds/ensaht.pressure"; uint16_t tvoc, eco2, etoh, avg_tvoc, avg_eco2, avg_etoh; uint8_t aqi, validData; double t, h, avg_t, avg_h, avg_bmp_t, avg_bmp_p; @@ -93,8 +93,8 @@ int main() { float bmpt_avg[AVERAGES]; float bmpp_avg[AVERAGES]; char payload[32]; - float bmpT; - float bmpP; + float bmpT = 0.0; + float bmpP = 0.0; // MQTT setup ensaht_mqtt_t mqtt; struct mqtt_connect_client_info_t mqtt_client_info = { @@ -139,7 +139,7 @@ int main() { if (mqtt_err != ERR_OK) { printf("MQTT connect start failed: %d\n", mqtt_err); } - i2c_init(i2c_default, 100 * 1000); // start i2c at 100khz + i2c_init(i2c_default, 400 * 1000); // start i2c0 at 400khz gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); @@ -159,10 +159,10 @@ int main() { printf("\x1b[2J"); // clear screen uint8_t i = 0; uint8_t sample_count = 0; - activateENS(); + activateENS(i2c_default); while (1) { // cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); - getAHTData(&t, &h); + getAHTData(i2c_default, &t, &h); getBMPData(i2c1, &bmpT, &bmpP); t_avg[i] = t; h_avg[i] = h; @@ -177,8 +177,9 @@ int main() { avg_bmp_p = average_float(bmpp_avg, sample_count); printf("\x1b[H\x1b[JTemperature %0.2f C Humidity %0.2f%%\n", avg_t, avg_h); printf("BMP Temperature %0.2f C Pressure %0.2f kPa\n", avg_bmp_t, - avg_bmp_p / 100.0); - validData = getENSData(&avg_bmp_t, &avg_h, &aqi, &tvoc, &eco2, &etoh); + avg_bmp_p / 1000.0); + validData = + getENSData(i2c_default, &avg_bmp_t, &avg_h, &aqi, &tvoc, &eco2, &etoh); tvoc_avg[i] = tvoc; eco2_avg[i] = eco2; etoh_avg[i] = etoh; @@ -194,10 +195,10 @@ int main() { i++; if (i == AVERAGES) i = 0; - snprintf(payload, sizeof(payload), "%.2f", avg_t); + snprintf(payload, sizeof(payload), "%.4f", avg_bmp_t); ensaht_mqtt_publish_client(&mqtt, temp_topic, payload, strlen(payload), NULL, NULL); - snprintf(payload, sizeof(payload), "%.2f", avg_h); + snprintf(payload, sizeof(payload), "%.4f", avg_h); ensaht_mqtt_publish_client(&mqtt, humi_topic, payload, strlen(payload), NULL, NULL); snprintf(payload, sizeof(payload), "%d", avg_tvoc); @@ -212,6 +213,9 @@ int main() { snprintf(payload, sizeof(payload), "%d", aqi); ensaht_mqtt_publish_client(&mqtt, aqi_topic, payload, strlen(payload), NULL, NULL); + snprintf(payload, sizeof(payload), "%.4f", avg_bmp_p / 1000.0); + ensaht_mqtt_publish_client(&mqtt, prs_topic, payload, strlen(payload), NULL, + NULL); sleep_ms(30000); }