diff --git a/LICENSE b/LICENSE index 52d0bdb..b93eb01 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 stephan192 +Copyright (c) 2025 stephan192 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index d6f4578..b9cd74b 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,9 @@ The door drive is automatically added to Home Assistant via [MQTT Discovery](htt * USB-UART converter ## PIC16 -* MPLabX v5.25 -* XC8 v2.10 +* MPLabX v5.45 +* Device Family Pack PIC16F1xxxx_DFP 1.5.133 +* XC8 v2.32 * PICkit3 diff --git a/docs/device.png b/docs/device.png index 8753e1a..cf7c2da 100644 Binary files a/docs/device.png and b/docs/device.png differ diff --git a/docs/hoermann.md b/docs/hoermann.md index e754325..eac305c 100644 --- a/docs/hoermann.md +++ b/docs/hoermann.md @@ -63,8 +63,8 @@ Sender : Master * d0 bits: * `0`: door open * `1`: door closed - * `2`: external relay supposed to be switched on (relay 03 on UAP1) - * `3`: light relay (not 100% sure) + * `2`: optional/external relay (relay 03 on UAP1) + * `3`: light relay * `4`: error active * `5`: direction when moving (=1 closing, =0 opening) * `6`: door is moving @@ -119,7 +119,7 @@ Sender: Slave * d0 bits: * `0`: Trigger open door * `1`: Trigger close door - * `2`: Trigger reverse direction (not 100% sure) + * `2`: Trigger impulse (stop if door is moving, reverse direction if stopped, behaviour like the button on the remote control) * `3`: Toggle light relais * `4`: Trigger venting position * `5`: ??? diff --git a/esp8266/esp8266.ino b/esp8266/esp8266.ino index 47e0a95..3c6e86d 100644 --- a/esp8266/esp8266.ino +++ b/esp8266/esp8266.ino @@ -8,7 +8,7 @@ #include "hoermann.h" #define HW_VERSION "v1" -#define SW_VERSION "v2" +#define SW_VERSION "v3" WiFiClient espClient; PubSubClient client(MQTT_SERVER, MQTT_PORT, espClient); @@ -34,6 +34,8 @@ String light_state_topic; String error_state_topic; String prewarn_state_topic; String option_relay_state_topic; +String emergency_stop_cmd_topic; +String impulse_cmd_topic; String bme_avty_topic; String bme_state_topic; @@ -358,6 +360,9 @@ void setup_mqtt_topics() { prewarn_state_topic = "homeassistant/binary_sensor/" + unique_id + "_prewarn/state"; option_relay_state_topic = "homeassistant/binary_sensor/" + unique_id + "_option_relay/state"; + emergency_stop_cmd_topic = "homeassistant/button/" + unique_id + "_emergency_stop/trigger"; + impulse_cmd_topic = "homeassistant/button/" + unique_id + "_impulse/trigger"; + bme_avty_topic = "homeassistant/sensor/" + unique_id + "_bme/availability"; bme_state_topic = "homeassistant/sensor/" + unique_id + "_bme/state"; } @@ -366,6 +371,8 @@ void mqtt_init_publish_and_subscribe() { mqtt.subscribe(cover_cmd_topic, cover_cmd_subscriber); mqtt.subscribe(venting_cmd_topic, venting_cmd_subscriber); mqtt.subscribe(light_cmd_topic, light_cmd_subscriber); + mqtt.subscribe(emergency_stop_cmd_topic, emergency_stop_cmd_subscriber); + mqtt.subscribe(impulse_cmd_topic, impulse_cmd_subscriber); mqtt.publish(cover_avty_topic, "online", true); if (bme_detected) @@ -387,39 +394,47 @@ void publish_mqtt_autodiscovery() { obj_id.toLowerCase(); topic = "homeassistant/cover/" + unique_id + "_cover/config"; - payload = "{\"~\":\"homeassistant/cover/" + unique_id + "_cover\", \"avty_t\":\"~/availability\", \"cmd_t\":\"~/command\", " + device + ", \"dev_cla\":\"garage\", \"name\":\"Garage door\", \"obj_id\":\"" + obj_id + "_cover\", \"pos_t\":\"~/position\", \"uniq_id\":\"" + unique_id + "_cover\"}"; + payload = "{\"~\":\"homeassistant/cover/" + unique_id + "_cover\", \"avty_t\":\"~/availability\", \"cmd_t\":\"~/command\", " + device + ", \"dev_cla\":\"garage\", \"name\":\"Garage door\", \"obj_id\":\"" + obj_id + "_cover\", \"pos_t\":\"~/position\", \"uniq_id\":\"" + unique_id + "_cover\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/switch/" + unique_id + "_venting/config"; - payload = "{\"~\":\"homeassistant/switch/" + unique_id + "_venting\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"~/command\", " + device + ", \"icon\":\"mdi:hvac\", \"name\":\"Venting\", \"obj_id\":\"" + obj_id + "_venting\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_venting\"}"; + payload = "{\"~\":\"homeassistant/switch/" + unique_id + "_venting\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"~/command\", " + device + ", \"icon\":\"mdi:fan\", \"name\":\"Venting\", \"obj_id\":\"" + obj_id + "_venting\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_venting\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/switch/" + unique_id + "_light/config"; - payload = "{\"~\":\"homeassistant/switch/" + unique_id + "_light\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"~/command\", " + device + ", \"icon\":\"mdi:lightbulb\", \"name\":\"Light\", \"obj_id\":\"" + obj_id + "_light\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_light\"}"; + payload = "{\"~\":\"homeassistant/switch/" + unique_id + "_light\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"~/command\", " + device + ", \"icon\":\"mdi:lightbulb\", \"name\":\"Light\", \"obj_id\":\"" + obj_id + "_light\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_light\", \"en\":\"false\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/binary_sensor/" + unique_id + "_error/config"; - payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_error\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"dev_cla\":\"problem\", \"name\":\"Error\", \"obj_id\":\"" + obj_id + "_error\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_error\"}"; + payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_error\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"dev_cla\":\"problem\", \"name\":\"Error\", \"obj_id\":\"" + obj_id + "_error\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_error\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/binary_sensor/" + unique_id + "_prewarn/config"; - payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_prewarn\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"dev_cla\":\"safety\", \"name\":\"Prewarn\", \"obj_id\":\"" + obj_id + "_prewarn\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_prewarn\"}"; + payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_prewarn\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"dev_cla\":\"safety\", \"name\":\"Prewarn\", \"obj_id\":\"" + obj_id + "_prewarn\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_prewarn\", \"en\":\"false\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/binary_sensor/" + unique_id + "_option_relay/config"; - payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_option_relay\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"name\":\"Option relay\", \"obj_id\":\"" + obj_id + "_option_relay\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_option_relay\"}"; + payload = "{\"~\":\"homeassistant/binary_sensor/" + unique_id + "_option_relay\", \"avty_t\":\"" + cover_avty_topic + "\", " + device + ", \"name\":\"Option relay\", \"obj_id\":\"" + obj_id + "_option_relay\", \"stat_t\":\"~/state\", \"uniq_id\":\"" + unique_id + "_option_relay\", \"en\":\"false\"}"; + publish_oversize_payload(topic, payload, true); + + topic = "homeassistant/button/" + unique_id + "_emergency_stop/config"; + payload = "{\"~\":\"homeassistant/button/" + unique_id + "_emergency_stop\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"homeassistant/button/" + unique_id + "_emergency_stop/trigger\", " + device + ", \"icon\":\"mdi:close-octagon\", \"name\":\"Emergency stop\", \"obj_id\":\"" + obj_id + "_emergency_stop\", \"uniq_id\":\"" + unique_id + "_emergency_stop\", \"en\":\"false\"}"; + publish_oversize_payload(topic, payload, true); + + topic = "homeassistant/button/" + unique_id + "_impulse/config"; + payload = "{\"~\":\"homeassistant/button/" + unique_id + "_impulse\", \"avty_t\":\"" + cover_avty_topic + "\", \"cmd_t\":\"homeassistant/button/" + unique_id + "_impulse/trigger\", " + device + ", \"icon\":\"mdi:arrow-up-down\", \"name\":\"Impulse\", \"obj_id\":\"" + obj_id + "_impulse\", \"uniq_id\":\"" + unique_id + "_impulse\", \"en\":\"false\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/sensor/" + unique_id + "_temperature/config"; - payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"temperature\", \"name\":\"Temperature\", \"obj_id\":\"" + obj_id + "_temperature\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_temperature\", \"unit_of_meas\":\"\u00b0C\", \"val_tpl\":\"{{value_json.temperature_C|round(1)}}\"}"; + payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"temperature\", \"name\":\"Temperature\", \"obj_id\":\"" + obj_id + "_temperature\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_temperature\", \"unit_of_meas\":\"\u00b0C\", \"val_tpl\":\"{{value_json.temperature_C|round(1)}}\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/sensor/" + unique_id + "_humidity/config"; - payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"humidity\", \"name\":\"Humidity\", \"obj_id\":\"" + obj_id + "_humidity\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_humidity\", \"unit_of_meas\":\"%\", \"val_tpl\":\"{{value_json.humidity|round(0)}}\"}"; + payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"humidity\", \"name\":\"Humidity\", \"obj_id\":\"" + obj_id + "_humidity\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_humidity\", \"unit_of_meas\":\"%\", \"val_tpl\":\"{{value_json.humidity|round(0)}}\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); topic = "homeassistant/sensor/" + unique_id + "_pressure/config"; - payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"pressure\", \"name\":\"Pressure\", \"obj_id\":\"" + obj_id + "_pressure\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_pressure\", \"unit_of_meas\":\"hPa\", \"val_tpl\":\"{{value_json.pressure_hPa|round(1)}}\"}"; + payload = "{\"avty\":[{\"topic\":\"" + cover_avty_topic + "\"}, {\"topic\":\"" + bme_avty_topic + "\"}], \"avty_mode\":\"all\", " + device + ", \"dev_cla\":\"pressure\", \"name\":\"Pressure\", \"obj_id\":\"" + obj_id + "_pressure\", \"stat_cla\":\"measurement\", \"stat_t\":\"" + bme_state_topic + "\", \"uniq_id\":\"" + unique_id + "_pressure\", \"unit_of_meas\":\"hPa\", \"val_tpl\":\"{{value_json.pressure_hPa|round(1)}}\", \"en\":\"true\"}"; publish_oversize_payload(topic, payload, true); Serial.println("MQTT autodiscovery sent"); @@ -480,3 +495,19 @@ void light_cmd_subscriber(String topic, String message) door.trigger_action(hoermann_action_toggle_light); } } + +void emergency_stop_cmd_subscriber(String topic, String message) +{ + if (message == "PRESS") + { + door.trigger_action(hoermann_action_emergency_stop); + } +} + +void impulse_cmd_subscriber(String topic, String message) +{ + if (message == "PRESS") + { + door.trigger_action(hoermann_action_impulse); + } +} diff --git a/esp8266/hoermann.cpp b/esp8266/hoermann.cpp index eac90d3..990b4d0 100644 --- a/esp8266/hoermann.cpp +++ b/esp8266/hoermann.cpp @@ -6,6 +6,7 @@ Hoermann::Hoermann(void) { actual_state.data_valid = false; + actual_action = hoermann_action_none; } void Hoermann::loop(void) diff --git a/esp8266/hoermann.h b/esp8266/hoermann.h index 8747e68..fe97be6 100644 --- a/esp8266/hoermann.h +++ b/esp8266/hoermann.h @@ -30,6 +30,8 @@ typedef enum hoermann_action_close, hoermann_action_venting, hoermann_action_toggle_light, + hoermann_action_emergency_stop, + hoermann_action_impulse, hoermann_action_none } hoermann_action_t; diff --git a/pic16/hoermann.c b/pic16/hoermann.c index ef6c244..faf3bbc 100644 --- a/pic16/hoermann.c +++ b/pic16/hoermann.c @@ -18,11 +18,12 @@ #define CMD_SLAVE_STATUS_RESPONSE 0x29 #define RESPONSE_DEFAULT 0x1000 -#define RESPONSE_STOP 0x0000 +#define RESPONSE_EMERGENCY_STOP 0x0000 #define RESPONSE_OPEN 0x1001 #define RESPONSE_CLOSE 0x1002 #define RESPONSE_VENTING 0x1010 #define RESPONSE_TOGGLE_LIGHT 0x1008 +#define RESPONSE_IMPULSE 0x1004 #define CRC8_INITIAL_VALUE 0xF3 /* CRC table for polynomial 0x07 */ @@ -252,7 +253,11 @@ void hoermann_trigger_action(hoermann_action_t action) { case hoermann_action_stop: { - slave_respone_data = RESPONSE_STOP; + /* Motor needs only to be stopped if it is running */ + if (((broadcast_status & 0x60) == 0x40) || ((broadcast_status & 0x60) == 0x60)) + { + slave_respone_data = RESPONSE_IMPULSE; + } break; } case hoermann_action_open: @@ -275,6 +280,16 @@ void hoermann_trigger_action(hoermann_action_t action) slave_respone_data = RESPONSE_TOGGLE_LIGHT; break; } + case hoermann_action_emergency_stop: + { + slave_respone_data = RESPONSE_EMERGENCY_STOP; + break; + } + case hoermann_action_impulse: + { + slave_respone_data = RESPONSE_IMPULSE; + break; + } } } diff --git a/pic16/hoermann.h b/pic16/hoermann.h index 4d37e1e..46e4215 100644 --- a/pic16/hoermann.h +++ b/pic16/hoermann.h @@ -4,7 +4,9 @@ typedef enum hoermann_action_open = 1, hoermann_action_close = 2, hoermann_action_venting = 3, - hoermann_action_toggle_light = 4 + hoermann_action_toggle_light = 4, + hoermann_action_emergency_stop = 5, + hoermann_action_impulse = 6 } hoermann_action_t; extern void hoermann_init(void); diff --git a/pic16/nbproject/configurations.xml b/pic16/nbproject/configurations.xml index e9157e6..8d5a819 100644 --- a/pic16/nbproject/configurations.xml +++ b/pic16/nbproject/configurations.xml @@ -35,12 +35,14 @@ PICkit3PlatformTool XC8 - 2.10 + 2.32 3 - + + + @@ -58,6 +60,7 @@ false + false false @@ -68,6 +71,7 @@ + @@ -196,12 +200,14 @@ + +