Compare commits

..

2 commits

4 changed files with 43 additions and 30 deletions

View file

@ -9,8 +9,8 @@ set(CMAKE_CXX_STANDARD 17)
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/amr/workspace/rp2040/pico-sdk")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(PICO_BOARD pico_w CACHE STRING "Board type")
set(PICO_BOARD pico2_w CACHE STRING "Board type")
#set(PICO_DEFAULT_RP2350_PLATFORM rp2350-riscv)
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
@ -18,10 +18,11 @@ if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
project(ensaht C CXX ASM)
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(ensaht
@ -39,6 +40,7 @@ target_include_directories(ensaht PRIVATE
${CMAKE_CURRENT_LIST_DIR}/include
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
# target_compile_options(ensaht PRIVATE -ggdb)
pico_set_program_name(ensaht "ensaht")
pico_set_program_version(ensaht "0.1")
pico_enable_stdio_usb(ensaht 1)
@ -60,7 +62,7 @@ pico_add_extra_outputs(ensaht)
add_custom_target(flash
COMMAND openocd
-f interface/cmsis-dap.cfg
-f target/rp2040.cfg
-f target/rp2350.cfg
-c "adapter speed 10000"
-c "program ${CMAKE_CURRENT_BINARY_DIR}/ensaht.elf verify"
-c "reset init"
@ -69,7 +71,7 @@ add_custom_target(flash
)
add_custom_target(debug
COMMAND arm-none-eabi-gdb -ex "target extended-remote | openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c 'adapter speed 10000' -c 'gdb_port pipe'" ${CMAKE_CURRENT_BINARY_DIR}/ensaht.elf
COMMAND bash -c "openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c 'adapter speed 10000' & PID=\$\$! ; trap 'kill -9 \$\$PID 2>/dev/null || true' EXIT ; sleep 1 ; arm-none-eabi-gdb -ex 'target extended-remote localhost:3333' ${CMAKE_CURRENT_BINARY_DIR}/ensaht.elf"
DEPENDS flash
USES_TERMINAL
VERBATIM

View file

@ -13,12 +13,12 @@ void getAHTData(i2c_inst_t *i2c, double *t, double *h) {
uint32_t temperature;
uint32_t humidity;
i2c_write_blocking(i2c, AHT_ADDR, AHT_MEASURE, 3,
false); // trigger measurement
i2c_write_timeout_us(i2c, AHT_ADDR, AHT_MEASURE, 3, false,
1200); // trigger measurement
// now we must delay ~100ms
sleep_ms(100);
i2c_read_blocking(i2c, AHT_ADDR, result, 6,
false); // read 6 bytes back
i2c_read_timeout_us(i2c, AHT_ADDR, result, 6, false,
3000); // 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];
*t = (((double)temperature / 1048576.0f) * 200.0f) - 50.0f;

View file

@ -18,8 +18,6 @@
* the readings to Adafruit IO over MQTT using the Pico W.
******************************************************************************/
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "include/aht.h"
#include "include/bmp.h"
#include "include/credentials.h"
@ -29,6 +27,8 @@
#include "pico/cyw43_arch.h"
#include "pico/stdlib.h" // IWYU pragma: keep
#include <boards/pico_w.h>
#include <hardware/gpio.h>
#include <hardware/i2c.h>
#include <hardware/structs/io_bank0.h>
#include <pico/binary_info/code.h>
#include <pico/double.h>
@ -85,6 +85,15 @@ int main(void) {
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";
static const char valid_topic[] =
ADAFRUIT_IO_USERNAME "/feeds/ensaht.datavalid";
OPT4048_Data lightData = {
.x = 0,
.y = 0,
.z = 0,
.lux = 0,
};
float lightch0, lightch1, lightch2;
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;
@ -139,7 +148,7 @@ int main(void) {
if (mqtt_err != ERR_OK) {
printf("MQTT connect start failed: %d\n", mqtt_err);
}
i2c_init(i2c_default, 400 * 1000); // start i2c0 at 400khz
i2c_init(i2c_default, 100 * 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);
@ -148,22 +157,18 @@ int main(void) {
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN,
GPIO_FUNC_I2C));
i2c_init(i2c1,
100 * 1000); // start i2c1 at 100kHz -- this is the stemma chain
gpio_set_function(I2C1_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(I2C1_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(I2C1_SDA_PIN);
gpio_pull_up(I2C1_SCL_PIN);
bi_decl(bi_2pins_with_func(I2C1_SDA_PIN, I2C1_SCL_PIN, GPIO_FUNC_I2C));
initBMP(i2c1);
activateENS(i2c_default);
initBMP(i2c_default);
initOPT(i2c_default);
printf("\x1b[2J"); // clear screen
uint8_t i = 0;
uint8_t sample_count = 0;
activateENS(i2c_default);
while (1) {
// cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
getOPTData(i2c_default, &lightch0, &lightch1, &lightch2);
getBMPData(i2c_default, &bmpT, &bmpP);
getAHTData(i2c_default, &t, &h);
getBMPData(i2c1, &bmpT, &bmpP);
lightData = calculate_color_data(lightch0, lightch1, lightch2);
t_avg[i] = t;
h_avg[i] = h;
bmpt_avg[i] = bmpT;
@ -178,6 +183,8 @@ int main(void) {
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 / 1000.0);
printf("Light: CIE Coords: %0.2fX %0.2fY %0.2fZ %0.2fLux\n", lightData.x,
lightData.y, lightData.z, lightData.lux);
validData =
getENSData(i2c_default, &avg_bmp_t, &avg_h, &aqi, &tvoc, &eco2, &etoh);
tvoc_avg[i] = tvoc;
@ -186,6 +193,9 @@ int main(void) {
avg_tvoc = average_uint16(tvoc_avg, sample_count);
avg_eco2 = average_uint16(eco2_avg, sample_count);
avg_etoh = average_uint16(etoh_avg, sample_count);
snprintf(payload, sizeof(payload), "%d", validData);
ensaht_mqtt_publish_client(&mqtt, valid_topic, payload, strlen(payload),
NULL, NULL);
if (!validData) {
printf("!! ");
}

View file

@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2026 A.M. Rowsell <amr@frzn.dev>
#include "include/opt4048.h"
#include <hardware/i2c.h>
OPT4048_Data calculate_color_data(float ch0, float ch1, float ch2) {
OPT4048_Data result;
@ -36,10 +37,9 @@ int initOPT(i2c_inst_t *i2c) {
// Need to init regs as follows:
// write setup to CONFIG (0x0A/0x0B)
// this sets it to 100ms sample time, auto-range lux
static const uint8_t config[5] = {0x0A, 0b00110010, 0b00001000, 0b10000000,
0b00011101};
static const uint8_t config[5] = {0x0A, 0x32, 0x08, 0x80, 0x1D};
// we'll be doing single-shot measurements
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, config, 4, false);
bytesWritten = i2c_write_timeout_us(i2c, OPT_ADDR, config, 5, false, 300);
result = (bytesWritten == 4) ? 0 : 1;
return result;
}
@ -54,20 +54,21 @@ int getOPTData(i2c_inst_t *i2c, float *ch0, float *ch1, float *ch2) {
uint8_t exponentCH0 = 0;
uint8_t exponentCH1 = 0;
uint8_t exponentCH2 = 0;
static const uint8_t triggerMeas[2] = {0x0B, 0b00101000};
static const uint8_t triggerMeas[3] = {0x0B, 0x80, 0x28};
static const uint8_t dataReg = 0x00;
// force a one-shot measurement
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, triggerMeas, 2, false);
bytesWritten = i2c_write_timeout_us(i2c, OPT_ADDR, triggerMeas, 3, false,
1000); // 1ms timeout
if (bytesWritten != 2) {
result = 1;
}
sleep_ms(410); // 4 channels @ 100ms each plus a little buffer time
sleep_ms(500); // 4 channels @ 100ms each plus a little buffer time
bytesWritten = i2c_write_blocking(i2c, OPT_ADDR, &dataReg, 1, true);
bytesWritten = i2c_write_timeout_us(i2c, OPT_ADDR, &dataReg, 1, true, 1000);
if (bytesWritten != 1) {
result = 1;
}
bytesRead = i2c_read_blocking(i2c, OPT_ADDR, lightData, 16, false);
bytesRead = i2c_read_timeout_us(i2c, OPT_ADDR, lightData, 16, false, 2000);
if (bytesRead != 16) {
result = 1;
}