From 81aa0c64f985fced2a395d3d50bfeaa19bcf4201 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Wed, 10 Jan 2024 19:43:07 +0700 Subject: [PATCH] integrate IRBlaster into climate card --- .../lib/ESPMegaPRO/ClimateCard.cpp | 45 +++++++------------ .../lib/ESPMegaPRO/ClimateCard.hpp | 9 ++-- .../lib/ESPMegaPRO/IRBlaster.cpp | 36 ++++++++++++--- .../lib/ESPMegaPRO/IRBlaster.hpp | 20 +++++---- .../src/{main.cpp.disabled => main.cpp} | 0 .../{rmt_demo.cpp => rmt_demo.cpp.disabled} | 0 6 files changed, 60 insertions(+), 50 deletions(-) rename ESPMegaPRO-OS-SDK/src/{main.cpp.disabled => main.cpp} (100%) rename ESPMegaPRO-OS-SDK/src/{rmt_demo.cpp => rmt_demo.cpp.disabled} (100%) diff --git a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.cpp b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.cpp index adae7b9..6527cfc 100644 --- a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.cpp +++ b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.cpp @@ -11,12 +11,15 @@ /** * @brief Construct a new ClimateCard object. * + * @note RMT channel must be universally unique, this means that you can't use the same channel for multiple cards. + * * @param ir_pin The GPIO pin number of the IR transmitter. * @param ac The AirConditioner object that represents the air conditioner. * @param sensor_type The type of the sensor connected to the card. * @param sensor_pin The GPIO pin number of the sensor. + * @param channel The RMT channel to use for IR transmission. */ -ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin) +ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin, rmt_channel_t channel) : ir_blaster(ir_pin, channel) { this->ir_pin = ir_pin; this->ac = ac; @@ -45,10 +48,13 @@ ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, * * @param ir_pin The GPIO pin number of the IR transmitter. * @param ac The AirConditioner object that represents the air conditioner. + * @param channel The RMT channel to use for IR transmission. + * + * @note RMT channel must be universally unique, this means that you can't use the same channel for multiple cards. * * @note This constructor can be used when no sensor is connected to the card. */ -ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac) : ClimateCard(ir_pin, ac, AC_SENSOR_TYPE_NONE, 0) +ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, rmt_channel_t channel) : ClimateCard(ir_pin, ac, AC_SENSOR_TYPE_NONE, 0, channel) { } @@ -59,7 +65,6 @@ ClimateCard::~ClimateCard() { delete dht; delete ds18b20; - rmt_driver_uninstall(RMT_TX_CHANNEL); } /** @@ -81,17 +86,7 @@ bool ClimateCard::begin() break; } updateAirConditioner(); - // We are returning here because sending IR signals is not working yet return true; - if (sensor_pin != 0) - { - // Initialize RMT - gpio_num_t gpio_num = gpio_num_t(ir_pin); - rmt_config_t rmt_tx = RMT_DEFAULT_CONFIG_TX(gpio_num, RMT_TX_CHANNEL); - rmt_tx.clk_div = 80; // 1MHz clock - rmt_config(&rmt_tx); - rmt_driver_install(rmt_tx.channel, 0, 0); - } } /** @@ -351,25 +346,15 @@ void ClimateCard::updateSensor() void ClimateCard::updateAirConditioner() { // // The IR Transmissions are not working yet so we just return - // const uint16_t* ir_code_ptr = nullptr; - // size_t itemCount = (*(this->ac.getInfraredCode))(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature, &ir_code_ptr); + const uint16_t* ir_code_ptr = nullptr; + size_t itemCount = (*(this->ac.getInfraredCode))(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature, &ir_code_ptr); - // if (ir_code_ptr == nullptr) - // return; + if (ir_code_ptr == nullptr) + return; - // rmt_item32_t items[itemCount]; - // // Convert IR timing array to RMT items - // for (size_t i = 0; i < itemCount; i+=2) - // { - // items[i].level0 = 1; - // items[i].duration0 = ir_code_ptr[i]; - // items[i].level1 = 0; - // items[i].duration1 = ir_code_ptr[i+1]; - // } - // // Send IR signal - // rmt_write_items(RMT_TX_CHANNEL, items, itemCount, true); - // rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY); - // // Publish state + ir_blaster.send(ir_code_ptr, itemCount); + + // Publish state for (const auto &callback : callbacks) { callback.second(this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature); diff --git a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.hpp b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.hpp index f4fa416..7d7e4ee 100644 --- a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.hpp +++ b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/ClimateCard.hpp @@ -1,14 +1,12 @@ #pragma once #include -#include +#include #include #include #include #include #include -#define RMT_TX_CHANNEL RMT_CHANNEL_0 - #define CARD_TYPE_CLIMATE 0x03 #define AC_SENSOR_TYPE_NONE 0x00 @@ -65,8 +63,8 @@ struct AirConditioner { */ class ClimateCard : public ExpansionCard { public: - ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin); - ClimateCard(uint8_t ir_pin, AirConditioner ac); + ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin, rmt_channel_t channel); + ClimateCard(uint8_t ir_pin, AirConditioner ac, rmt_channel_t channel); ~ClimateCard(); bool begin(); void loop(); @@ -107,6 +105,7 @@ class ClimateCard : public ExpansionCard { void updateAirConditioner(); // IR variables uint8_t ir_pin; + IRBlaster ir_blaster; // Air conditioner variables AirConditioner ac; ClimateCardData state; diff --git a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.cpp b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.cpp index c38bdae..81478c2 100644 --- a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.cpp +++ b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.cpp @@ -1,11 +1,23 @@ #include -#include -void IRBlaster::send(uint16_t *data, size_t size) +/** + * @brief Destroy the IRBlaster object +*/ +IRBlaster::~IRBlaster() +{ + ESP_ERROR_CHECK(rmt_driver_uninstall(channel)); +} + +/** + * @brief Send an IR signal + * + * @param data The microseconds timing array produced by IRReceiver + * @param size The number of elements in the array +*/ +void IRBlaster::send(const uint16_t *data, const size_t size) { // Send a raw IR signal rmt_item32_t *items = new rmt_item32_t[size / 2 + size % 2]; - Serial.println("Converting IR data"); // data is in microseconds, we need to convert it to ticks // If the number of elements is odd, we need to add a 0 at the end for (size_t i = 0, j = 0; i < size; i += 2, j++) @@ -20,12 +32,18 @@ void IRBlaster::send(uint16_t *data, size_t size) items[j].duration1 = 0; } } - Serial.println("Sending IR data"); ESP_ERROR_CHECK(rmt_write_items(channel, items, size / 2 + size % 2, true)); delete[] items; } -IRBlaster::IRBlaster(uint8_t pin, rmt_channel_t channel) +/** + * @brief Construct a new IRBlaster object + * + * @param pin The pin to use for IR transmission + * @param channel The RMT channel to use +*/ + +IRBlaster::IRBlaster(const uint8_t pin, rmt_channel_t channel) { this->channel = channel; gpio_num_t gpio = gpio_num_t(pin); @@ -37,7 +55,13 @@ IRBlaster::IRBlaster(uint8_t pin, rmt_channel_t channel) ESP_ERROR_CHECK(rmt_driver_install(channel, 0, 0)); } -IRBlaster::IRBlaster(uint8_t pin) +/** + * @brief Construct a new IRBlaster object + * @note This constructor uses RMT_CHANNEL_0 + * + * @param pin The pin to use for IR transmission +*/ +IRBlaster::IRBlaster(const uint8_t pin) { IRBlaster(pin, RMT_CHANNEL_0); } \ No newline at end of file diff --git a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.hpp b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.hpp index 8b58850..79248e3 100644 --- a/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.hpp +++ b/ESPMegaPRO-OS-SDK/lib/ESPMegaPRO/IRBlaster.hpp @@ -1,16 +1,18 @@ +#pragma once #include + +/** + * @brief Class for sending IR signals + * + * @warning This class takes one of the RMT channels, The ESP32 has 8 RMT channels, so you can use 7 IRBlaster objects at the same time (or 6 if you use the IRReceiver class) +*/ class IRBlaster { public: - IRBlaster(uint8_t pin, rmt_channel_t channel); - IRBlaster(uint8_t pin); - /*** - * @brief Send an array of IR codes - * - * @param data Array of IR codes, each code is a 16 bit integer representing the number of 10us ticks - * @param size Size of the array - */ - void send(uint16_t *data, size_t size); + IRBlaster(const uint8_t pin, rmt_channel_t channel); + IRBlaster(const uint8_t pin); + ~IRBlaster(); + void send(const uint16_t *data, const size_t size); private: rmt_channel_t channel; }; \ No newline at end of file diff --git a/ESPMegaPRO-OS-SDK/src/main.cpp.disabled b/ESPMegaPRO-OS-SDK/src/main.cpp similarity index 100% rename from ESPMegaPRO-OS-SDK/src/main.cpp.disabled rename to ESPMegaPRO-OS-SDK/src/main.cpp diff --git a/ESPMegaPRO-OS-SDK/src/rmt_demo.cpp b/ESPMegaPRO-OS-SDK/src/rmt_demo.cpp.disabled similarity index 100% rename from ESPMegaPRO-OS-SDK/src/rmt_demo.cpp rename to ESPMegaPRO-OS-SDK/src/rmt_demo.cpp.disabled