From b5b10dad80ea102e094f797c5c75c2b18d3777af Mon Sep 17 00:00:00 2001 From: Mikael Nousiainen Date: Tue, 11 Apr 2023 17:12:30 +0300 Subject: [PATCH] Add support for RadSens I2C radiation sensor. Improve BMP280 sensor configuration. --- README.md | 5 +- src/CMakeLists.txt | 11 +- src/bmp280_handler.c | 2 +- src/codecs/horus/horus_packet_v2.c | 17 +- src/config.c | 12 +- src/config.h | 12 ++ src/config_internal.h | 1 + src/drivers/pulse_counter/pulse_counter.h | 5 + src/drivers/radsens/radsens.cpp | 212 ++++++++++++++++++++++ src/drivers/radsens/radsens.h | 103 +++++++++++ src/drivers/si4032/si4032.h | 2 +- src/main.c | 12 ++ src/radio.c | 2 + src/radsens_handler.cpp | 175 ++++++++++++++++++ src/radsens_handler.h | 19 ++ src/telemetry.c | 5 + src/telemetry.h | 1 + src/template.c | 4 + 18 files changed, 588 insertions(+), 12 deletions(-) create mode 100644 src/drivers/radsens/radsens.cpp create mode 100644 src/drivers/radsens/radsens.h create mode 100644 src/radsens_handler.cpp create mode 100644 src/radsens_handler.h diff --git a/README.md b/README.md index 91a3a43..ea29cb2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ **NOTE:** This firmware is a work in progress and some features might not work as expected yet! This is a custom, amateur radio-oriented firmware for [Vaisala RS41 radiosondes](https://www.vaisala.com/en/products/instruments-sensors-and-other-measurement-devices/soundings-products/rs41). -Some of the code is based on an earlier RS41 firmware project called [RS41HUP](https://github.com/df8oe/RS41HUP), +Some code is based on an earlier RS41 firmware project called [RS41HUP](https://github.com/df8oe/RS41HUP), but most of it has been rewritten from scratch. The Horus 4FSK code has been adapted from the [darksidelemm fork of RS41HUP](https://github.com/darksidelemm/RS41HUP). @@ -109,6 +109,9 @@ The following sensors are currently supported: * Bosch BMP280/BME280 barometric pressure / temperature / humidity sensor * Note that only BME280 sensors will report humidity. For BMP280 humidity readings will be zero. +* RadSens universal dosimeter-radiometer module for measuring radiation + * https://www.tindie.com/stores/climateguard/ + * https://github.com/climateguard/RadSens Sensor driver code contributions are welcome! diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81d62e3..32ec00b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,14 @@ project(RS41ng C CXX) +set(CMAKE_FIND_ROOT_PATH /usr/arm-none-eabi) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(COLLECT_GCC ${TOOLCHAIN_PATH}/arm-none-eabi-gcc) + if (UNIX) set(TOOLCHAIN_PATH /usr/bin) set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/arm-none-eabi-gcc) @@ -19,7 +28,7 @@ add_definitions(-DSUPPORT_CPLUSPLUS) add_definitions(-D__ASSEMBLY__) SET(LINKER_SCRIPT arm-gcc-link.ld) -SET(COMMON_FLAGS " -mcpu=cortex-m3 -mthumb -Wall -ffunction-sections -fdata-sections -g -O3 -nostartfiles") +SET(COMMON_FLAGS " -mcpu=cortex-m3 -mthumb -Wall -ffunction-sections -fdata-sections -O3 -nostartfiles") SET(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=c++11") SET(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu99") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=${CMAKE_BINARY_DIR}/${PROJECT_NAME}.map -lstdc++ -O3 -mcpu=cortex-m3 -mthumb -Wl,--gc-sections --specs=nano.specs -T ${LINKER_SCRIPT}") diff --git a/src/bmp280_handler.c b/src/bmp280_handler.c index d4bc824..02693b7 100644 --- a/src/bmp280_handler.c +++ b/src/bmp280_handler.c @@ -9,7 +9,7 @@ static bool bmp280_initialization_required = true; bool bmp280_handler_init() { bmp280_dev.port = &DEFAULT_I2C_PORT; - bmp280_dev.addr = BMP280_I2C_ADDRESS_1; + bmp280_dev.addr = SENSOR_BMP280_I2C_ADDRESS; bmp280_params_t bmp280_params = { .mode = BMP280_MODE_NORMAL, diff --git a/src/codecs/horus/horus_packet_v2.c b/src/codecs/horus/horus_packet_v2.c index 01c3bda..b267be2 100644 --- a/src/codecs/horus/horus_packet_v2.c +++ b/src/codecs/horus/horus_packet_v2.c @@ -49,10 +49,17 @@ size_t horus_packet_v2_create(uint8_t *payload, size_t length, telemetry_data *d uint8_t *custom_data_pointer = horus_packet.CustomData; - // Unit: cm/s - int16_t gps_climb_cm_per_second = (int16_t) gps_data->climb_cm_per_second; - memcpy(custom_data_pointer, &gps_climb_cm_per_second, sizeof(gps_climb_cm_per_second)); - custom_data_pointer += sizeof(gps_climb_cm_per_second); + if (radsens_enabled) { + // Unit: µR/h + uint16_t ext_radiation_intensity_uR_h = (uint16_t) data->radiation_intensity_uR_h; + memcpy(custom_data_pointer, &ext_radiation_intensity_uR_h, sizeof(ext_radiation_intensity_uR_h)); + custom_data_pointer += sizeof(ext_radiation_intensity_uR_h); + } else { + // Unit: cm/s + int16_t gps_climb_cm_per_second = (int16_t) gps_data->climb_cm_per_second; + memcpy(custom_data_pointer, &gps_climb_cm_per_second, sizeof(gps_climb_cm_per_second)); + custom_data_pointer += sizeof(gps_climb_cm_per_second); + } // Unit: Celsius * 10 int16_t ext_temp_celsius_10 = (int16_t) (data->temperature_celsius_100 / 10.0f); @@ -68,7 +75,7 @@ size_t horus_packet_v2_create(uint8_t *payload, size_t length, telemetry_data *d uint16_t ext_pressure_mbar = (uint16_t) (data->pressure_mbar_100 / 10.0f); memcpy(custom_data_pointer, &ext_pressure_mbar, sizeof(ext_pressure_mbar)); - if (pulse_counter_enabled) { + if (pulse_counter_enabled || radsens_enabled) { // Unit: pulse count custom_data_pointer += sizeof(ext_pressure_mbar); uint16_t ext_pulse_count = (uint16_t) data->pulse_count; diff --git a/src/config.c b/src/config.c index 4a95ffe..78d21e3 100644 --- a/src/config.c +++ b/src/config.c @@ -26,6 +26,7 @@ * $cl - Climb in m/s (up to 2 chars) * $he - Heading in degrees (up to 3 chars) * $pc - Pulse counter value (wraps to zero at 65535, 16-bit unsigned value) + * $ri - Radiation intensity in µR/h (up to 5 chars) * * Allowed message lengths: * @@ -43,6 +44,7 @@ bool leds_enabled = LEDS_ENABLE; bool bmp280_enabled = SENSOR_BMP280_ENABLE; +bool radsens_enabled = SENSOR_RADSENS_ENABLE; bool si5351_enabled = RADIO_SI5351_ENABLE; bool gps_nmea_output_enabled = GPS_NMEA_OUTPUT_VIA_SERIAL_PORT_ENABLE; bool pulse_counter_enabled = PULSE_COUNTER_ENABLE; @@ -54,7 +56,10 @@ volatile bool system_initialized = false; * Maximum length: 64 characters. */ char *cw_message_templates[] = { - "$cs $loc6 $altm $gs km/h $tiC", +// "$cs $loc6 $altm $gs km/h $tiC", +// "$cs $loc6", +// "$alt m", +// "$gs km/h $ti C", NULL }; @@ -76,7 +81,8 @@ char *aprs_comment_templates[] = { // " B$bu $teC $hu% $prmb $hh:$mm:$ss @ $tow ms - " APRS_COMMENT, // " B$bu $teC $hu% $prmb - " APRS_COMMENT, // " B$bu $loc12 $hh:$mm:$ss - " APRS_COMMENT, - " $loc12 - " APRS_COMMENT, +// " $loc12 - " APRS_COMMENT, +// " $teC $hu% $prmb PC $pc RI $ri uR/h - " APRS_COMMENT, // " " APRS_COMMENT, NULL }; @@ -86,7 +92,7 @@ char *aprs_comment_templates[] = { * Maximum length: 130 characters. */ char *fsq_comment_templates[] = { - "TEST $loc6 $altm $tiC", +// "TEST $loc6 $altm $tiC", // " $lat $lon, $alt m, $cl m/s, $gs km/h, $he deg - " FSQ_COMMENT, // " $loc12, $teC $hu% $prmb $hh:$mm:$ss @ $tow ms - " FSQ_COMMENT, NULL diff --git a/src/config.h b/src/config.h index ea16cc0..4ed60fb 100644 --- a/src/config.h +++ b/src/config.h @@ -32,6 +32,18 @@ // Enable use of an externally connected I²C BMP280/BME280 atmospheric sensor // NOTE: Only BME280 sensors will report humidity. For BMP280 humidity readings will be zero. #define SENSOR_BMP280_ENABLE false +// BMP280/BME280 I²C device address is usually 0x76 or 0x77. +#define SENSOR_BMP280_I2C_ADDRESS 0x77 + +// Enable use of an externally connected I²C RadSens radiation sensor +#define SENSOR_RADSENS_ENABLE false +// Expected RadSens chip ID to verify initialization of the sensor, default is 0x7D. +#define SENSOR_RADSENS_CHIP_ID 0x7D +// RadSens I²C device address, default is 0x66. +#define SENSOR_RADSENS_I2C_ADDRESS 0x66 +// Uncomment to set RadSens sensor sensitivity (imp/MKR). The default value is 105 imp/MKR. +// The value is stored in the non-volatile memory of the microcontroller. +#define SENSOR_RADSENS_SENSITIVITY 105 // Enable use of an externally connected I²C Si5351 clock generator chip for HF radio transmissions #define RADIO_SI5351_ENABLE false diff --git a/src/config_internal.h b/src/config_internal.h index 71e8a87..3c9ccb0 100644 --- a/src/config_internal.h +++ b/src/config_internal.h @@ -18,6 +18,7 @@ extern bool leds_enabled; extern bool gps_nmea_output_enabled; extern bool bmp280_enabled; +extern bool radsens_enabled; extern bool si5351_enabled; extern bool pulse_counter_enabled; diff --git a/src/drivers/pulse_counter/pulse_counter.h b/src/drivers/pulse_counter/pulse_counter.h index 92a7578..c1a0f85 100644 --- a/src/drivers/pulse_counter/pulse_counter.h +++ b/src/drivers/pulse_counter/pulse_counter.h @@ -1,5 +1,10 @@ +#ifndef __PULSE_COUNTER_H +#define __PULSE_COUNTER_H + #include #include void pulse_counter_init(int pin_mode, int edge); uint16_t pulse_counter_get_count(); + +#endif diff --git a/src/drivers/radsens/radsens.cpp b/src/drivers/radsens/radsens.cpp new file mode 100644 index 0000000..374b9df --- /dev/null +++ b/src/drivers/radsens/radsens.cpp @@ -0,0 +1,212 @@ +/** + * RadSens - universal dosimeter-radiometer module + * + * Driver code adapted from https://github.com/climateguard/RadSens + * Original license GPL 3.0. + */ + +#include "radsens.h" +#include "../../hal/delay.h" + +RadSens::RadSens(i2c_port *port, uint8_t sensor_address) +{ + _port = port; + _sensor_address = sensor_address; +} + +RadSens::~RadSens() +{ +} + +/** + * Initialization function and sensor connection. Returns false if the sensor is not connected to the I2C bus. + */ +bool RadSens::init() +{ + uint8_t res[2]; + if (!i2c_read(RS_REG_DEVICE_ID, res, 2)) { + return false; + } + _chip_id = res[0]; + _firmware_ver = res[1]; + updatePulses(); + return true; +} + +/** + * Get chip id, default value: 0x7D. + */ +uint8_t RadSens::getChipId() +{ + return _chip_id; +} + +/** + * Get firmware version. + */ +uint8_t RadSens::getFirmwareVersion() +{ + return _firmware_ver; +} + +/** + * Get radiation intensity (dynamic period T < 123 sec). + */ +float RadSens::getRadIntensityDynamic() +{ + // It seems any I²C command will reset the pulse counter, so it must be read first + updatePulses(); + uint8_t res[3]; + if (!i2c_read(RS_REG_RAD_INTENSITY_DYNAMIC, res, 3)) { + return -1; + } + return (((uint32_t) res[0] << 16) | ((uint16_t) res[1] << 8) | res[2]) / 10.0; +} + +/** + * Get radiation intensity (static period T = 500 sec). + */ +float RadSens::getRadIntensityStatic() +{ + // It seems any I²C command will reset the pulse counter, so it must be read first + updatePulses(); + uint8_t res[3]; + if (!i2c_read(RS_REG_RAD_INTENSITY_STATIC, res, 3)) { + return -1; + } + return (((uint32_t) res[0] << 16) | ((uint16_t) res[1] << 8) | res[2]) / 10.0; +} + +bool RadSens::updatePulses() +{ + uint8_t res[2]; + if (!i2c_read(RS_REG_PULSE_COUNTER, res, 2)) { + return false; + } + _pulse_count += (res[0] << 8) | res[1]; + return true; +} + +/** + * Get the accumulated number of pulses registered by the module since the last I2C data reading. + */ +int32_t RadSens::getNumberOfPulses() +{ + if (!updatePulses()) { + return -1; + } + return _pulse_count; +} + +/** + * Get sensor address. + */ +uint8_t RadSens::getSensorAddress() +{ + uint8_t res; + if (!i2c_read(RS_REG_DEVICE_ADDRESS, &res, 1)) { + return 0; + } + _sensor_address = res; + return _sensor_address; +} + +/** + * Get state of high-voltage voltage Converter. + */ +bool RadSens::getHVGeneratorState() +{ + uint8_t res; + if (!i2c_read(RS_REG_HV_GENERATOR, &res, 1)) { + return false; + } + return res == 1; +} + +/** + * Get the value coefficient used for calculating the radiation intensity. + */ +int16_t RadSens::getSensitivity() +{ + uint8_t res[2]; + if (!i2c_read(RS_REG_SENSITIVITY, res, 2)) { + return -1; + } + return res[1] * 256 + res[0]; +} + +/** + * Control register for a high-voltage voltage Converter. By default, it is in the enabled state. + * To enable the HV generator, write 1 to the register, and 0 to disable it. If you try to write other + * values, the command is ignored. + * @param state true - generator on / false - generator off + */ +bool RadSens::setHVGeneratorState(bool state) +{ + return i2c_write(RS_REG_HV_GENERATOR, state ? 1 : 0); +} + +/** + * Contains the value coefficient used for calculating the radiation intensity. + * If necessary (for example, when installing a different type of counter), the necessary sensitivity value in + * Imp / uR is entered in the register. The default value is 105 Imp / uR. At the end of + * recording, the new value is stored in the non-volatile memory of the microcontroller. + * @param sens sensitivity coefficient in Impulse / uR + */ +bool RadSens::setSensitivity(uint16_t sens) +{ + if (!i2c_write(RS_REG_SENSITIVITY, (uint8_t)(sens & 0xFF))) { + return false; + } + delay_ms(15); + + if (!i2c_write(RS_REG_SENSITIVITY + 1, (uint8_t)(sens >> 8))) { + return false; + } + delay_ms(15); + + return true; +} + +/** + * Control register for an indication diode. By default, it is in the enabled state. To enable the indication, + * write 1 to the register, and 0 to disable it. If you try to write other values, the command is ignored. + * @param state true - diode on / false - diode off + */ +bool RadSens::setLedState(bool state) +{ + bool result = i2c_write(RS_REG_LED_CONTROL, state ? 1 : 0); + delay_ms(15); + return result; +} + +/*Get state of led indication.*/ +bool RadSens::getLedState() +{ + uint8_t res; + if (!i2c_read(RS_REG_LED_CONTROL, &res, 1)) { + return false; + } + return res == 1; +} + +/** + * Read block of data + * @param reg - address of starting register + * @param dest - destination array + * @param num - number of bytes to read + */ +bool RadSens::i2c_read(uint8_t reg, uint8_t *dest, uint8_t num) +{ + return i2c_read_bytes(_port, _sensor_address, reg, num, dest) == HAL_OK; +} + +/** + * Write a byte of data + * @param reg - address of starting register + * @param data - byte of data to write + */ +bool RadSens::i2c_write(uint8_t reg, uint8_t data) +{ + return i2c_write_byte(_port, _sensor_address, reg, data) == HAL_OK; +} diff --git a/src/drivers/radsens/radsens.h b/src/drivers/radsens/radsens.h new file mode 100644 index 0000000..ae9cd6b --- /dev/null +++ b/src/drivers/radsens/radsens.h @@ -0,0 +1,103 @@ +/** + * RadSens - universal dosimeter-radiometer module + * + * Driver code adapted from https://github.com/climateguard/RadSens + * Original license GPL 3.0. + */ + +#ifndef __RADSENS_H +#define __RADSENS_H + +#include + +#include "hal/i2c.h" + +#define RS_REG_COUNT 21 + +// Default RadSens I2C device address +#define RS_DEFAULT_I2C_ADDRESS 0x66 + +// Device id, default value: 0x7D +// Size: 8 bit +#define RS_REG_DEVICE_ID 0x00 + +// Firmware version +// Size: 8 bit +#define RS_REG_FIRMWARE_VER 0x01 + +// Radiation intensity (dynamic period T < 123 sec) +// Size: 24 bit +#define RS_REG_RAD_INTENSITY_DYNAMIC 0x03 + +// Radiation intensity (static period T = 500 sec) +// Size: 24 bit +#define RS_REG_RAD_INTENSITY_STATIC 0x06 + +// Contains the accumulated number of pulses registered by the module since the last I2C data reading. +// The value is reset each time it is read. Allows you to process directly the pulses from the Geiger counter +// and implement other algorithms. The value is updated when each pulse is registered. +// Size: 16 bit +#define RS_REG_PULSE_COUNTER 0x09 + +// This register is used to change the device address when multiple devices need to be connected +// to the same line at the same time. By default, it contains the value 0x66. At the end of recording, the new +// value is stored in the non-volatile memory of the microcontroller. +// Size: 8 bit +// Access: R/W +#define RS_REG_DEVICE_ADDRESS 0x10 + +// Control register for a high-voltage voltage Converter. By default, it is in the enabled state. +// To enable the HV generator, write 1 to the register, and 0 to disable it. If you try to write other +// values, the command is ignored. +// Size: 8 bit +// Access: R/W +#define RS_REG_HV_GENERATOR 0x11 + +// Contains the value coefficient used for calculating the radiation intensity. +// If necessary (for example, when installing a different type of counter), the necessary sensitivity value in +// imp/MKR is entered in the register. The default value is 105 imp/MKR. At the end of +// recording, the new value is stored in the non-volatile memory of the microcontroller. +// Size: 16 bit +// Access: R/W +#define RS_REG_SENSITIVITY 0x12 + +// Control register for an indication diode. By default, it is in the enabled state. To enable the indication, +// write 1 to the register, and 0 to disable it. If you try to write other values, the command is ignored. +// Size: 8 bit +// Access: R/W +#define RS_REG_LED_CONTROL 0x14 + +class RadSens { +private: + i2c_port *_port; + uint8_t _sensor_address; + uint8_t _chip_id = 0; + uint8_t _firmware_ver = 0; + uint32_t _pulse_count = 0; + + bool i2c_read(uint8_t addr, uint8_t *dest, uint8_t num); + bool i2c_write(uint8_t reg, uint8_t data); + + bool updatePulses(); + +public: + RadSens(i2c_port *port, uint8_t sensor_address); + + ~RadSens(); + + bool init(); + uint8_t getChipId(); + uint8_t getFirmwareVersion(); + float getRadIntensityDynamic(); + float getRadIntensityStatic(); + int32_t getNumberOfPulses(); + uint8_t getSensorAddress(); + bool getHVGeneratorState(); + bool getLedState(); + int16_t getSensitivity(); + bool setHVGeneratorState(bool state); + bool setSensitivity(uint16_t sens); + bool setLedState(bool state); +}; + +#endif diff --git a/src/drivers/si4032/si4032.h b/src/drivers/si4032/si4032.h index f26b054..ca9de65 100644 --- a/src/drivers/si4032/si4032.h +++ b/src/drivers/si4032/si4032.h @@ -1,5 +1,5 @@ #ifndef __SI4032_H -#define __SI4032_h +#define __SI4032_H #include #include diff --git a/src/main.c b/src/main.c index bfadb5a..988a3ad 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include "drivers/si4032/si4032.h" #include "drivers/pulse_counter/pulse_counter.h" #include "bmp280_handler.h" +#include "radsens_handler.h" #include "si5351_handler.h" #include "radio.h" #include "config.h" @@ -118,6 +119,17 @@ int main(void) } } + if (radsens_enabled) { + for (int i = 0; i < 3; i++) { + log_info("RadSens init\n"); + success = radsens_handler_init(); + if (success) { + break; + } + log_error("RadSens init failed, retrying..."); + } + } + if (si5351_enabled) { for (int i = 0; i < 3; i++) { log_info("Si5351 init\n"); diff --git a/src/radio.c b/src/radio.c index 87c2d9d..af30d6a 100644 --- a/src/radio.c +++ b/src/radio.c @@ -849,6 +849,8 @@ void radio_init() memset(¤t_telemetry_data, 0, sizeof(current_telemetry_data)); + telemetry_collect(¤t_telemetry_data); + for (uint8_t i = 0; i < radio_transmit_entry_count; i++) { radio_transmit_entry *entry = &radio_transmit_schedule[i]; switch (entry->data_mode) { diff --git a/src/radsens_handler.cpp b/src/radsens_handler.cpp new file mode 100644 index 0000000..008312d --- /dev/null +++ b/src/radsens_handler.cpp @@ -0,0 +1,175 @@ +#include +#include "drivers/radsens/radsens.h" +#include "radsens_handler.h" +#include "hal/delay.h" +#include "log.h" + +RadSens *radsens = NULL; + +static bool radsens_initialization_required = true; + +static bool radsens_handler_init_sensor(); + +bool radsens_handler_init() +{ + if (radsens == NULL) { + radsens = new RadSens(&DEFAULT_I2C_PORT, SENSOR_RADSENS_I2C_ADDRESS); + } + return radsens_handler_init_sensor(); +} + +static bool radsens_handler_init_sensor() +{ + uint16_t sensitivity; + + bool success = radsens->init(); + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens init failed\n"); + return false; + } + + success = radsens->getChipId() == SENSOR_RADSENS_CHIP_ID; + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens invalid chip ID\n"); + return false; + } + + sensitivity = radsens->getSensitivity(); + success = sensitivity > 0; + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens get sensitivity failed\n"); + return false; + } + log_info("RadSens initial sensitivity: %d\n", sensitivity); + + // Give the sensor some time to start up + delay_ms(50); + + success = radsens->setLedState(true); + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens enable LED failed\n"); + return false; + } + + delay_ms(200); + +#if defined(SENSOR_RADSENS_SENSITIVITY) + success = radsens->setSensitivity(SENSOR_RADSENS_SENSITIVITY); + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens set sensitivity failed\n"); + return false; + } + + sensitivity = radsens->getSensitivity(); + success = sensitivity > 0; + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens get sensitivity failed\n"); + return false; + } + log_info("RadSens final sensitivity: %d\n", sensitivity); +#endif + + success = radsens->setHVGeneratorState(true); + radsens_initialization_required = !success; + if (!success) { + log_error("RadSens HV generator enable failed\n"); + return false; + } + + delay_ms(50); + + bool enabled = radsens->getHVGeneratorState(); + radsens_initialization_required = !enabled; + if (!enabled) { + log_error("RadSens HV generator is not enabled\n"); + return false; + } + + delay_ms(50); + + radsens->getNumberOfPulses(); + + return success; +} + +bool radsens_read(uint16_t *pulse_count, float *dynamic_intensity, float *static_intensity) +{ + float radiation_intensity_static; + float radiation_intensity_dynamic; + uint32_t radiation_pulse_counter; + + if (static_intensity) { + radiation_intensity_static = radsens->getRadIntensityStatic(); + if (radiation_intensity_static < 0) { + radsens_initialization_required = true; + log_error("Failed to read RadSens static radiation intensity\n"); + return false; + } + *static_intensity = radiation_intensity_static; + } + + if (dynamic_intensity) { + radiation_intensity_dynamic = radsens->getRadIntensityDynamic(); + if (radiation_intensity_dynamic < 0) { + radsens_initialization_required = true; + log_error("Failed to read RadSens dynamic radiation intensity\n"); + return false; + } + *dynamic_intensity = radiation_intensity_dynamic; + } + + if (pulse_count) { + radiation_pulse_counter = radsens->getNumberOfPulses(); + if (radiation_pulse_counter < 0) { + radsens_initialization_required = true; + log_error("Failed to read RadSens pulse counter\n"); + return false; + } + *pulse_count = (uint16_t) (radiation_pulse_counter % 0x10000); + } + + // log_info("PC: %d RI: %d\n", radiation_pulse_counter, (int) radiation_intensity_dynamic); + + return true; +} + +bool radsens_read_telemetry(telemetry_data *data) +{ + bool success; + + if (radsens_initialization_required) { + log_info("RadSens re-init\n"); + success = radsens_handler_init_sensor(); + log_info("RadSens re-init: %d\n", success); + if (!success) { + // Pulse counter does not need to be zeroed + data->radiation_intensity_uR_h = 0; + return false; + } + } + + success = radsens_read(&data->pulse_count, &data->radiation_intensity_uR_h, NULL); + + if (!success) { + log_info("RadSens re-init\n"); + success = radsens_handler_init_sensor(); + log_info("RadSens re-init: %d\n", success); + + if (success) { + success = radsens_read(&data->pulse_count, &data->radiation_intensity_uR_h, NULL); + } else { + // Pulse counter does not need to be zeroed + data->radiation_intensity_uR_h = 0; + } + } + + radsens_initialization_required = !success; + + return success; +} diff --git a/src/radsens_handler.h b/src/radsens_handler.h new file mode 100644 index 0000000..305ca97 --- /dev/null +++ b/src/radsens_handler.h @@ -0,0 +1,19 @@ +#ifndef __RADSENS_HANDLER_H +#define __RADSENS_HANDLER_H + +#include +#include "telemetry.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool radsens_handler_init(); +bool radsens_read(uint16_t *pulse_count, float *dynamic_intensity, float *static_intensity); +bool radsens_read_telemetry(telemetry_data *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/telemetry.c b/src/telemetry.c index 1179edb..fa382d0 100644 --- a/src/telemetry.c +++ b/src/telemetry.c @@ -4,6 +4,7 @@ #include "drivers/ubxg6010/ubxg6010.h" #include "drivers/pulse_counter/pulse_counter.h" #include "bmp280_handler.h" +#include "radsens_handler.h" #include "locator.h" #include "config.h" #include "log.h" @@ -20,6 +21,10 @@ void telemetry_collect(telemetry_data *data) bmp280_read_telemetry(data); } + if (radsens_enabled) { + radsens_read_telemetry(data); + } + if (pulse_counter_enabled) { data->pulse_count = pulse_counter_get_count(); } diff --git a/src/telemetry.h b/src/telemetry.h index 4a59f54..6e1a00a 100644 --- a/src/telemetry.h +++ b/src/telemetry.h @@ -16,6 +16,7 @@ typedef struct _telemetry_data { uint32_t pressure_mbar_100; uint32_t humidity_percentage_100; uint16_t pulse_count; + float radiation_intensity_uR_h; gps_data gps; diff --git a/src/template.c b/src/template.c index 93f4c92..e55c1db 100644 --- a/src/template.c +++ b/src/template.c @@ -106,6 +106,10 @@ size_t template_replace(char *dest, size_t dest_len, char *src, telemetry_data * strlcpy(temp, dest, dest_len); str_replace(dest, dest_len, temp, "$pc", replacement); + snprintf(replacement, sizeof(replacement), "%d", (int) data->radiation_intensity_uR_h); + strlcpy(temp, dest, dest_len); + str_replace(dest, dest_len, temp, "$ri", replacement); + free(temp); return len;