kopia lustrzana https://github.com/meshtastic/firmware
DFRobot Lark weather station support (#4032)
* DF Robot Lark weather station support * Missed it * I am a man of const char sorrow... * Strang * Use our forkpull/4033/head^2
rodzic
b43c7c0f23
commit
a218c6fb4d
|
@ -139,3 +139,5 @@ lib_deps =
|
|||
adafruit/Adafruit TSL2591 Library@^1.4.5
|
||||
ClosedCube OPT3001@^1.1.2
|
||||
emotibit/EmotiBit MLX90632@^1.0.8
|
||||
dfrobot/DFRobot_RTU@^1.0.3
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#0e884fc86b7a0b602c7ff3d26b893b997f15c6ac
|
|
@ -135,6 +135,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define OPT3001_ADDR 0x45
|
||||
#define OPT3001_ADDR_ALT 0x44
|
||||
#define MLX90632_ADDR 0x3A
|
||||
#define DFROBOT_LARK_ADDR 0x42
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ACCELEROMETER
|
||||
|
|
|
@ -49,6 +49,7 @@ class ScanI2C
|
|||
OPT3001,
|
||||
MLX90632,
|
||||
AHT10,
|
||||
DFROBOT_LARK,
|
||||
} DeviceType;
|
||||
|
||||
// typedef uint8_t DeviceAddress;
|
||||
|
|
|
@ -281,8 +281,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
|||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = INA3221;
|
||||
} else { // Unknown device
|
||||
LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address);
|
||||
} else {
|
||||
LOG_INFO("DFRobot Lark weather station found at address 0x%x\n", (uint8_t)addr.address);
|
||||
type = DFROBOT_LARK;
|
||||
}
|
||||
break;
|
||||
case MCP9808_ADDR:
|
||||
|
|
|
@ -486,3 +486,91 @@ std::shared_ptr<GeoCoord> GeoCoord::pointAtDistance(double bearing, double range
|
|||
|
||||
return std::make_shared<GeoCoord>(double(lat), double(lon), this->getAltitude());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bearing to degrees
|
||||
* @param bearing
|
||||
* The bearing in string format
|
||||
* @return Bearing in degrees
|
||||
*/
|
||||
uint GeoCoord::bearingToDegrees(const char *bearing)
|
||||
{
|
||||
if (strcmp(bearing, "N") == 0)
|
||||
return 0;
|
||||
else if (strcmp(bearing, "NNE") == 0)
|
||||
return 22;
|
||||
else if (strcmp(bearing, "NE") == 0)
|
||||
return 45;
|
||||
else if (strcmp(bearing, "ENE") == 0)
|
||||
return 67;
|
||||
else if (strcmp(bearing, "E") == 0)
|
||||
return 90;
|
||||
else if (strcmp(bearing, "ESE") == 0)
|
||||
return 112;
|
||||
else if (strcmp(bearing, "SE") == 0)
|
||||
return 135;
|
||||
else if (strcmp(bearing, "SSE") == 0)
|
||||
return 157;
|
||||
else if (strcmp(bearing, "S") == 0)
|
||||
return 180;
|
||||
else if (strcmp(bearing, "SSW") == 0)
|
||||
return 202;
|
||||
else if (strcmp(bearing, "SW") == 0)
|
||||
return 225;
|
||||
else if (strcmp(bearing, "WSW") == 0)
|
||||
return 247;
|
||||
else if (strcmp(bearing, "W") == 0)
|
||||
return 270;
|
||||
else if (strcmp(bearing, "WNW") == 0)
|
||||
return 292;
|
||||
else if (strcmp(bearing, "NW") == 0)
|
||||
return 315;
|
||||
else if (strcmp(bearing, "NNW") == 0)
|
||||
return 337;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bearing to string
|
||||
* @param degrees
|
||||
* The bearing in degrees
|
||||
* @return Bearing in string format
|
||||
*/
|
||||
const char *GeoCoord::degreesToBearing(uint degrees)
|
||||
{
|
||||
if (degrees >= 348 || degrees < 11)
|
||||
return "N";
|
||||
else if (degrees >= 11 && degrees < 34)
|
||||
return "NNE";
|
||||
else if (degrees >= 34 && degrees < 56)
|
||||
return "NE";
|
||||
else if (degrees >= 56 && degrees < 79)
|
||||
return "ENE";
|
||||
else if (degrees >= 79 && degrees < 101)
|
||||
return "E";
|
||||
else if (degrees >= 101 && degrees < 124)
|
||||
return "ESE";
|
||||
else if (degrees >= 124 && degrees < 146)
|
||||
return "SE";
|
||||
else if (degrees >= 146 && degrees < 169)
|
||||
return "SSE";
|
||||
else if (degrees >= 169 && degrees < 191)
|
||||
return "S";
|
||||
else if (degrees >= 191 && degrees < 214)
|
||||
return "SSW";
|
||||
else if (degrees >= 214 && degrees < 236)
|
||||
return "SW";
|
||||
else if (degrees >= 236 && degrees < 259)
|
||||
return "WSW";
|
||||
else if (degrees >= 259 && degrees < 281)
|
||||
return "W";
|
||||
else if (degrees >= 281 && degrees < 304)
|
||||
return "WNW";
|
||||
else if (degrees >= 304 && degrees < 326)
|
||||
return "NW";
|
||||
else if (degrees >= 326 && degrees < 348)
|
||||
return "NNW";
|
||||
else
|
||||
return "N";
|
||||
}
|
||||
|
|
|
@ -117,6 +117,8 @@ class GeoCoord
|
|||
static float bearing(double lat1, double lon1, double lat2, double lon2);
|
||||
static float rangeRadiansToMeters(double range_radians);
|
||||
static float rangeMetersToRadians(double range_meters);
|
||||
static uint bearingToDegrees(const char *bearing);
|
||||
static const char *degreesToBearing(uint degrees);
|
||||
|
||||
// Point to point conversions
|
||||
int32_t distanceTo(const GeoCoord &pointB);
|
||||
|
|
|
@ -540,6 +540,7 @@ void setup()
|
|||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10)
|
||||
SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK)
|
||||
|
||||
i2cScanner.reset();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Sensor/BME680Sensor.h"
|
||||
#include "Sensor/BMP085Sensor.h"
|
||||
#include "Sensor/BMP280Sensor.h"
|
||||
#include "Sensor/DFRobotLarkSensor.h"
|
||||
#include "Sensor/LPS22HBSensor.h"
|
||||
#include "Sensor/MCP9808Sensor.h"
|
||||
#include "Sensor/MLX90632Sensor.h"
|
||||
|
@ -49,6 +50,7 @@ SHT4XSensor sht4xSensor;
|
|||
RCWL9620Sensor rcwl9620Sensor;
|
||||
AHT10Sensor aht10Sensor;
|
||||
MLX90632Sensor mlx90632Sensor;
|
||||
DFRobotLarkSensor dfRobotLarkSensor;
|
||||
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||
|
@ -72,7 +74,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||
|
||||
// moduleConfig.telemetry.environment_measurement_enabled = 1;
|
||||
// moduleConfig.telemetry.environment_screen_enabled = 1;
|
||||
// moduleConfig.telemetry.environment_update_interval = 45;
|
||||
// moduleConfig.telemetry.environment_update_interval = 15;
|
||||
|
||||
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) {
|
||||
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
|
||||
|
@ -87,6 +89,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||
LOG_INFO("Environment Telemetry: Initializing\n");
|
||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||
// therefore, we should only enable the sensor loop if measurement is also enabled
|
||||
if (dfRobotLarkSensor.hasSensor())
|
||||
result = dfRobotLarkSensor.runOnce();
|
||||
if (bmp085Sensor.hasSensor())
|
||||
result = bmp085Sensor.runOnce();
|
||||
if (bmp280Sensor.hasSensor())
|
||||
|
@ -240,6 +244,10 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
|
|||
t->variant.environment_metrics.temperature);
|
||||
LOG_INFO("(Received from %s): voltage=%f, IAQ=%d, distance=%f, lux=%f\n", sender, t->variant.environment_metrics.voltage,
|
||||
t->variant.environment_metrics.iaq, t->variant.environment_metrics.distance, t->variant.environment_metrics.lux);
|
||||
|
||||
LOG_INFO("(Received from %s): wind speed=%fm/s, direction=%d degrees\n", sender,
|
||||
t->variant.environment_metrics.wind_speed, t->variant.environment_metrics.wind_direction);
|
||||
|
||||
#endif
|
||||
// release previous packet before occupying a new spot
|
||||
if (lastMeasurementPacket != nullptr)
|
||||
|
@ -259,6 +267,10 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
|||
m.time = getTime();
|
||||
m.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
|
||||
if (dfRobotLarkSensor.hasSensor()) {
|
||||
valid = valid && dfRobotLarkSensor.getMetrics(&m);
|
||||
hasSensor = true;
|
||||
}
|
||||
if (sht31Sensor.hasSensor()) {
|
||||
valid = valid && sht31Sensor.getMetrics(&m);
|
||||
hasSensor = true;
|
||||
|
@ -342,6 +354,9 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
|
|||
LOG_INFO("(Sending): voltage=%f, IAQ=%d, distance=%f, lux=%f\n", m.variant.environment_metrics.voltage,
|
||||
m.variant.environment_metrics.iaq, m.variant.environment_metrics.distance, m.variant.environment_metrics.lux);
|
||||
|
||||
LOG_INFO("(Sending): wind speed=%fm/s, direction=%d degrees\n", m.variant.environment_metrics.wind_speed,
|
||||
m.variant.environment_metrics.wind_direction);
|
||||
|
||||
sensor_read_error_count = 0;
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataProtobuf(m);
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "DFRobotLarkSensor.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include <DFRobot_LarkWeatherStation.h>
|
||||
#include <string>
|
||||
|
||||
DFRobotLarkSensor::DFRobotLarkSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_DFROBOT_LARK, "DFROBOT_LARK") {}
|
||||
|
||||
int32_t DFRobotLarkSensor::runOnce()
|
||||
{
|
||||
LOG_INFO("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
lark = DFRobot_LarkWeatherStation_I2C(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
|
||||
|
||||
if (lark.begin() == 0) // DFRobotLarkSensor init
|
||||
{
|
||||
LOG_DEBUG("DFRobotLarkSensor Init Succeed\n");
|
||||
status = true;
|
||||
} else {
|
||||
LOG_ERROR("DFRobotLarkSensor Init Failed\n");
|
||||
status = false;
|
||||
}
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void DFRobotLarkSensor::setup() {}
|
||||
|
||||
bool DFRobotLarkSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
{
|
||||
measurement->variant.environment_metrics.temperature = lark.getValue("Temp").toFloat();
|
||||
measurement->variant.environment_metrics.relative_humidity = lark.getValue("Humi").toFloat();
|
||||
measurement->variant.environment_metrics.wind_speed = lark.getValue("Speed").toFloat();
|
||||
measurement->variant.environment_metrics.wind_direction = GeoCoord::bearingToDegrees(lark.getValue("Dir").c_str());
|
||||
measurement->variant.environment_metrics.barometric_pressure = lark.getValue("Pressure").toFloat();
|
||||
|
||||
LOG_INFO("Temperature: %f\n", measurement->variant.environment_metrics.temperature);
|
||||
LOG_INFO("Humidity: %f\n", measurement->variant.environment_metrics.relative_humidity);
|
||||
LOG_INFO("Wind Speed: %f\n", measurement->variant.environment_metrics.wind_speed);
|
||||
LOG_INFO("Wind Direction: %d\n", measurement->variant.environment_metrics.wind_direction);
|
||||
LOG_INFO("Barometric Pressure: %f\n", measurement->variant.environment_metrics.barometric_pressure);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
|
||||
#include "../mesh/generated/meshtastic/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <DFRobot_LarkWeatherStation.h>
|
||||
#include <string>
|
||||
|
||||
class DFRobotLarkSensor : public TelemetrySensor
|
||||
{
|
||||
private:
|
||||
DFRobot_LarkWeatherStation_I2C lark = DFRobot_LarkWeatherStation_I2C();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
DFRobotLarkSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
Ładowanie…
Reference in New Issue