From d2610b983f353a0ac33081f7c9de7b5a054e77a7 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 02:18:44 +0700 Subject: [PATCH 1/9] add iot-core support for analog expansion card --- src/espmega_iot_core.cpp | 343 ++++++++++++++++++++++++++++++++++++--- src/espmega_iot_core.hpp | 17 +- src/user_code.hpp | 4 + 3 files changed, 341 insertions(+), 23 deletions(-) diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index af1b163..a997d5d 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -92,23 +92,43 @@ char AC_ROOM_TEMPERATURE_TOPIC[75]; char AC_HUMIDITY_TOPIC[75]; #endif +#ifdef ENABLE_ANALOG_MODULE +#define DAC_COUNT 4 +#define ADC_COUNT 8 +bool dac_states[DAC_COUNT]; +uint16_t dac_values[DAC_COUNT]; +uint16_t adc_values[ADC_COUNT]; +bool adc_report_enable[ADC_COUNT]; + +char ADC_COMMAND_TOPIC[75]; +char ADC_STATE_TOPIC[75]; +char ADC_REPORT_TOPIC[75]; +char DAC_SET_STATE_TOPIC[75]; +char DAC_SET_VALUE_TOPIC[75]; +char DAC_STATE_TOPIC[75]; +char DAC_VALUE_TOPIC[75]; +#endif + // EEPROM ADDRESS -#define EEPROM_ADDRESS_AC_MODE 0 // 01bytes -#define EEPROM_ADDRESS_AC_TEMPERATURE 1 // 01bytes -#define EEPROM_ADDRESS_AC_FAN_SPEED 2 // 01bytes -#define EEPROM_ADDRESS_PWM_STATE 3 // 16bytes, thru 18 -#define EEPROM_ADDRESS_PWM_VALUE 19 // 32bytes, thru 50 -#define EEPROM_ADDRESS_HOSTNAME 65 // 15bytes, thru 79 -#define EEPROM_ADDRESS_TOPIC 80 // 20bytes, thru 99 -#define EEPROM_ADDRESS_IP 100 // 04bytes, thru 103 -#define EEPROM_ADDRESS_SUBNET 104 // 04bytes, thru 107 -#define EEPROM_ADDRESS_GATEWAY 108 // 04bytes, thru 111 -#define EEPROM_ADDRESS_DNS 112 // 04bytes, thru 115 -#define EEPROM_ADDRESS_MQTT_SERVER 116 // 04bytes, thru 119 -#define EEPROM_ADDRESS_MQTT_PORT 120 // 02bytes, thru 121 -#define EEPROM_ADDRESS_MQTT_USERNAME 122 // 32bytes, thru 153 -#define EEPROM_ADDRESS_MQTT_PASSWORD 154 // 32bytes, thru 185 -#define EEPROM_ADDRESS_MQTT_USEAUTH 186 // 1bytes +#define EEPROM_ADDRESS_AC_MODE 0 // 01bytes +#define EEPROM_ADDRESS_AC_TEMPERATURE 1 // 01bytes +#define EEPROM_ADDRESS_AC_FAN_SPEED 2 // 01bytes +#define EEPROM_ADDRESS_PWM_STATE 3 // 16bytes, thru 18 +#define EEPROM_ADDRESS_PWM_VALUE 19 // 32bytes, thru 50 +#define EEPROM_ADDRESS_HOSTNAME 65 // 15bytes, thru 79 +#define EEPROM_ADDRESS_TOPIC 80 // 20bytes, thru 99 +#define EEPROM_ADDRESS_IP 100 // 04bytes, thru 103 +#define EEPROM_ADDRESS_SUBNET 104 // 04bytes, thru 107 +#define EEPROM_ADDRESS_GATEWAY 108 // 04bytes, thru 111 +#define EEPROM_ADDRESS_DNS 112 // 04bytes, thru 115 +#define EEPROM_ADDRESS_MQTT_SERVER 116 // 04bytes, thru 119 +#define EEPROM_ADDRESS_MQTT_PORT 120 // 02bytes, thru 121 +#define EEPROM_ADDRESS_MQTT_USERNAME 122 // 32bytes, thru 153 +#define EEPROM_ADDRESS_MQTT_PASSWORD 154 // 32bytes, thru 185 +#define EEPROM_ADDRESS_MQTT_USEAUTH 186 // 1bytes +#define EEPROM_ADDRESS_ADC_REPORT_STATE 187 // 8bytes, thru 194 +#define EEPROM_ADDRESS_DAC_STATE 195 // 4bytes, thru 198 +#define EEPROM_ADDRESS_DAC_VALUE 199 // 8bytes, thru 206 char PWM_STATE_TOPIC[75]; char PWM_VALUE_TOPIC[75]; @@ -125,7 +145,8 @@ Thread mqtt_reconnector = Thread(); Thread environment_reporter = Thread(); Thread eeprom_pwm_updater = Thread(); Thread user_timer_tick = Thread(); -StaticThreadController<4> thread_controller(&mqtt_reconnector, &environment_reporter, &eeprom_pwm_updater, &user_timer_tick); +Thread analog_handler = Thread(); +StaticThreadController<5> thread_controller(&mqtt_reconnector, &environment_reporter, &eeprom_pwm_updater, &user_timer_tick, &analog_handler); #ifdef ENABLE_INTERNAL_LCD Thread top_bar_updater = Thread(); @@ -144,12 +165,12 @@ void setup() #endif Serial.println("ESPMega R3 Initializing"); ESPMega_begin(); - #ifdef OVERCLOCK_FM2 +#ifdef OVERCLOCK_FM2 Wire.setClock(1000000); - #endif - #ifdef OVERCLOCK_FM +#endif +#ifdef OVERCLOCK_FM Wire.setClock(400000); - #endif +#endif io_begin(); eeprom_retrieve_init(); user_pre_init(); @@ -297,6 +318,30 @@ void eeprom_retrieve_init() strcat(PWM_VALUE_TOPIC, "/pwm/00/value"); memcpy(INPUTS_TOPIC, MQTT_BASE_TOPIC, 20); strcat(INPUTS_TOPIC, "/input/00"); +#ifdef ENABLE_ANALOG_MODULE + memcpy(ADC_COMMAND_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(ADC_COMMAND_TOPIC, "/adc/00/set/state"); + memcpy(ADC_STATE_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(ADC_STATE_TOPIC, "/adc/00/state"); + memcpy(ADC_REPORT_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(ADC_REPORT_TOPIC, "/adc/00/report"); + memcpy(DAC_SET_STATE_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(DAC_SET_STATE_TOPIC, "/dac/00/set/state"); + memcpy(DAC_SET_VALUE_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(DAC_SET_VALUE_TOPIC, "/dac/00/set/value"); + memcpy(DAC_STATE_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(DAC_STATE_TOPIC, "/dac/00/state"); + memcpy(DAC_VALUE_TOPIC, MQTT_BASE_TOPIC, 20); + strcat(DAC_VALUE_TOPIC, "/dac/00/value"); + ESPMega_FRAM.read(EEPROM_ADDRESS_ADC_REPORT_STATE, (uint8_t *)adc_report_enable, 8); + ESPMega_FRAM.read(EEPROM_ADDRESS_DAC_STATE, (uint8_t *)dac_states, 4); + ESPMega_FRAM.read(EEPROM_ADDRESS_DAC_VALUE, (uint8_t *)dac_values, 8); + for (int i = 0; i < DAC_COUNT; i++) + { + dac_set_state(i, dac_states[i]); + dac_set_value(i, dac_values[i]); + } +#endif } #ifdef ENABLE_WEBUI @@ -572,6 +617,23 @@ void mqtt_subscribe() mqtt.subscribe(AC_SET_MODE_TOPIC); #endif mqtt.subscribe(STATE_REQUEST_TOPIC); +#ifdef ENABLE_ANALOG_MODULE + for (int i = 0; i < ADC_COUNT; i++) + { + ADC_COMMAND_TOPIC[base_topic_length + 4] = ((i - i % 10) / 10) + '0'; + ADC_COMMAND_TOPIC[base_topic_length + 5] = (i % 10) + '0'; + mqtt.subscribe(ADC_COMMAND_TOPIC); + } + for (int i = 0; i < DAC_COUNT; i++) + { + DAC_SET_STATE_TOPIC[base_topic_length + 4] = ((i - i % 10) / 10) + '0'; + DAC_SET_STATE_TOPIC[base_topic_length + 5] = (i % 10) + '0'; + DAC_SET_VALUE_TOPIC[base_topic_length + 4] = ((i - i % 10) / 10) + '0'; + DAC_SET_VALUE_TOPIC[base_topic_length + 5] = (i % 10) + '0'; + mqtt.subscribe(DAC_SET_STATE_TOPIC); + mqtt.subscribe(DAC_SET_VALUE_TOPIC); + } +#endif } /** @@ -597,6 +659,20 @@ void mqtt_callback(char *topic, byte *payload, unsigned int length) { pwm_value_callback(topic_trim, topic_length, payload_nt, length); } +#ifdef ENABLE_ANALOG_MODULE + else if ((!strncmp(topic_trim, "/adc/", 5)) && !strncmp(topic_trim + 7, "/set/state", 10)) + { + adc_set_state_callback(topic_trim, topic_length, payload_nt, length); + } + else if ((!strncmp(topic_trim, "/dac/", 5)) && !strncmp(topic_trim + 7, "/set/state", 10)) + { + dac_set_state_callback(topic_trim, topic_length, payload_nt, length); + } + else if ((!strncmp(topic_trim, "/dac/", 5)) && !strncmp(topic_trim + 7, "/set/value", 10)) + { + dac_set_value_callback(topic_trim, topic_length, payload_nt, length); + } +#endif else if (!strcmp(topic, STATE_REQUEST_TOPIC)) { state_request_callback(); @@ -628,6 +704,10 @@ void thread_initialization() eeprom_pwm_updater.setInterval(1000); user_timer_tick.onRun(timer_tick_callback); user_timer_tick.setInterval(15000); +#ifdef ENABLE_ANALOG_MODULE + analog_handler.onRun(adc_loop); + analog_handler.setInterval(ANALOG_REPORTING_INTERVAL); +#endif } /** @@ -1747,4 +1827,223 @@ void check_boot_reset() { factory_reset(); } -} \ No newline at end of file +} + +#ifdef ENABLE_ANALOG_MODULE +/** + * Enables the ADC reporting for the specified ID. + * + * @param id The ID of the ADC to enable reporting for. + */ +void enable_adc(int id) +{ + adc_report_enable[id] = true; + ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 1); +} +/** + * @brief Disables the ADC reporting for the specified ID. + * + * This function sets the adc_report_enable flag to false for the specified ID and writes the state to the EEPROM. + * + * @param id The ID of the ADC to disable reporting for. + */ +void disable_adc(int id) +{ + adc_report_enable[id] = false; + ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 0); +} +/** + * @brief Updates the ADC value for the specified ID if ADC reporting is enabled. + * + * @param id The ID of the ADC channel. + */ +void adc_update(int id) +{ + if (adc_report_enable[id]) + { + adc_values[id] = ESPMega_analogRead(id); + } +} + +/** + * @brief Updates the ADC value for the specified ID, do so even if reporting is disabled.. + * + * @param id The ID of the ADC pin. + */ +void adc_update_force(int id) +{ + adc_values[id] = ESPMega_analogRead(id); +} + + +/** + * @brief Updates all ADC channels. + * + * This function updates all ADC channels by calling the `adc_update` function for each channel. + * + * @return void + */ +void adc_update_all() +{ + for (int i = 0; i < ADC_COUNT; i++) + { + adc_update(i); + } +} + +/** + * @brief Performs ADC loop operations. + * + * This function updates all ADC values and publishes them. + */ +void adc_loop() +{ + adc_update_all(); + publish_all_adc(); +} + +/** + * Publishes the ADC value to the MQTT broker. + * + * @param id The ID of the ADC channel. + */ +void publish_adc(int id) +{ + ADC_STATE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; + ADC_STATE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; + char temp[6]; + itoa(adc_values[id], temp, DEC); + mqtt.publish(ADC_STATE_TOPIC, temp); +} + +/** + * Publishes the values of all enabled ADC channels. + * This function iterates through all ADC channels and publishes the values + * of the enabled channels using the publish_adc() function. + */ +void publish_all_adc() +{ + for (int i = 0; i < ADC_COUNT; i++) + { + if (adc_report_enable[i]) + publish_adc(i); + } +} +/** + * @brief Retrieves the ADC value for the specified ID. + * + * This function checks if the ADC report is enabled for the given ID. If not, it forces an update. + * It then returns the ADC value for the specified ID. + * + * @param id The ID of the ADC channel. + * @return The ADC value for the specified ID. + */ +uint16_t get_adc_value(int id) +{ + if (!adc_report_enable[id]) + adc_update_force(id); + return adc_values[id]; +} + +/** + * @brief Sets the state of an ADC based on the received MQTT message. + * + * This function is called when an MQTT message is received to set the state of an ADC (Analog-to-Digital Converter). + * The function extracts the ADC ID from the topic and enables or disables the ADC based on the payload value. + * + * @param topic The topic of the MQTT message. + * @param topic_length The length of the topic. + * @param payload The payload of the MQTT message. + * @param payload_length The length of the payload. + */ +void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) +{ + int a = topic[4] - '0'; + int b = topic[5] - '0'; + int id = 10 * a + b; + if (!strcmp(payload, "on")) + { + enable_adc(id); + } + else if (!strcmp(payload, "off")) + { + disable_adc(id); + } +} + +/** + * @brief Sets the value of a DAC channel. + * + * This function sets the value of a DAC channel specified by the `id` parameter. + * The `value` parameter represents the desired value for the DAC channel. + * The function updates the internal DAC value array, writes the value to the DAC, + * and also stores the value in the FRAM memory. + * + * @param id The ID of the DAC channel. + * @param value The desired value for the DAC channel. + */ +void dac_set_value(int id, int value) +{ + dac_values[id] = value; + ESPMega_dacWrite(id, dac_values[id] * dac_states[id]); + ESPMega_FRAM.write16(EEPROM_ADDRESS_DAC_VALUE + id * 2, dac_values[id]); +} + +/** + * @brief Sets the state of a DAC channel. + * + * This function updates the state of a DAC channel and writes the new state to the DAC output. + * It also saves the state to the EEPROM for persistence across power cycles. + * + * @param id The ID of the DAC channel. + * @param state The new state of the DAC channel. + */ +void dac_set_state(int id, bool state) +{ + dac_states[id] = state; + ESPMega_dacWrite(id, dac_values[id] * dac_states[id]); + ESPMega_FRAM.write8(EEPROM_ADDRESS_DAC_STATE + id, dac_states[id]); +} + +/** + * @brief Sets the value of the DAC with a callback function. + * + * @param topic The topic of the message. + * @param topic_length The length of the topic string. + * @param payload The payload of the message. + * @param payload_length The length of the payload string. + */ +void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) +{ + int a = topic[4] - '0'; + int b = topic[5] - '0'; + int id = 10 * a + b; + int value = atoi(payload); + dac_set_value(id, value); +} +/** + * @brief Callback function for setting the state of the DAC. + * + * This function is called when a message is received on the specified topic. + * It takes the topic, topic length, payload, and payload length as parameters. + * + * @param topic The topic of the received message. + * @param topic_length The length of the topic string. + * @param payload The payload of the received message. + * @param payload_length The length of the payload string. + */ +void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) +{ + int a = topic[4] - '0'; + int b = topic[5] - '0'; + int id = 10 * a + b; + if (!strcmp(payload, "on")) + { + dac_set_state(id, true); + } + else if (!strcmp(payload, "off")) + { + dac_set_state(id, false); + } +} +#endif diff --git a/src/espmega_iot_core.hpp b/src/espmega_iot_core.hpp index f542632..a2eb29f 100644 --- a/src/espmega_iot_core.hpp +++ b/src/espmega_iot_core.hpp @@ -131,4 +131,19 @@ void eeprom_mqtt_useauth_retrieve(); void set_mqtt_useauth(bool use_auth); void factory_reset(); -void check_boot_reset(); \ No newline at end of file +void check_boot_reset(); + +void enable_adc(int id); +void disable_adc(int id); +void adc_update(int id); +void adc_update_force(int id); +void adc_update_all(); +void adc_loop(); +void publish_adc(int id); +void publish_all_adc(); +uint16_t get_adc_value(int id); +void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); +void dac_set_value(int id, int value); +void dac_set_state(int id, bool state); +void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); +void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); diff --git a/src/user_code.hpp b/src/user_code.hpp index f14d89b..0e04793 100644 --- a/src/user_code.hpp +++ b/src/user_code.hpp @@ -16,6 +16,7 @@ #define ENABLE_INTERNAL_LCD #define ENABLE_IR_MODULE #define ENABLE_CLIMATE_MODULE // Require IR Module +#define ENABLE_ANALOG_MODULE #define ENABLE_WEBUI // Infrared Transciever @@ -35,6 +36,9 @@ #define ESPMega_EXTLCD Serial2 #endif +// Analog Module Configuration +#define ANALOG_REPORTING_INTERVAL 500 + // User Defined Functions void user_pre_init(); void user_init(); From 1010dae0e69325b206232fe31198b710298af635 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 02:15:43 -0800 Subject: [PATCH 2/9] Add readme.md --- readme.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..16792ca --- /dev/null +++ b/readme.md @@ -0,0 +1,18 @@ +# IoT Core OS V3 +This is an OS for the ESPMega PRO R3 Programable Logic Controller + +## **Compatibility** +1. CPU + - ESPMega PRO R3.0a/b + - ESPMega PRO R3.1a + - ESPMega PRO R3.2a/b/c +2. CPU Add-ons + - ESPMega PRO Internal Display Module + - ESPMega PRO External Touch Display Module +3. Add-on Cards + - ESPMega I/O Analog Expansion Card + - ESPMega I/O IR Expansion Kit + - ESPMega I/O Card Hub + - ESPMega I/O UART Multiplexer [WIP] + - ESPMega I/O Digital Expansion Card [WIP] +## Features \ No newline at end of file From bb0838ad3048763a14054f9651f90fb961f6edd6 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 02:16:06 -0800 Subject: [PATCH 3/9] Update readme.md --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 16792ca..ffcefb2 100644 --- a/readme.md +++ b/readme.md @@ -2,14 +2,14 @@ This is an OS for the ESPMega PRO R3 Programable Logic Controller ## **Compatibility** -1. CPU +1. **CPU** - ESPMega PRO R3.0a/b - ESPMega PRO R3.1a - ESPMega PRO R3.2a/b/c -2. CPU Add-ons +2. **CPU Add-ons** - ESPMega PRO Internal Display Module - ESPMega PRO External Touch Display Module -3. Add-on Cards +3. **Add-on Cards** - ESPMega I/O Analog Expansion Card - ESPMega I/O IR Expansion Kit - ESPMega I/O Card Hub From 557df3333ec7b1714ed9b33407401876cf4d626e Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 02:28:13 -0800 Subject: [PATCH 4/9] Update readme.md --- readme.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index ffcefb2..b0a4f7e 100644 --- a/readme.md +++ b/readme.md @@ -15,4 +15,21 @@ This is an OS for the ESPMega PRO R3 Programable Logic Controller - ESPMega I/O Card Hub - ESPMega I/O UART Multiplexer [WIP] - ESPMega I/O Digital Expansion Card [WIP] -## Features \ No newline at end of file + +## Features +- Internal Touch Display support for diagnostics and configuration +- WebUI for Configuration and OTA Update +- Allowing for reading and writing to registers from MQTT +- Provides abstraction layer to the MQTT protocol and internal components + +## User Code and 3rd Party Extension +This OS allows the user to write custom program for the device to run in the OS
+### *usercode.hpp* and *user_code.cpp* +### I/O Abstraction Layer +### MQTT Abstraction Layer +### RTC and Clock Abstraction Layer +### Persistent Storage Abstraction Layer +### Climate Abstraction Layer +### Energy Monitoring Abstraction Layer +### Timer Abstraction Layer +### LCD Abstraction Layer From 549500822ccda0edb839a3637fc72e7dead8d03a Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 18:53:01 +0700 Subject: [PATCH 5/9] update state publishing --- src/espmega_iot_core.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/espmega_iot_core.hpp | 4 ++++ 2 files changed, 44 insertions(+) diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index a997d5d..303df07 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -579,6 +579,9 @@ void mqtt_connect() publish_ac_state(); #endif mqtt_connected_user_callback(); + publish_dac_states(); + publish_dac_values(); + publish_all_adc(); standalone = false; ESPMega_updateTimeFromNTP(); } @@ -1004,6 +1007,9 @@ void state_request_callback() publish_env_state(); #endif user_state_request_callback(); + publish_all_adc(); + publish_dac_states(); + publish_dac_values(); } #ifdef ENABLE_IR_MODULE @@ -1929,6 +1935,22 @@ void publish_all_adc() publish_adc(i); } } + +void publish_dac_state(int id) +{ + DAC_STATE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; + DAC_STATE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; + mqtt.publish(DAC_STATE_TOPIC, dac_states[id] ? "on" : "off"); +} + +void publish_dac_value(int id) { + DAC_VALUE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; + DAC_VALUE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; + char temp[6]; + itoa(dac_values[id], temp, DEC); + mqtt.publish(DAC_VALUE_TOPIC, temp); +} + /** * @brief Retrieves the ADC value for the specified ID. * @@ -1987,6 +2009,7 @@ void dac_set_value(int id, int value) dac_values[id] = value; ESPMega_dacWrite(id, dac_values[id] * dac_states[id]); ESPMega_FRAM.write16(EEPROM_ADDRESS_DAC_VALUE + id * 2, dac_values[id]); + publish_dac_value(id); } /** @@ -2003,6 +2026,23 @@ void dac_set_state(int id, bool state) dac_states[id] = state; ESPMega_dacWrite(id, dac_values[id] * dac_states[id]); ESPMega_FRAM.write8(EEPROM_ADDRESS_DAC_STATE + id, dac_states[id]); + publish_dac_state(id); +} + +void publish_dac_states() +{ + for (int i = 0; i < DAC_COUNT; i++) + { + publish_dac_state(i); + } +} + +void publish_dac_values() +{ + for (int i = 0; i < DAC_COUNT; i++) + { + publish_dac_value(i); + } } /** diff --git a/src/espmega_iot_core.hpp b/src/espmega_iot_core.hpp index a2eb29f..9e48e06 100644 --- a/src/espmega_iot_core.hpp +++ b/src/espmega_iot_core.hpp @@ -147,3 +147,7 @@ void dac_set_value(int id, int value); void dac_set_state(int id, bool state); void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); +void publish_dac_value(int id); +void publish_dac_state(int id); +void publish_dac_values(); +void publish_dac_states(); \ No newline at end of file From 62f774964d04a074bea5602d873957889062767f Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 19:44:05 +0700 Subject: [PATCH 6/9] fix adc reporting bug --- src/espmega_iot_core.cpp | 55 ++++++++++++++++++++++++++++------------ src/espmega_iot_core.hpp | 8 +++--- src/user_code.hpp | 2 +- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index 303df07..cf087c2 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -581,7 +581,7 @@ void mqtt_connect() mqtt_connected_user_callback(); publish_dac_states(); publish_dac_values(); - publish_all_adc(); + publish_adc_values(); standalone = false; ESPMega_updateTimeFromNTP(); } @@ -1007,7 +1007,7 @@ void state_request_callback() publish_env_state(); #endif user_state_request_callback(); - publish_all_adc(); + publish_adc_values(); publish_dac_states(); publish_dac_values(); } @@ -1845,6 +1845,8 @@ void enable_adc(int id) { adc_report_enable[id] = true; ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 1); + publish_adc_state(id); + Serial.println("ADC " + String(id) + " enabled."); } /** * @brief Disables the ADC reporting for the specified ID. @@ -1857,7 +1859,25 @@ void disable_adc(int id) { adc_report_enable[id] = false; ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 0); + publish_adc_state(id); + Serial.println("ADC " + String(id) + " disabled."); } + +void publish_adc_state(int id) +{ + ADC_STATE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; + ADC_STATE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; + mqtt.publish(ADC_STATE_TOPIC, adc_report_enable[id] ? "on" : "off"); +} + +void publish_adc_states() +{ + for (int i = 0; i < ADC_COUNT; i++) + { + publish_adc_state(i); + } +} + /** * @brief Updates the ADC value for the specified ID if ADC reporting is enabled. * @@ -1869,6 +1889,7 @@ void adc_update(int id) { adc_values[id] = ESPMega_analogRead(id); } + } /** @@ -1905,7 +1926,7 @@ void adc_update_all() void adc_loop() { adc_update_all(); - publish_all_adc(); + publish_adc_values(); } /** @@ -1913,13 +1934,13 @@ void adc_loop() * * @param id The ID of the ADC channel. */ -void publish_adc(int id) +void publish_adc_value(int id) { - ADC_STATE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; - ADC_STATE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; - char temp[6]; + ADC_REPORT_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; + ADC_REPORT_TOPIC[base_topic_length + 5] = (id % 10) + '0'; + char temp[8]; itoa(adc_values[id], temp, DEC); - mqtt.publish(ADC_STATE_TOPIC, temp); + mqtt.publish(ADC_REPORT_TOPIC, temp); } /** @@ -1927,12 +1948,12 @@ void publish_adc(int id) * This function iterates through all ADC channels and publishes the values * of the enabled channels using the publish_adc() function. */ -void publish_all_adc() +void publish_adc_values() { for (int i = 0; i < ADC_COUNT; i++) { if (adc_report_enable[i]) - publish_adc(i); + publish_adc_value(i); } } @@ -1980,9 +2001,11 @@ uint16_t get_adc_value(int id) */ void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - int a = topic[4] - '0'; - int b = topic[5] - '0'; + Serial.println(topic); + int a = topic[5] - '0'; + int b = topic[6] - '0'; int id = 10 * a + b; + Serial.println("ID = "+String(id)); if (!strcmp(payload, "on")) { enable_adc(id); @@ -2055,8 +2078,8 @@ void publish_dac_values() */ void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - int a = topic[4] - '0'; - int b = topic[5] - '0'; + int a = topic[5] - '0'; + int b = topic[6] - '0'; int id = 10 * a + b; int value = atoi(payload); dac_set_value(id, value); @@ -2074,8 +2097,8 @@ void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, un */ void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - int a = topic[4] - '0'; - int b = topic[5] - '0'; + int a = topic[5] - '0'; + int b = topic[6] - '0'; int id = 10 * a + b; if (!strcmp(payload, "on")) { diff --git a/src/espmega_iot_core.hpp b/src/espmega_iot_core.hpp index 9e48e06..531735a 100644 --- a/src/espmega_iot_core.hpp +++ b/src/espmega_iot_core.hpp @@ -139,8 +139,8 @@ void adc_update(int id); void adc_update_force(int id); void adc_update_all(); void adc_loop(); -void publish_adc(int id); -void publish_all_adc(); +void publish_adc_value(int id); +void publish_adc_values(); uint16_t get_adc_value(int id); void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length); void dac_set_value(int id, int value); @@ -150,4 +150,6 @@ void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, un void publish_dac_value(int id); void publish_dac_state(int id); void publish_dac_values(); -void publish_dac_states(); \ No newline at end of file +void publish_dac_states(); +void publish_adc_state(int id); +void publish_adc_states(); \ No newline at end of file diff --git a/src/user_code.hpp b/src/user_code.hpp index 0e04793..b6206e2 100644 --- a/src/user_code.hpp +++ b/src/user_code.hpp @@ -13,7 +13,7 @@ //#define OVERCLOCK_FM2 // Enable Software Module(s) -#define ENABLE_INTERNAL_LCD +//#define ENABLE_INTERNAL_LCD #define ENABLE_IR_MODULE #define ENABLE_CLIMATE_MODULE // Require IR Module #define ENABLE_ANALOG_MODULE From ef43526d2cfa6d2dff20fade549426a2083797b9 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 19:46:58 +0700 Subject: [PATCH 7/9] cleanup debug prints --- src/espmega_iot_core.cpp | 47 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index cf087c2..e8713c9 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -579,9 +579,12 @@ void mqtt_connect() publish_ac_state(); #endif mqtt_connected_user_callback(); +#ifdef ENABLE_ANALOG_MODULE publish_dac_states(); publish_dac_values(); publish_adc_values(); + publish_adc_states(); +#endif standalone = false; ESPMega_updateTimeFromNTP(); } @@ -1007,9 +1010,12 @@ void state_request_callback() publish_env_state(); #endif user_state_request_callback(); +#ifdef ENABLE_ANALOG_MODULE + publish_adc_states(); publish_adc_values(); publish_dac_states(); publish_dac_values(); +#endif } #ifdef ENABLE_IR_MODULE @@ -1846,7 +1852,6 @@ void enable_adc(int id) adc_report_enable[id] = true; ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 1); publish_adc_state(id); - Serial.println("ADC " + String(id) + " enabled."); } /** * @brief Disables the ADC reporting for the specified ID. @@ -1860,7 +1865,6 @@ void disable_adc(int id) adc_report_enable[id] = false; ESPMega_FRAM.write8(EEPROM_ADDRESS_ADC_REPORT_STATE + id, 0); publish_adc_state(id); - Serial.println("ADC " + String(id) + " disabled."); } void publish_adc_state(int id) @@ -1880,7 +1884,7 @@ void publish_adc_states() /** * @brief Updates the ADC value for the specified ID if ADC reporting is enabled. - * + * * @param id The ID of the ADC channel. */ void adc_update(int id) @@ -1889,12 +1893,11 @@ void adc_update(int id) { adc_values[id] = ESPMega_analogRead(id); } - } /** * @brief Updates the ADC value for the specified ID, do so even if reporting is disabled.. - * + * * @param id The ID of the ADC pin. */ void adc_update_force(int id) @@ -1902,12 +1905,11 @@ void adc_update_force(int id) adc_values[id] = ESPMega_analogRead(id); } - /** * @brief Updates all ADC channels. - * + * * This function updates all ADC channels by calling the `adc_update` function for each channel. - * + * * @return void */ void adc_update_all() @@ -1920,7 +1922,7 @@ void adc_update_all() /** * @brief Performs ADC loop operations. - * + * * This function updates all ADC values and publishes them. */ void adc_loop() @@ -1931,7 +1933,7 @@ void adc_loop() /** * Publishes the ADC value to the MQTT broker. - * + * * @param id The ID of the ADC channel. */ void publish_adc_value(int id) @@ -1964,7 +1966,8 @@ void publish_dac_state(int id) mqtt.publish(DAC_STATE_TOPIC, dac_states[id] ? "on" : "off"); } -void publish_dac_value(int id) { +void publish_dac_value(int id) +{ DAC_VALUE_TOPIC[base_topic_length + 4] = ((id - id % 10) / 10) + '0'; DAC_VALUE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; char temp[6]; @@ -1974,10 +1977,10 @@ void publish_dac_value(int id) { /** * @brief Retrieves the ADC value for the specified ID. - * + * * This function checks if the ADC report is enabled for the given ID. If not, it forces an update. * It then returns the ADC value for the specified ID. - * + * * @param id The ID of the ADC channel. * @return The ADC value for the specified ID. */ @@ -1990,10 +1993,10 @@ uint16_t get_adc_value(int id) /** * @brief Sets the state of an ADC based on the received MQTT message. - * + * * This function is called when an MQTT message is received to set the state of an ADC (Analog-to-Digital Converter). * The function extracts the ADC ID from the topic and enables or disables the ADC based on the payload value. - * + * * @param topic The topic of the MQTT message. * @param topic_length The length of the topic. * @param payload The payload of the MQTT message. @@ -2001,11 +2004,9 @@ uint16_t get_adc_value(int id) */ void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - Serial.println(topic); int a = topic[5] - '0'; int b = topic[6] - '0'; int id = 10 * a + b; - Serial.println("ID = "+String(id)); if (!strcmp(payload, "on")) { enable_adc(id); @@ -2018,12 +2019,12 @@ void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, un /** * @brief Sets the value of a DAC channel. - * + * * This function sets the value of a DAC channel specified by the `id` parameter. * The `value` parameter represents the desired value for the DAC channel. * The function updates the internal DAC value array, writes the value to the DAC, * and also stores the value in the FRAM memory. - * + * * @param id The ID of the DAC channel. * @param value The desired value for the DAC channel. */ @@ -2037,10 +2038,10 @@ void dac_set_value(int id, int value) /** * @brief Sets the state of a DAC channel. - * + * * This function updates the state of a DAC channel and writes the new state to the DAC output. * It also saves the state to the EEPROM for persistence across power cycles. - * + * * @param id The ID of the DAC channel. * @param state The new state of the DAC channel. */ @@ -2086,10 +2087,10 @@ void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, un } /** * @brief Callback function for setting the state of the DAC. - * + * * This function is called when a message is received on the specified topic. * It takes the topic, topic length, payload, and payload length as parameters. - * + * * @param topic The topic of the received message. * @param topic_length The length of the topic string. * @param payload The payload of the received message. From 38a656ee55f862a81bff24fadf4479c45d960908 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 19:48:52 +0700 Subject: [PATCH 8/9] re enable lcd --- src/user_code.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/user_code.hpp b/src/user_code.hpp index b6206e2..0e04793 100644 --- a/src/user_code.hpp +++ b/src/user_code.hpp @@ -13,7 +13,7 @@ //#define OVERCLOCK_FM2 // Enable Software Module(s) -//#define ENABLE_INTERNAL_LCD +#define ENABLE_INTERNAL_LCD #define ENABLE_IR_MODULE #define ENABLE_CLIMATE_MODULE // Require IR Module #define ENABLE_ANALOG_MODULE From 47f5e325aa2aa9619afaa13baa7727f077ead335 Mon Sep 17 00:00:00 2001 From: Siwat Sirichai Date: Thu, 30 Nov 2023 19:50:54 +0700 Subject: [PATCH 9/9] move DHT22 pin def --- src/espmega_iot_core.cpp | 1 - src/user_code.hpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index e8713c9..64a7450 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -78,7 +78,6 @@ Mode 0: Off, 1: Cool, 2: Fan Fan Speed 0: Auto, 1: High, 2: Mid, 3: Low */ #ifdef ENABLE_CLIMATE_MODULE -#define DHT22_PIN 32 uint8_t ac_mode = 0; uint8_t ac_fan_speed = 0; uint8_t ac_temperature = 25; diff --git a/src/user_code.hpp b/src/user_code.hpp index 0e04793..395a6e4 100644 --- a/src/user_code.hpp +++ b/src/user_code.hpp @@ -19,13 +19,14 @@ #define ENABLE_ANALOG_MODULE #define ENABLE_WEBUI -// Infrared Transciever +// IR Kit Configuration #define IR_RECIEVE_PIN 35 #define IR_SEND_PIN 17 #define MARK_EXCESS_MICROS 20 #define RAW_BUFFER_LENGTH 750 #define AC_MAX_TEMPERATURE 30 #define AC_MIN_TEMPERATURE 15 +#define DHT22_PIN 32 // External LCD Configuration #define ENABLE_EXTERNAL_LCD