Compare commits
2 commits
914b76ba8b
...
1ba2d96180
| Author | SHA1 | Date | |
|---|---|---|---|
|
1ba2d96180 |
|||
|
f894b2abfe |
4 changed files with 43 additions and 30 deletions
|
|
@ -9,8 +9,8 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
# (note this can come from environment, CMake cache etc)
|
# (note this can come from environment, CMake cache etc)
|
||||||
set(PICO_SDK_PATH "/home/amr/workspace/rp2040/pico-sdk")
|
set(PICO_SDK_PATH "/home/amr/workspace/rp2040/pico-sdk")
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
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)
|
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||||
include(pico_sdk_import.cmake)
|
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}")
|
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
|
||||||
endif()
|
endif()
|
||||||
# Initialise the Raspberry Pi Pico SDK
|
# Initialise the Raspberry Pi Pico SDK
|
||||||
pico_sdk_init()
|
|
||||||
|
|
||||||
project(ensaht C CXX ASM)
|
project(ensaht C CXX ASM)
|
||||||
|
|
||||||
|
pico_sdk_init()
|
||||||
|
|
||||||
# Add executable. Default name is the project name, version 0.1
|
# Add executable. Default name is the project name, version 0.1
|
||||||
|
|
||||||
add_executable(ensaht
|
add_executable(ensaht
|
||||||
|
|
@ -39,6 +40,7 @@ target_include_directories(ensaht PRIVATE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/include
|
${CMAKE_CURRENT_LIST_DIR}/include
|
||||||
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
|
${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_name(ensaht "ensaht")
|
||||||
pico_set_program_version(ensaht "0.1")
|
pico_set_program_version(ensaht "0.1")
|
||||||
pico_enable_stdio_usb(ensaht 1)
|
pico_enable_stdio_usb(ensaht 1)
|
||||||
|
|
@ -60,7 +62,7 @@ pico_add_extra_outputs(ensaht)
|
||||||
add_custom_target(flash
|
add_custom_target(flash
|
||||||
COMMAND openocd
|
COMMAND openocd
|
||||||
-f interface/cmsis-dap.cfg
|
-f interface/cmsis-dap.cfg
|
||||||
-f target/rp2040.cfg
|
-f target/rp2350.cfg
|
||||||
-c "adapter speed 10000"
|
-c "adapter speed 10000"
|
||||||
-c "program ${CMAKE_CURRENT_BINARY_DIR}/ensaht.elf verify"
|
-c "program ${CMAKE_CURRENT_BINARY_DIR}/ensaht.elf verify"
|
||||||
-c "reset init"
|
-c "reset init"
|
||||||
|
|
@ -69,7 +71,7 @@ add_custom_target(flash
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(debug
|
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
|
DEPENDS flash
|
||||||
USES_TERMINAL
|
USES_TERMINAL
|
||||||
VERBATIM
|
VERBATIM
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ void getAHTData(i2c_inst_t *i2c, double *t, double *h) {
|
||||||
uint32_t temperature;
|
uint32_t temperature;
|
||||||
uint32_t humidity;
|
uint32_t humidity;
|
||||||
|
|
||||||
i2c_write_blocking(i2c, AHT_ADDR, AHT_MEASURE, 3,
|
i2c_write_timeout_us(i2c, AHT_ADDR, AHT_MEASURE, 3, false,
|
||||||
false); // trigger measurement
|
1200); // trigger measurement
|
||||||
// now we must delay ~100ms
|
// now we must delay ~100ms
|
||||||
sleep_ms(100);
|
sleep_ms(100);
|
||||||
i2c_read_blocking(i2c, AHT_ADDR, result, 6,
|
i2c_read_timeout_us(i2c, AHT_ADDR, result, 6, false,
|
||||||
false); // read 6 bytes back
|
3000); // read 6 bytes back
|
||||||
humidity = (result[1] << 12) | (result[2] << 4) | (result[3] & 0xF0) >> 4;
|
humidity = (result[1] << 12) | (result[2] << 4) | (result[3] & 0xF0) >> 4;
|
||||||
temperature = (result[3] & 0x0F) << 16 | (result[4] << 8) | result[5];
|
temperature = (result[3] & 0x0F) << 16 | (result[4] << 8) | result[5];
|
||||||
*t = (((double)temperature / 1048576.0f) * 200.0f) - 50.0f;
|
*t = (((double)temperature / 1048576.0f) * 200.0f) - 50.0f;
|
||||||
|
|
|
||||||
36
src/main.c
36
src/main.c
|
|
@ -18,8 +18,6 @@
|
||||||
* the readings to Adafruit IO over MQTT using the Pico W.
|
* 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/aht.h"
|
||||||
#include "include/bmp.h"
|
#include "include/bmp.h"
|
||||||
#include "include/credentials.h"
|
#include "include/credentials.h"
|
||||||
|
|
@ -29,6 +27,8 @@
|
||||||
#include "pico/cyw43_arch.h"
|
#include "pico/cyw43_arch.h"
|
||||||
#include "pico/stdlib.h" // IWYU pragma: keep
|
#include "pico/stdlib.h" // IWYU pragma: keep
|
||||||
#include <boards/pico_w.h>
|
#include <boards/pico_w.h>
|
||||||
|
#include <hardware/gpio.h>
|
||||||
|
#include <hardware/i2c.h>
|
||||||
#include <hardware/structs/io_bank0.h>
|
#include <hardware/structs/io_bank0.h>
|
||||||
#include <pico/binary_info/code.h>
|
#include <pico/binary_info/code.h>
|
||||||
#include <pico/double.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 etoh_topic[] = ADAFRUIT_IO_USERNAME "/feeds/ensaht.etoh";
|
||||||
static const char eco2_topic[] = ADAFRUIT_IO_USERNAME "/feeds/ensaht.eco2";
|
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 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;
|
uint16_t tvoc, eco2, etoh, avg_tvoc, avg_eco2, avg_etoh;
|
||||||
uint8_t aqi, validData;
|
uint8_t aqi, validData;
|
||||||
double t, h, avg_t, avg_h, avg_bmp_t, avg_bmp_p;
|
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) {
|
if (mqtt_err != ERR_OK) {
|
||||||
printf("MQTT connect start failed: %d\n", mqtt_err);
|
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_SCL_PIN, GPIO_FUNC_I2C);
|
||||||
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
|
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
|
||||||
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
|
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,
|
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN,
|
||||||
GPIO_FUNC_I2C));
|
GPIO_FUNC_I2C));
|
||||||
|
|
||||||
i2c_init(i2c1,
|
activateENS(i2c_default);
|
||||||
100 * 1000); // start i2c1 at 100kHz -- this is the stemma chain
|
initBMP(i2c_default);
|
||||||
gpio_set_function(I2C1_SDA_PIN, GPIO_FUNC_I2C);
|
initOPT(i2c_default);
|
||||||
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);
|
|
||||||
printf("\x1b[2J"); // clear screen
|
printf("\x1b[2J"); // clear screen
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
uint8_t sample_count = 0;
|
uint8_t sample_count = 0;
|
||||||
activateENS(i2c_default);
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 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);
|
getAHTData(i2c_default, &t, &h);
|
||||||
getBMPData(i2c1, &bmpT, &bmpP);
|
lightData = calculate_color_data(lightch0, lightch1, lightch2);
|
||||||
t_avg[i] = t;
|
t_avg[i] = t;
|
||||||
h_avg[i] = h;
|
h_avg[i] = h;
|
||||||
bmpt_avg[i] = bmpT;
|
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("\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,
|
printf("BMP Temperature %0.2f C Pressure %0.2f kPa\n", avg_bmp_t,
|
||||||
avg_bmp_p / 1000.0);
|
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 =
|
validData =
|
||||||
getENSData(i2c_default, &avg_bmp_t, &avg_h, &aqi, &tvoc, &eco2, &etoh);
|
getENSData(i2c_default, &avg_bmp_t, &avg_h, &aqi, &tvoc, &eco2, &etoh);
|
||||||
tvoc_avg[i] = tvoc;
|
tvoc_avg[i] = tvoc;
|
||||||
|
|
@ -186,6 +193,9 @@ int main(void) {
|
||||||
avg_tvoc = average_uint16(tvoc_avg, sample_count);
|
avg_tvoc = average_uint16(tvoc_avg, sample_count);
|
||||||
avg_eco2 = average_uint16(eco2_avg, sample_count);
|
avg_eco2 = average_uint16(eco2_avg, sample_count);
|
||||||
avg_etoh = average_uint16(etoh_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) {
|
if (!validData) {
|
||||||
printf("!! ");
|
printf("!! ");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-FileCopyrightText: 2026 A.M. Rowsell <amr@frzn.dev>
|
// SPDX-FileCopyrightText: 2026 A.M. Rowsell <amr@frzn.dev>
|
||||||
|
|
||||||
#include "include/opt4048.h"
|
#include "include/opt4048.h"
|
||||||
|
#include <hardware/i2c.h>
|
||||||
|
|
||||||
OPT4048_Data calculate_color_data(float ch0, float ch1, float ch2) {
|
OPT4048_Data calculate_color_data(float ch0, float ch1, float ch2) {
|
||||||
OPT4048_Data result;
|
OPT4048_Data result;
|
||||||
|
|
@ -36,10 +37,9 @@ int initOPT(i2c_inst_t *i2c) {
|
||||||
// Need to init regs as follows:
|
// Need to init regs as follows:
|
||||||
// write setup to CONFIG (0x0A/0x0B)
|
// write setup to CONFIG (0x0A/0x0B)
|
||||||
// this sets it to 100ms sample time, auto-range lux
|
// this sets it to 100ms sample time, auto-range lux
|
||||||
static const uint8_t config[5] = {0x0A, 0b00110010, 0b00001000, 0b10000000,
|
static const uint8_t config[5] = {0x0A, 0x32, 0x08, 0x80, 0x1D};
|
||||||
0b00011101};
|
|
||||||
// we'll be doing single-shot measurements
|
// 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;
|
result = (bytesWritten == 4) ? 0 : 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -54,20 +54,21 @@ int getOPTData(i2c_inst_t *i2c, float *ch0, float *ch1, float *ch2) {
|
||||||
uint8_t exponentCH0 = 0;
|
uint8_t exponentCH0 = 0;
|
||||||
uint8_t exponentCH1 = 0;
|
uint8_t exponentCH1 = 0;
|
||||||
uint8_t exponentCH2 = 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;
|
static const uint8_t dataReg = 0x00;
|
||||||
// force a one-shot measurement
|
// 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) {
|
if (bytesWritten != 2) {
|
||||||
result = 1;
|
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) {
|
if (bytesWritten != 1) {
|
||||||
result = 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) {
|
if (bytesRead != 16) {
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue