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 @@
+
+