From: Bas Schouten Date: Mon, 30 Jan 2023 04:53:46 +0000 (+0100) Subject: Add support for AHT20 temperature sensor and GPIO pin high/low heating output. X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=94f83a6f9e763992a9ee80ae4fc568cf163afd04;p=mqttthermostat.git Add support for AHT20 temperature sensor and GPIO pin high/low heating output. --- diff --git a/MQTTThermostat/AHTTemperatureSupplier.cpp b/MQTTThermostat/AHTTemperatureSupplier.cpp new file mode 100644 index 0000000..a9bb709 --- /dev/null +++ b/MQTTThermostat/AHTTemperatureSupplier.cpp @@ -0,0 +1,81 @@ +#include +#include + +#include +#include +#include + +extern "C" { +#include +#include +#include +} +#include +#include + +#include "AHTTemperatureSupplier.h" + +int i2c_fd; + +#define DATA_PENDING_BIT (1 << 7) + +using namespace std; + +AHTTemperatureSupplier::AHTTemperatureSupplier() +{ + int adapter_nr = 11; + char filename[20]; + + snprintf(filename, 19, "/dev/i2c-%d", adapter_nr); + i2c_fd = open(filename, O_RDWR); + + if (i2c_fd < 0) { + printf("Failed to access i2c port.\n"); + return; + } + if (ioctl(i2c_fd, I2C_SLAVE, 0x38) < 0) { + printf("Failed to find sensor.\n"); + return; + } +} + +float +AHTTemperatureSupplier::getTemperature() +{ + uint8_t byteRead; + byteRead = i2c_smbus_read_byte_data(i2c_fd, 0x71); + + i2c_smbus_write_word_data(i2c_fd, 0xAC, 0x0033); + byteRead = 0x98; + + auto start_time = chrono::high_resolution_clock::now(); + while ((byteRead & DATA_PENDING_BIT)) { + auto current_time = chrono::high_resolution_clock::now(); + if (chrono::duration_cast(current_time - start_time).count() > 150) { + return mLastTemperature; + } + usleep(10000); + + byteRead = i2c_smbus_read_byte_data(i2c_fd, 0x71); + } + + uint8_t data[6]; + read(i2c_fd, data, 6); + + uint32_t encHumidity = (data[1] << 12) + (data[2] << 4) + (data[3] >> 4); + float humidity = (float)encHumidity / 1048576.0; + + uint32_t encTemperature = ((data[3] & 0xF) << 16) + (data[4] << 8) + data[5]; + float temperature = (float)(encTemperature / 1048576.0) * 200.0 - 50.0; + + mLastHumidity = (uint32_t)(humidity * 100.0); + mLastTemperature = temperature; + + return temperature; +} + +uint32_t +AHTTemperatureSupplier::getHumidity() +{ + return mLastHumidity; +} \ No newline at end of file diff --git a/MQTTThermostat/AHTTemperatureSupplier.h b/MQTTThermostat/AHTTemperatureSupplier.h new file mode 100644 index 0000000..17f05ae --- /dev/null +++ b/MQTTThermostat/AHTTemperatureSupplier.h @@ -0,0 +1,14 @@ +#include "TemperatureSupplier.h" + +class AHTTemperatureSupplier : public TemperatureSupplier +{ +public: + AHTTemperatureSupplier(); + + float getTemperature(); + uint32_t getHumidity(); + +private: + uint32_t mLastHumidity = 0; + float mLastTemperature = 0.0; +}; \ No newline at end of file diff --git a/MQTTThermostat/CMakeLists.txt b/MQTTThermostat/CMakeLists.txt index f62271c..a3b9a09 100644 --- a/MQTTThermostat/CMakeLists.txt +++ b/MQTTThermostat/CMakeLists.txt @@ -4,15 +4,28 @@ # Add source to this project's executable. +add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h" "HeatingController.h") if (WIN32) -add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h" "HeatingController.h" "maintest.cpp") +target_sources (mqttthermostat PRIVATE "maintest.cpp") target_link_libraries (mqttthermostat PRIVATE paho-mqtt3a-static paho-mqtt3c-static) endif (WIN32) if (UNIX) -add_executable (mqttthermostat "MQTTThermostat.cpp" "MQTTThermostat.h" "TemperatureSupplier.h" "HeatingController.h" "maindaemon.cpp") +target_sources (mqttthermostat PRIVATE "maindaemon.cpp") target_link_libraries (mqttthermostat PRIVATE paho-mqtt3a paho-mqtt3c) endif (UNIX) +if (HAS_AHT_SUPPORT) +target_sources (mqttthermostat PRIVATE "AHTTemperatureSupplier.cpp") +target_link_libraries (mqttthermostat PRIVATE i2c) +add_compile_definitions(HAS_AHT_SUPPORT) +endif (HAS_AHT_SUPPORT) + +if (HAS_GPIO_SUPPORT) +target_sources (mqttthermostat PRIVATE "GPIOHeatingController.cpp") +target_link_libraries (mqttthermostat PRIVATE wiringPi) +add_compile_definitions(HAS_GPIO_SUPPORT) +endif (HAS_GPIO_SUPPORT) + target_include_directories (mqttthermostat PRIVATE ../paho.mqtt.c/src) install(TARGETS mqttthermostat diff --git a/MQTTThermostat/GPIOHeatingController.cpp b/MQTTThermostat/GPIOHeatingController.cpp new file mode 100644 index 0000000..9eba3f8 --- /dev/null +++ b/MQTTThermostat/GPIOHeatingController.cpp @@ -0,0 +1,25 @@ +#include +#include + +#include "GPIOHeatingController.h" +#include "wiringPi.h" + +using namespace std; + +GPIOHeatingController::GPIOHeatingController(uint32_t aPin) + : mPin(aPin) +{ + wiringPiSetupGpio(); + pinMode(mPin, OUTPUT); +} + +void +GPIOHeatingController::setHeatingActive(bool aActive) +{ + if (aActive) { + digitalWrite(mPin, HIGH); + } + else { + digitalWrite(mPin, LOW); + } +} \ No newline at end of file diff --git a/MQTTThermostat/GPIOHeatingController.h b/MQTTThermostat/GPIOHeatingController.h new file mode 100644 index 0000000..f3eab9b --- /dev/null +++ b/MQTTThermostat/GPIOHeatingController.h @@ -0,0 +1,12 @@ +#include "HeatingController.h" + +class GPIOHeatingController : public HeatingController +{ +public: + GPIOHeatingController(uint32_t aPin); + + void setHeatingActive(bool aActive); + +private: + uint32_t mPin; +}; \ No newline at end of file diff --git a/MQTTThermostat/maindaemon.cpp b/MQTTThermostat/maindaemon.cpp index 2073bb0..306dad6 100644 --- a/MQTTThermostat/maindaemon.cpp +++ b/MQTTThermostat/maindaemon.cpp @@ -14,6 +14,12 @@ #include #include "MQTTThermostat.h" +#ifdef HAS_AHT_SUPPORT +#include "AHTTemperatureSupplier.h" +#endif +#ifdef HAS_GPIO_SUPPORT +#include "GPIOHeatingController.h" +#endif using namespace std; @@ -25,6 +31,7 @@ static int pid_fd; static ofstream logStream; static string pidFile = "~/mqttthermostat.lock"; static string configFile = "~/mqttthermostat.conf"; +int32_t gpioHeatingPin = -1; static bool shuttingDown = false; @@ -79,6 +86,11 @@ void read_config_file() if (value.rfind("dummy", 0) == 0) { tempSupplier = make_unique(); } +#ifdef HAS_AHT_SUPPORT + else if (value.rfind("AHT", 0) == 0) { + tempSupplier = make_unique(); + } +#endif else { LOG("Unknown temperature supplier specified."); } @@ -87,6 +99,15 @@ void read_config_file() if (value.rfind("dummy", 0) == 0) { heatingController = make_unique(); } +#ifdef HAS_GPIO_SUPPORT + else if (value.rfind("GPIO", 0) == 0) { + if (gpioHeatingPin < 0) { + LOG("GPIO heating pin not specified. Add it before selecting the heating controller."); + exit(EXIT_FAILURE); + } + heatingController = make_unique(gpioHeatingPin); + } +#endif else { LOG("Unknown heating controller specified."); } @@ -100,6 +121,9 @@ void read_config_file() else if (key == "clientid") { clientid = value; } + else if (key == "gpio heating pin") { + gpioHeatingPin = stoi(value); + } } } }