mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-23 17:13:38 +00:00
Support for the ClimateGuard RadSens Geiger-Muller tube (#5425)
This commit is contained in:
parent
4d69159e75
commit
932966b896
@ -148,6 +148,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define NAU7802_ADDR 0x2A
|
#define NAU7802_ADDR 0x2A
|
||||||
#define MAX30102_ADDR 0x57
|
#define MAX30102_ADDR 0x57
|
||||||
#define MLX90614_ADDR_DEF 0x5A
|
#define MLX90614_ADDR_DEF 0x5A
|
||||||
|
#define CGRADSENS_ADDR 0x66
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// ACCELEROMETER
|
// ACCELEROMETER
|
||||||
|
@ -63,7 +63,8 @@ class ScanI2C
|
|||||||
ICM20948,
|
ICM20948,
|
||||||
MAX30102,
|
MAX30102,
|
||||||
TPS65233,
|
TPS65233,
|
||||||
MPR121KB
|
MPR121KB,
|
||||||
|
CGRADSENS
|
||||||
} DeviceType;
|
} DeviceType;
|
||||||
|
|
||||||
// typedef uint8_t DeviceAddress;
|
// typedef uint8_t DeviceAddress;
|
||||||
|
@ -479,6 +479,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CGRADSENS_ADDR:
|
||||||
|
// Register 0x00 of the RadSens sensor contains is product identifier 0x7D
|
||||||
|
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
|
||||||
|
if (registerValue == 0x7D) {
|
||||||
|
type = CGRADSENS;
|
||||||
|
LOG_INFO("ClimateGuard RadSens Geiger-Muller Sensor found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
|
LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address);
|
||||||
}
|
}
|
||||||
|
@ -614,6 +614,7 @@ void setup()
|
|||||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
|
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
|
||||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
|
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948)
|
||||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
|
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102)
|
||||||
|
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS)
|
||||||
|
|
||||||
i2cScanner.reset();
|
i2cScanner.reset();
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "Sensor/BMP085Sensor.h"
|
#include "Sensor/BMP085Sensor.h"
|
||||||
#include "Sensor/BMP280Sensor.h"
|
#include "Sensor/BMP280Sensor.h"
|
||||||
#include "Sensor/BMP3XXSensor.h"
|
#include "Sensor/BMP3XXSensor.h"
|
||||||
|
#include "Sensor/CGRadSensSensor.h"
|
||||||
#include "Sensor/DFRobotLarkSensor.h"
|
#include "Sensor/DFRobotLarkSensor.h"
|
||||||
#include "Sensor/LPS22HBSensor.h"
|
#include "Sensor/LPS22HBSensor.h"
|
||||||
#include "Sensor/MCP9808Sensor.h"
|
#include "Sensor/MCP9808Sensor.h"
|
||||||
@ -60,6 +61,7 @@ BMP3XXSensor bmp3xxSensor;
|
|||||||
#ifdef T1000X_SENSOR_EN
|
#ifdef T1000X_SENSOR_EN
|
||||||
T1000xSensor t1000xSensor;
|
T1000xSensor t1000xSensor;
|
||||||
#endif
|
#endif
|
||||||
|
CGRadSensSensor cgRadSens;
|
||||||
|
|
||||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||||
@ -147,6 +149,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
result = nau7802Sensor.runOnce();
|
result = nau7802Sensor.runOnce();
|
||||||
if (max17048Sensor.hasSensor())
|
if (max17048Sensor.hasSensor())
|
||||||
result = max17048Sensor.runOnce();
|
result = max17048Sensor.runOnce();
|
||||||
|
if (cgRadSens.hasSensor())
|
||||||
|
result = cgRadSens.runOnce();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -210,16 +214,19 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
|||||||
// Display "Env. From: ..." on its own
|
// Display "Env. From: ..." on its own
|
||||||
display->drawString(x, y, "Env. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
display->drawString(x, y, "Env. From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||||
|
|
||||||
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
if (lastMeasurement.variant.environment_metrics.has_temperature ||
|
||||||
if (moduleConfig.telemetry.environment_display_fahrenheit) {
|
lastMeasurement.variant.environment_metrics.has_relative_humidity) {
|
||||||
last_temp =
|
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
||||||
String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
|
if (moduleConfig.telemetry.environment_display_fahrenheit) {
|
||||||
}
|
last_temp =
|
||||||
|
String(UnitConversions::CelsiusToFahrenheit(lastMeasurement.variant.environment_metrics.temperature), 0) + "°F";
|
||||||
|
}
|
||||||
|
|
||||||
// Continue with the remaining details
|
// Continue with the remaining details
|
||||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Temp/Hum: " + last_temp + " / " +
|
"Temp/Hum: " + last_temp + " / " +
|
||||||
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
||||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
@ -243,6 +250,10 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
|||||||
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
||||||
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
||||||
|
|
||||||
|
if (lastMeasurement.variant.environment_metrics.radiation != 0)
|
||||||
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
|
"Rad: " + String(lastMeasurement.variant.environment_metrics.radiation, 2) + "µR/h");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
|
||||||
@ -263,6 +274,8 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
|
|||||||
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction,
|
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction,
|
||||||
t->variant.environment_metrics.weight);
|
t->variant.environment_metrics.weight);
|
||||||
|
|
||||||
|
LOG_INFO("(Received from %s): radiation=%fµR/h", sender, t->variant.environment_metrics.radiation);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// release previous packet before occupying a new spot
|
// release previous packet before occupying a new spot
|
||||||
if (lastMeasurementPacket != nullptr)
|
if (lastMeasurementPacket != nullptr)
|
||||||
@ -390,6 +403,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
|
|||||||
valid = valid && max17048Sensor.getMetrics(m);
|
valid = valid && max17048Sensor.getMetrics(m);
|
||||||
hasSensor = true;
|
hasSensor = true;
|
||||||
}
|
}
|
||||||
|
if (cgRadSens.hasSensor()) {
|
||||||
|
valid = valid && cgRadSens.getMetrics(m);
|
||||||
|
hasSensor = true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return valid && hasSensor;
|
return valid && hasSensor;
|
||||||
@ -443,6 +460,8 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
|||||||
LOG_INFO("Send: wind speed=%fm/s, direction=%d degrees, weight=%fkg", m.variant.environment_metrics.wind_speed,
|
LOG_INFO("Send: wind speed=%fm/s, direction=%d degrees, weight=%fkg", m.variant.environment_metrics.wind_speed,
|
||||||
m.variant.environment_metrics.wind_direction, m.variant.environment_metrics.weight);
|
m.variant.environment_metrics.wind_direction, m.variant.environment_metrics.weight);
|
||||||
|
|
||||||
|
LOG_INFO("Send: radiation=%fµR/h", m.variant.environment_metrics.radiation);
|
||||||
|
|
||||||
sensor_read_error_count = 0;
|
sensor_read_error_count = 0;
|
||||||
|
|
||||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||||
@ -585,6 +604,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
|
|||||||
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (cgRadSens.hasSensor()) {
|
||||||
|
result = cgRadSens.handleAdminMessage(mp, request, response);
|
||||||
|
if (result != AdminMessageHandleResult::NOT_HANDLED)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
src/modules/Telemetry/Sensor/CGRadSensSensor.cpp
Normal file
75
src/modules/Telemetry/Sensor/CGRadSensSensor.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Support for the ClimateGuard RadSens Dosimeter
|
||||||
|
* A fun and educational sensor for Meshtastic; not for safety critical applications.
|
||||||
|
*/
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "CGRadSensSensor.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
CGRadSensSensor::CGRadSensSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RADSENS, "RadSens") {}
|
||||||
|
|
||||||
|
int32_t CGRadSensSensor::runOnce()
|
||||||
|
{
|
||||||
|
// Initialize the sensor following the same pattern as RCWL9620Sensor
|
||||||
|
LOG_INFO("Init sensor: %s", sensorName);
|
||||||
|
if (!hasSensor()) {
|
||||||
|
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = true;
|
||||||
|
begin(nodeTelemetrySensorsMap[sensorType].second, nodeTelemetrySensorsMap[sensorType].first);
|
||||||
|
|
||||||
|
return initI2CSensor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGRadSensSensor::setup() {}
|
||||||
|
|
||||||
|
void CGRadSensSensor::begin(TwoWire *wire, uint8_t addr)
|
||||||
|
{
|
||||||
|
// Store the Wire and address to the sensor following the same pattern as RCWL9620Sensor
|
||||||
|
_wire = wire;
|
||||||
|
_addr = addr;
|
||||||
|
_wire->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
float CGRadSensSensor::getStaticRadiation()
|
||||||
|
{
|
||||||
|
// Read a register, following the same pattern as the RCWL9620Sensor
|
||||||
|
uint32_t data;
|
||||||
|
_wire->beginTransmission(_addr); // Transfer data to addr.
|
||||||
|
_wire->write(0x06); // Radiation intensity (static period T = 500 sec)
|
||||||
|
if (_wire->endTransmission() == 0) {
|
||||||
|
if (_wire->requestFrom(_addr, (uint8_t)3)) {
|
||||||
|
; // Request 3 bytes
|
||||||
|
data = _wire->read();
|
||||||
|
data <<= 8;
|
||||||
|
data |= _wire->read();
|
||||||
|
data <<= 8;
|
||||||
|
data |= _wire->read();
|
||||||
|
|
||||||
|
// As per the data sheet for the RadSens
|
||||||
|
// Register 0x06 contains the reading in 0.1 * μR / h
|
||||||
|
float microRadPerHr = float(data) / 10.0;
|
||||||
|
return microRadPerHr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGRadSensSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||||
|
{
|
||||||
|
// Store the meansurement in the the appropriate fields of the protobuf
|
||||||
|
measurement->variant.environment_metrics.has_radiation = true;
|
||||||
|
|
||||||
|
LOG_DEBUG("CGRADSENS getMetrics");
|
||||||
|
measurement->variant.environment_metrics.radiation = getStaticRadiation();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
30
src/modules/Telemetry/Sensor/CGRadSensSensor.h
Normal file
30
src/modules/Telemetry/Sensor/CGRadSensSensor.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Support for the ClimateGuard RadSens Dosimeter
|
||||||
|
* A fun and educational sensor for Meshtastic; not for safety critical applications.
|
||||||
|
*/
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||||
|
|
||||||
|
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||||
|
#include "TelemetrySensor.h"
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
class CGRadSensSensor : public TelemetrySensor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _addr = 0x66;
|
||||||
|
TwoWire *_wire = &Wire;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void setup() override;
|
||||||
|
void begin(TwoWire *wire = &Wire, uint8_t addr = 0x66);
|
||||||
|
float getStaticRadiation();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGRadSensSensor();
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -78,6 +78,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
|||||||
msgPayload["wind_direction"] = new JSONValue((uint)decoded->variant.environment_metrics.wind_direction);
|
msgPayload["wind_direction"] = new JSONValue((uint)decoded->variant.environment_metrics.wind_direction);
|
||||||
msgPayload["wind_gust"] = new JSONValue(decoded->variant.environment_metrics.wind_gust);
|
msgPayload["wind_gust"] = new JSONValue(decoded->variant.environment_metrics.wind_gust);
|
||||||
msgPayload["wind_lull"] = new JSONValue(decoded->variant.environment_metrics.wind_lull);
|
msgPayload["wind_lull"] = new JSONValue(decoded->variant.environment_metrics.wind_lull);
|
||||||
|
msgPayload["radiation"] = new JSONValue(decoded->variant.environment_metrics.radiation);
|
||||||
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
||||||
msgPayload["pm10"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_standard);
|
msgPayload["pm10"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_standard);
|
||||||
msgPayload["pm25"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm25_standard);
|
msgPayload["pm25"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm25_standard);
|
||||||
|
@ -77,6 +77,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
|||||||
jsonObj["payload"]["wind_direction"] = (uint)decoded->variant.environment_metrics.wind_direction;
|
jsonObj["payload"]["wind_direction"] = (uint)decoded->variant.environment_metrics.wind_direction;
|
||||||
jsonObj["payload"]["wind_gust"] = decoded->variant.environment_metrics.wind_gust;
|
jsonObj["payload"]["wind_gust"] = decoded->variant.environment_metrics.wind_gust;
|
||||||
jsonObj["payload"]["wind_lull"] = decoded->variant.environment_metrics.wind_lull;
|
jsonObj["payload"]["wind_lull"] = decoded->variant.environment_metrics.wind_lull;
|
||||||
|
jsonObj["payload"]["radiation"] = decoded->variant.environment_metrics.radiation;
|
||||||
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
||||||
jsonObj["payload"]["pm10"] = (unsigned int)decoded->variant.air_quality_metrics.pm10_standard;
|
jsonObj["payload"]["pm10"] = (unsigned int)decoded->variant.air_quality_metrics.pm10_standard;
|
||||||
jsonObj["payload"]["pm25"] = (unsigned int)decoded->variant.air_quality_metrics.pm25_standard;
|
jsonObj["payload"]["pm25"] = (unsigned int)decoded->variant.air_quality_metrics.pm25_standard;
|
||||||
|
Loading…
Reference in New Issue
Block a user