Skip to content

Commit

Permalink
DFRobot Lark weather station support (#4032)
Browse files Browse the repository at this point in the history
* DF Robot Lark weather station support

* Missed it

* I am a man of const char sorrow...

* Strang

* Use our fork
  • Loading branch information
thebentern authored Jun 4, 2024
1 parent b43c7c0 commit a218c6f
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 3 deletions.
2 changes: 2 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/detect/ScanI2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ScanI2C
OPT3001,
MLX90632,
AHT10,
DFROBOT_LARK,
} DeviceType;

// typedef uint8_t DeviceAddress;
Expand Down
5 changes: 3 additions & 2 deletions src/detect/ScanI2CTwoWire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
88 changes: 88 additions & 0 deletions src/gps/GeoCoord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
2 changes: 2 additions & 0 deletions src/gps/GeoCoord.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
17 changes: 16 additions & 1 deletion src/modules/Telemetry/EnvironmentTelemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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())
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
53 changes: 53 additions & 0 deletions src/modules/Telemetry/Sensor/DFRobotLarkSensor.cpp
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions src/modules/Telemetry/Sensor/DFRobotLarkSensor.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit a218c6f

Please sign in to comment.