Skip to content
Snippets Groups Projects
Verified Commit fea5ac8f authored by Zoe Michaela Dietmar Pfister's avatar Zoe Michaela Dietmar Pfister :gay_pride_flag:
Browse files

initial version of DS18B20 (cheap) temperature sensor

parent 3593da7b
No related branches found
No related tags found
2 merge requests!39Merge Develop into Main,!31Resolve "Cheap DS18B20 Sensor"
Pipeline #103351 passed
//
// Created by zoe on 3/23/23.
//
#include "DS18B20.h"
std::list<Measurement> DS18B20::readData() {
sensors.requestTemperatures();
float temperature = sensors.getTempC(sensorAddress);
if (temperature == DEVICE_DISCONNECTED_C) {
Serial.println("Error: Could not read temperature data");
// error measurement
auto errorMessage = Measurement(ERROR_VALUE, NO_CHANNEL, NO_I2C_ADDRESS, MeasurementType::TEMPERATURE,
ErrorType::SENSOR_NOT_CONNECTED);
return std::list<Measurement>{errorMessage};
}
auto measurement =
Measurement(temperature, NO_CHANNEL, NO_I2C_ADDRESS, MeasurementType::TEMPERATURE, ErrorType::DATA_OK);
return std::list<Measurement>{measurement};
}
std::list<Message> DS18B20::buildMessages() {
std::list<Message> messages;
auto measurements = readData();
for (auto measurement : measurements) {
messages.emplace_back(measurement, getSensorInformation(), Time::getInstance().getEpochSeconds());
}
return messages;
}
SensorInformation DS18B20::getSensorInformation() const {
return {HardwareName::DS18B20, SensorProtocol::OneWire};
}
void DS18B20::setup() {
ESP_LOGD("DS18B20", "Setting up DS18B20\n");
oneWire = OneWireSingleton::getInstance().getOneWire(33);
sensors = DallasTemperature(oneWire.get());
sensors.begin();
ESP_LOGD("DS18B20", "Found %d devices\n", sensors.getDeviceCount());
ESP_LOGD("DS18B20", "Parasite power is: %s\n", sensors.isParasitePowerMode() ? "ON" : "OFF");
// TODO: This is hardcoded to only use the first device
if (!sensors.getAddress(sensorAddress, 0)) {
ESP_LOGD("DS18B20", "Unable to find address for Device 0\n");
}
ESP_LOGD("DS18B20", "Device 0 Address: %s\n", getAddressString(sensorAddress).c_str());
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(sensorAddress, 9);
ESP_LOGD("DS18B20", "Device 0 Resolution: %d\n", sensors.getResolution(sensorAddress));
ESP_LOGD("DS18B20", "Setup complete\n");
}
//
// Created by zoe on 3/23/23.
//
#ifndef CLIENT_SATELLITE_DS18B20_H
#define CLIENT_SATELLITE_DS18B20_H
#include <ForteSensor.hpp>
#include "DallasTemperature.h"
#include <OneWire.h>
#include <OneWireSingleton.h>
class DS18B20 : ForteSensor<std::list<Measurement>> {
public:
void setup() override;
std::list<Measurement> readData() override;
std::list<Message> buildMessages() override;
[[nodiscard]] SensorInformation getSensorInformation() const override;
private:
std::shared_ptr<OneWire> oneWire;
DallasTemperature sensors;
DeviceAddress sensorAddress;
// function to print a device address
String getAddressString(DeviceAddress deviceAddress) {
String addressString = "";
for (uint8_t i = 0; i < 8; i++) {
if (deviceAddress[i] < 16) {
addressString += "0";
}
char hexBuffer[3];
snprintf(hexBuffer, sizeof(hexBuffer), "%02X", deviceAddress[i]);
addressString += hexBuffer;
}
return addressString;
}
};
#endif // CLIENT_SATELLITE_DS18B20_H
//
// Created by zoe on 3/23/23.
//
#include "OneWireSingleton.h"
std::shared_ptr<OneWire> OneWireSingleton::getOneWire(int pin) {
if (oneWireMap.find(pin) == oneWireMap.end()) {
oneWireMap[pin] = std::make_shared<OneWire>(OneWire(pin));
}
return oneWireMap[pin];
}
\ No newline at end of file
//
// Created by zoe on 3/23/23.
//
#ifndef CLIENT_SATELLITE_ONEWIRESINGLETON_H
#define CLIENT_SATELLITE_ONEWIRESINGLETON_H
#include <OneWire.h>
#include <memory>
class OneWireSingleton {
public:
static OneWireSingleton &getInstance() {
static OneWireSingleton instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
// This returns a shared pointer to the OneWire object. I made this shared so that the OneWire object is only
// cleared when not only the singleton is destroyed, but when the last reference to the OneWire object is
// destroyed.
std::shared_ptr<OneWire> getOneWire(int pin);
private:
OneWireSingleton() {} // Constructor? (the {} brackets) are needed here.
std::unordered_map<int, std::shared_ptr<OneWire>> oneWireMap;
// C++ 11
// =======
// We can use the better technique of deleting the methods
// we don't want.
public:
OneWireSingleton(OneWireSingleton const &) = delete;
void operator=(OneWireSingleton const &) = delete;
// Note: Scott Meyers mentions in his Effective Modern
// C++ book, that deleted functions should generally
// be public as it results in better error messages
// due to the compilers behavior to check accessibility
// before deleted status
};
#endif // CLIENT_SATELLITE_ONEWIRESINGLETON_H
...@@ -126,7 +126,7 @@ esp_err_t espnow_setup() { ...@@ -126,7 +126,7 @@ esp_err_t espnow_setup() {
if (result != ESP_OK) { if (result != ESP_OK) {
// initialization failed // initialization failed
ESP_LOGE(TAG, "ESPNow setup failed"); ESP_LOGE(TAG, "ESPNow setup failed");
return result; // not sure about this return result;
} }
get_host_mac(hostInfo.peer_addr); // check if there is a host saved in flash mem, broadcast otherwise get_host_mac(hostInfo.peer_addr); // check if there is a host saved in flash mem, broadcast otherwise
......
...@@ -4,42 +4,44 @@ ...@@ -4,42 +4,44 @@
#include "HardwareNames.h" #include "HardwareNames.h"
namespace HardwareNames { namespace HardwareNames {
std::string hardwareNameToString(HardwareName hardwareName) { std::string hardwareNameToString(HardwareName hardwareName) {
// switch // switch
switch (hardwareName) { switch (hardwareName) {
case HardwareName::RS485: case HardwareName::RS485:
return "RS485"; return "RS485";
case HardwareName::INA219: case HardwareName::INA219:
return "INA219"; return "INA219";
case HardwareName::SCD30: case HardwareName::SCD30:
return "SCD30"; return "SCD30";
case HardwareName::RAIN_GAUGE: case HardwareName::RAIN_GAUGE:
return "RAIN_GAUGE"; return "RAIN_GAUGE";
case HardwareName::SOIL_MOISTURE_SENSOR: case HardwareName::SOIL_MOISTURE_SENSOR:
return "SOIL_MOISTURE_SENSOR"; return "SOIL_MOISTURE_SENSOR";
case HardwareName::SOIL_TEMPERATURE_SENSOR: case HardwareName::SOIL_TEMPERATURE_SENSOR:
return "SOIL_TEMPERATURE_SENSOR"; return "SOIL_TEMPERATURE_SENSOR";
case HardwareName::SOLAR_RADIATION_SENSOR: case HardwareName::SOLAR_RADIATION_SENSOR:
return "SOLAR_RADIATION_SENSOR"; return "SOLAR_RADIATION_SENSOR";
case HardwareName::SHT85: case HardwareName::SHT85:
return "SHT85"; return "SHT85";
case HardwareName::DRS26: case HardwareName::DRS26:
return "DRS26"; return "DRS26";
case HardwareName::DR26: case HardwareName::DR26:
return "DR26"; return "DR26";
case HardwareName::MOCK: case HardwareName::MOCK:
return "MOCK"; return "MOCK";
case HardwareName::NONE: case HardwareName::NONE:
return "NONE"; return "NONE";
case HardwareName::LC709203: case HardwareName::LC709203:
return "LC709203"; return "LC709203";
case HardwareName::SEM228A: case HardwareName::SEM228A:
return "SEM228A"; return "SEM228A";
case HardwareName::SEM225: case HardwareName::SEM225:
return "SEM225"; return "SEM225";
case HardwareName::SEM404: case HardwareName::SEM404:
return "SEM404"; return "SEM404";
} case HardwareName::DS18B20:
return "UNKNOWN_HARDWARE_NAME"; return "DS18B20";
} }
return "UNKNOWN_HARDWARE_NAME";
}
} // namespace HardwareNames } // namespace HardwareNames
\ No newline at end of file
...@@ -9,29 +9,29 @@ ...@@ -9,29 +9,29 @@
// 32,767 possible values // 32,767 possible values
enum class HardwareName : short { enum class HardwareName : short {
RS485, // TODO: THIS IS THE PROTOCOL NAME NOT THE HARDWARE NAME RS485, // TODO: THIS IS THE PROTOCOL NAME NOT THE HARDWARE NAME
INA219, INA219,
SCD30, SCD30,
RAIN_GAUGE, RAIN_GAUGE,
SOIL_MOISTURE_SENSOR, SOIL_MOISTURE_SENSOR,
SOIL_TEMPERATURE_SENSOR, SOIL_TEMPERATURE_SENSOR,
SOLAR_RADIATION_SENSOR, SOLAR_RADIATION_SENSOR,
SEM404, SEM404,
SEM228A, SEM228A,
SEM225, SEM225,
SHT85, DS18B20,
DRS26, SHT85,
DR26, DRS26,
MOCK, DR26,
NONE, MOCK,
LC709203, NONE,
LC709203,
}; };
// hardware name to string function // hardware name to string function
namespace HardwareNames { namespace HardwareNames {
std::string hardwareNameToString(HardwareName hardwareName); std::string hardwareNameToString(HardwareName hardwareName);
} }
#endif // CLIENT_MOCK_HARDWARENAMES_H
#endif //CLIENT_MOCK_HARDWARENAMES_H
...@@ -4,19 +4,21 @@ ...@@ -4,19 +4,21 @@
#include "SensorProtocol.hpp" #include "SensorProtocol.hpp"
namespace SensorProtocols { namespace SensorProtocols {
std::string sensorProtocolToString(SensorProtocol sensorProtocol) { std::string sensorProtocolToString(SensorProtocol sensorProtocol) {
switch (sensorProtocol) { switch (sensorProtocol) {
case SensorProtocol::I2C: case SensorProtocol::I2C:
return "I2C"; return "I2C";
case SensorProtocol::RS485: case SensorProtocol::RS485:
return "RS485"; return "RS485";
case SensorProtocol::Analog: case SensorProtocol::Analog:
return "Analog"; return "Analog";
case SensorProtocol::Mock: case SensorProtocol::Mock:
return "Mock"; return "Mock";
case SensorProtocol::NULL_PROTOCOL: case SensorProtocol::OneWire:
return "NULL_PROTOCOL"; return "OneWire";
} case SensorProtocol::NULL_PROTOCOL:
return "UNKNOWN"; return "NULL_PROTOCOL";
} }
} return "UNKNOWN";
\ No newline at end of file }
} // namespace SensorProtocols
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define CLIENT_PROTOCOL_HPP #define CLIENT_PROTOCOL_HPP
#include <map> #include <map>
enum class SensorProtocol : short { I2C, RS485, Analog, Mock, NULL_PROTOCOL }; enum class SensorProtocol : short { I2C, RS485, Analog, Mock, OneWire, NULL_PROTOCOL };
namespace SensorProtocols { namespace SensorProtocols {
std::string sensorProtocolToString(SensorProtocol sensorProtocol); std::string sensorProtocolToString(SensorProtocol sensorProtocol);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment