climate display implementation

This commit is contained in:
Siwat Sirichai 2023-12-31 00:25:07 +07:00
parent 2d0d38ecf3
commit ea2c2e076b
14 changed files with 213 additions and 342 deletions

View file

@ -1,8 +1,11 @@
#include <ClimateCard.hpp>
ClimateCard::ClimateCard(uint8_t ir_pin)
ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin)
{
this->ir_pin = ir_pin;
this->ac = ac;
this->sensor_type = sensor_type;
this->sensor_pin = sensor_pin;
// Initialize Pointers
this->dht = nullptr;
this->ds18b20 = nullptr;
@ -21,13 +24,11 @@ ClimateCard::ClimateCard(uint8_t ir_pin)
this->state.ac_fan_speed = 0;
// Initialize callbacks
this->callbacks = std::vector<std::function<void(uint8_t, uint8_t, uint8_t)>>();
this->sensor_callbacks = std::vector<std::function<void(float, float)>>();
// 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);
}
ClimateCard::ClimateCard(uint8_t ir_pin, AirConditioner ac) : ClimateCard(ir_pin, ac, AC_SENSOR_TYPE_NONE, 0)
{
}
ClimateCard::~ClimateCard()
@ -37,11 +38,8 @@ ClimateCard::~ClimateCard()
rmt_driver_uninstall(RMT_TX_CHANNEL);
}
bool ClimateCard::begin(AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin)
bool ClimateCard::begin()
{
this->ac = ac;
this->sensor_type = sensor_type;
this->sensor_pin = sensor_pin;
switch (sensor_type)
{
case AC_SENSOR_TYPE_DHT22:
@ -54,11 +52,15 @@ bool ClimateCard::begin(AirConditioner ac, uint8_t sensor_type, uint8_t sensor_p
}
updateAirConditioner();
return true;
}
bool ClimateCard::begin(AirConditioner ac)
{
return this->begin(ac, AC_SENSOR_TYPE_NONE, 0);
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);
}
}
void ClimateCard::loop()
@ -94,6 +96,11 @@ void ClimateCard::loadStateFromFRAM()
void ClimateCard::setTemperature(uint8_t temperature)
{
// If temperature is out of range, set to its respective maximum or minimum
if (temperature > ac.max_temperature)
temperature = ac.max_temperature;
else if (temperature < ac.min_temperature)
temperature = ac.min_temperature;
this->state.ac_temperature = temperature;
updateAirConditioner();
if (fram_auto_save)
@ -161,25 +168,29 @@ void ClimateCard::updateSensor()
void ClimateCard::updateAirConditioner()
{
size_t itemCount = sizeof(ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature]) / sizeof(ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][0]);
rmt_item32_t items[itemCount];
// Convert IR timing array to RMT items
for (size_t i = 0; i < itemCount; i++)
{
items[i].level0 = 1;
items[i].duration0 = ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][i];
items[i].level1 = 0;
items[i].duration1 = ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][i];
}
// Send IR signal
rmt_write_items(RMT_TX_CHANNEL, items, itemCount, true);
rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY);
// Publish state
for (uint8_t i = 0; i < callbacks.size(); i++)
{
callbacks[i](this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature);
}
// 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;
// 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
// for (uint8_t i = 0; i < callbacks.size(); i++)
// {
// callbacks[i](this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature);
// }
}
uint8_t ClimateCard::getSensorType()
@ -215,4 +226,5 @@ uint8_t ClimateCard::getFanSpeed()
void ClimateCard::registerSensorCallback(std::function<void(float, float)> callback)
{
sensor_callbacks.push_back(callback);
}
}

View file

@ -28,19 +28,22 @@ struct AirConditioner {
uint8_t max_temperature;
uint8_t min_temperature;
uint8_t modes;
char **mode_names;
const char **mode_names;
uint8_t fan_speeds;
char **fan_speed_names;
uint16_t ****infraredCodes;
const char **fan_speed_names;
// function to get IR code
// takes 3 arguments: mode, fan speed, temperature, all uint8_t
// return size of IR code array
size_t (*getInfraredCode)(uint8_t, uint8_t, uint8_t, const uint16_t**);
};
// This requires 3 bytes of FRAM
class ClimateCard : public ExpansionCard {
public:
ClimateCard(uint8_t ir_pin);
ClimateCard(uint8_t ir_pin, AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin);
ClimateCard(uint8_t ir_pin, AirConditioner ac);
~ClimateCard();
bool begin(AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin);
bool begin(AirConditioner ac);
bool begin();
void loop();
void bindFRAM(FRAM *fram, uint16_t fram_address);
void setFRAMAutoSave(bool autoSave);
@ -83,4 +86,5 @@ class ClimateCard : public ExpansionCard {
FRAM *fram;
uint8_t fram_address;
bool fram_auto_save;
uint16_t* getIrIndex(uint8_t mode, uint8_t fan_speed, uint8_t temperature);
};

View file

@ -121,6 +121,10 @@ void InternalDisplay::refreshPage(uint8_t page) {
this->refreshOutput();
break;
case INTERNAL_DISPLAY_AC_PAGE:
if (this->climateCard == nullptr) {
this->jumpToPage(INTERNAL_DISPLAY_CLIMATE_NULL_PTR_PAGE);
break;
}
this->refreshAC();
break;
case INTERNAL_DISPLAY_PWM_ADJUSTMENT_PAGE:
@ -145,8 +149,6 @@ void InternalDisplay::refreshDashboard() {
// Send the MQTT server and port
this->displayAdapter->print("server_address.txt=\"");
this->displayAdapter->print(this->mqttConfig->mqtt_server);
this->displayAdapter->print(":");
this->displayAdapter->print(this->mqttConfig->mqtt_port);
this->displayAdapter->print("\"");
this->sendStopBytes();
// Send the MQTT connection status
@ -167,7 +169,52 @@ void InternalDisplay::refreshOutput() {
}
void InternalDisplay::refreshAC() {
// TODO: implementation
this->displayAdapter->print("temp.txt=\"");
this->displayAdapter->print(this->climateCard->getTemperature());
this->displayAdapter->print(" C\"");
this->sendStopBytes();
this->displayAdapter->print("fan_auto.pic=");
this->displayAdapter->print(this->climateCard->getFanSpeed() == AC_FAN_SPEED_AUTO ? PIC_AC_FAN_SPEED_AUTO_ACTIVE : PIC_AC_FAN_SPEED_AUTO_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("fan_low.pic=");
this->displayAdapter->print(this->climateCard->getFanSpeed() == AC_FAN_SPEED_LOW ? PIC_AC_FAN_SPEED_LOW_ACTIVE : PIC_AC_FAN_SPEED_LOW_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("fan_med.pic=");
this->displayAdapter->print(this->climateCard->getFanSpeed() == AC_FAN_SPEED_MEDIUM ? PIC_AC_FAN_SPEED_MEDIUM_ACTIVE : PIC_AC_FAN_SPEED_MEDIUM_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("fan_high.pic=");
this->displayAdapter->print(this->climateCard->getFanSpeed() == AC_FAN_SPEED_HIGH ? PIC_AC_FAN_SPEED_HIGH_ACTIVE : PIC_AC_FAN_SPEED_HIGH_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("mode_off.pic=");
this->displayAdapter->print(this->climateCard->getMode() == AC_MODE_OFF ? PIC_AC_MODE_OFF_ACTIVE : PIC_AC_MODE_OFF_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("mode_fan.pic=");
this->displayAdapter->print(this->climateCard->getMode() == AC_MODE_FAN_ONLY ? PIC_AC_MODE_FAN_ACTIVE : PIC_AC_MODE_FAN_INACTIVE);
this->sendStopBytes();
this->displayAdapter->print("mode_cool.pic=");
this->displayAdapter->print(this->climateCard->getMode() == AC_MODE_COOL ? PIC_AC_MODE_COOL_ACTIVE : PIC_AC_MODE_COOL_INACTIVE);
this->sendStopBytes();
if (this->climateCard->getSensorType() == AC_SENSOR_TYPE_DHT22) {
this->displayAdapter->print("roomtemp.txt=\"");
this->displayAdapter->print(this->climateCard->getRoomTemperature());
this->displayAdapter->print("C\"");
this->sendStopBytes();
this->displayAdapter->print("roomhumid.txt=\"");
this->displayAdapter->print(this->climateCard->getHumidity());
this->displayAdapter->print("%\"");
this->sendStopBytes();
}
else if(this->climateCard->getSensorType() == AC_SENSOR_TYPE_DS18B20) {
this->displayAdapter->print("roomtemp.txt=\"");
this->displayAdapter->print(this->climateCard->getRoomTemperature());
this->displayAdapter->print("C\"");
this->sendStopBytes();
this->setString("roomhumid.txt", "N/A");
}
else {
this->setString("roomtemp.txt", "N/A");
this->setString("roomhumid.txt", "N/A");
}
}
void InternalDisplay::setPWMAdjustmentSlider(uint16_t value) {
@ -225,6 +272,9 @@ void InternalDisplay::bindOutputCard(DigitalOutputCard *outputCard) {
this->outputCard = outputCard;
}
// This assume that your ClimeateCard has the mode and fan speed names in the following order:
// mode: [off, fan_only, cool]
// fan_speed: [auto, low, medium, high]
void InternalDisplay::bindClimateCard(ClimateCard *climateCard) {
this->climateCard = climateCard;
}
@ -281,7 +331,64 @@ void InternalDisplay::handleTouch(uint8_t page, uint8_t component, uint8_t type)
}
void InternalDisplay::handleACTouch(uint8_t type, uint8_t component) {
// b1 [component 18] -> inclement AC temperature by 1
// b0 [component 17] -> declement AC temperature by 1
// fan_auto [component 4] -> set the fan speed to auto
// fan_low [component 5] -> set the fan speed to low
// fan_med [component 6] -> set the fan speed to medium
// fan_high [component 7] -> set the fan speed to high
// mode_off [component 10] -> set the mode to off
// mode_fan [component 9] -> set the mode to fan only
// mode_cool [component 8] -> set the mode to cool
// For b0 and b1, if the type is not release then return
// For other components, if the type is not press then return
if ((component == 17 || component == 18) && type != TOUCH_TYPE_RELEASE) return;
if ((component != 17 && component != 18) && type != TOUCH_TYPE_PRESS) return;
// Switch based on the component
switch (component) {
case 17:
// Decrement the temperature
this->climateCard->setTemperature(this->climateCard->getTemperature() - 1);
break;
case 18:
// Increment the temperature
this->climateCard->setTemperature(this->climateCard->getTemperature() + 1);
break;
case 4:
// Set the fan speed to auto
this->climateCard->setFanSpeed(AC_FAN_SPEED_AUTO);
break;
case 5:
// Set the fan speed to low
this->climateCard->setFanSpeed(AC_FAN_SPEED_LOW);
break;
case 6:
// Set the fan speed to medium
this->climateCard->setFanSpeed(AC_FAN_SPEED_MEDIUM);
break;
case 7:
// Set the fan speed to high
this->climateCard->setFanSpeed(AC_FAN_SPEED_HIGH);
break;
case 10:
// Set the mode to off
this->climateCard->setMode(AC_MODE_OFF);
break;
case 9:
// Set the mode to fan only
this->climateCard->setMode(AC_MODE_FAN_ONLY);
break;
case 8:
// Set the mode to cool
this->climateCard->setMode(AC_MODE_COOL);
break;
default:
break;
}
// Refresh the AC page
this->refreshAC();
}
void InternalDisplay::handlePWMAdjustmentTouch(uint8_t type, uint8_t component) {

View file

@ -27,6 +27,29 @@
#define PIC_MQTT_CONNECTED 5
#define PIC_PWM_BAR_ON 33
#define PIC_PWM_BAR_OFF 48
#define PIC_AC_MODE_OFF_ACTIVE 24
#define PIC_AC_MODE_OFF_INACTIVE 25
#define PIC_AC_MODE_FAN_ACTIVE 22
#define PIC_AC_MODE_FAN_INACTIVE 23
#define PIC_AC_MODE_COOL_ACTIVE 12
#define PIC_AC_MODE_COOL_INACTIVE 13
#define PIC_AC_FAN_SPEED_AUTO_ACTIVE 14
#define PIC_AC_FAN_SPEED_AUTO_INACTIVE 15
#define PIC_AC_FAN_SPEED_LOW_ACTIVE 18
#define PIC_AC_FAN_SPEED_LOW_INACTIVE 19
#define PIC_AC_FAN_SPEED_MEDIUM_ACTIVE 20
#define PIC_AC_FAN_SPEED_MEDIUM_INACTIVE 21
#define PIC_AC_FAN_SPEED_HIGH_ACTIVE 16
#define PIC_AC_FAN_SPEED_HIGH_INACTIVE 17
// AC Fan Speeds and Mode Position Assumptions
#define AC_FAN_SPEED_AUTO 0
#define AC_FAN_SPEED_LOW 1
#define AC_FAN_SPEED_MEDIUM 2
#define AC_FAN_SPEED_HIGH 3
#define AC_MODE_OFF 0
#define AC_MODE_FAN_ONLY 1
#define AC_MODE_COOL 2
// Messages
#define MSG_MQTT_CONNECTED "BMS Managed"