From 226922d3e408adc272fcf9a500f1630cc74c7858 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Fri, 12 May 2023 23:19:01 +0200 Subject: [PATCH] avr/reed: implemented tilt detection mode - implemented tilt detection mode - added docu - change the way a VALUE2 message is printed when value type is "door" --- aqhome/msg/msg_value2.c | 42 ++++++++-- aqhome/msg/msg_value2.h | 2 + avr/modules/comproto/MESSAGES | 27 ++++++ avr/modules/comproto/defs.asm | 52 +++++++----- avr/modules/reed/main.asm | 150 ++++++++++++++++++++++++++++++---- 5 files changed, 227 insertions(+), 46 deletions(-) diff --git a/aqhome/msg/msg_value2.c b/aqhome/msg/msg_value2.c index d6c9274..f73ec93 100644 --- a/aqhome/msg/msg_value2.c +++ b/aqhome/msg/msg_value2.c @@ -29,6 +29,7 @@ + uint32_t AQH_Value2Msg_GetUid(const GWEN_MSG *msg) { return GWEN_Msg_GetUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_VALUE2_UID, 0); @@ -72,6 +73,7 @@ const char *AQH_Value2Msg_GetValueTypeName(const GWEN_MSG *msg) switch(t) { case AQH_MSG_VALUE2_TYPE_TEMP: return "temperature"; case AQH_MSG_VALUE2_TYPE_HUMIDITY: return "humidity"; + case AQH_MSG_VALUE2_TYPE_DOOR: return "door/window"; default: break; } return "unknown"; @@ -79,6 +81,19 @@ const char *AQH_Value2Msg_GetValueTypeName(const GWEN_MSG *msg) +const char *AQH_Value2Msg_GetValueAsWindowStateString(const GWEN_MSG *msg) +{ + switch(AQH_Value2Msg_GetValueNom(msg)) { + case 0: return "closed"; + case 128: return "tilted"; + case 255: return "fully open"; + default: break; + } + return "unknown"; +} + + + double AQH_Value2Msg_GetValue(const GWEN_MSG *msg) { if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE2) && @@ -106,18 +121,27 @@ void AQH_Value2Msg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const ch { if ((AQH_NodeMsg_GetMsgType(msg)==AQH_MSG_TYPE_VALUE2) && (GWEN_Msg_GetBytesInBuffer(msg)>=AQH_MSG_VALUE2_MINSIZE)) { - GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE2 %s (uid=0x%08x, value_id=0x%02x type=%s value=%f)\n", - AQH_NodeMsg_GetSourceAddress(msg), - AQH_NodeMsg_GetDestAddress(msg), - sText, - (unsigned int) AQH_Value2Msg_GetUid(msg), - AQH_Value2Msg_GetValueId(msg), - AQH_Value2Msg_GetValueTypeName(msg), - AQH_Value2Msg_GetValue(msg)); + if (AQH_Value2Msg_GetValueType(msg)==AQH_MSG_VALUE2_TYPE_DOOR) + GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE2 %s (uid=0x%08x, value_id=0x%02x type=%s value=%s)\n", + AQH_NodeMsg_GetSourceAddress(msg), + AQH_NodeMsg_GetDestAddress(msg), + sText, + (unsigned int) AQH_Value2Msg_GetUid(msg), + AQH_Value2Msg_GetValueId(msg), + AQH_Value2Msg_GetValueTypeName(msg), + AQH_Value2Msg_GetValueAsWindowStateString(msg)); + else + GWEN_Buffer_AppendArgs(dbuf, "0x%02x->0x%02x: VALUE2 %s (uid=0x%08x, value_id=0x%02x type=%s value=%f)\n", + AQH_NodeMsg_GetSourceAddress(msg), + AQH_NodeMsg_GetDestAddress(msg), + sText, + (unsigned int) AQH_Value2Msg_GetUid(msg), + AQH_Value2Msg_GetValueId(msg), + AQH_Value2Msg_GetValueTypeName(msg), + AQH_Value2Msg_GetValue(msg)); } } - diff --git a/aqhome/msg/msg_value2.h b/aqhome/msg/msg_value2.h index 02fd909..11c46a0 100644 --- a/aqhome/msg/msg_value2.h +++ b/aqhome/msg/msg_value2.h @@ -20,6 +20,7 @@ #define AQH_MSG_VALUE2_TYPE_TEMP 1 #define AQH_MSG_VALUE2_TYPE_HUMIDITY 2 +#define AQH_MSG_VALUE2_TYPE_DOOR 3 @@ -31,6 +32,7 @@ AQHOME_API int16_t AQH_Value2Msg_GetValueDenom(const GWEN_MSG *msg); AQHOME_API double AQH_Value2Msg_GetValue(const GWEN_MSG *msg); +AQHOME_API const char *AQH_Value2Msg_GetValueAsWindowStateString(const GWEN_MSG *msg); AQHOME_API void AQH_Value2Msg_DumpToBuffer(const GWEN_MSG *msg, GWEN_BUFFER *dbuf, const char *sText); diff --git a/avr/modules/comproto/MESSAGES b/avr/modules/comproto/MESSAGES index a34a1e7..b58653a 100644 --- a/avr/modules/comproto/MESSAGES +++ b/avr/modules/comproto/MESSAGES @@ -302,6 +302,33 @@ Offset Length Meaning +Config Module Request Message +============================= + +Offset Length Meaning +--------------------------------------------------------- + 0 1 destination address + 1 1 remaining message length + 2 1 command code + 3 1 source address +--------------------------------------------------------- + 4 1 module id + 5 1 module command + 6 n command data (depending on module and command) + + + +Config Module Response Message +============================== + +Offset Length Meaning +--------------------------------------------------------- + 0 1 destination address + 1 1 remaining message length + 2 1 command code + 3 1 source address +--------------------------------------------------------- + 4 1 response code diff --git a/avr/modules/comproto/defs.asm b/avr/modules/comproto/defs.asm index 39ce2af..0d0772b 100644 --- a/avr/modules/comproto/defs.asm +++ b/avr/modules/comproto/defs.asm @@ -16,31 +16,34 @@ ; defines -.equ CPRO_CMD_PING = 10 -.equ CPRO_CMD_PONG = 11 -.equ CPRO_CMD_COMSENDSTATS = 20 -.equ CPRO_CMD_COMRECVSTATS = 21 -.equ CPRO_CMD_TWIBUSMEMBER = 30 -.equ CPRO_CMD_DEBUG = 40 -.equ CPRO_CMD_VALUE = 51 ; was 50 when sending timestamp instead of uid -.equ CPRO_CMD_NEED_ADDRESS = 60 -.equ CPRO_CMD_HAVE_ADDRESS = 61 -.equ CPRO_CMD_CLAIM_ADDRESS = 62 -.equ CPRO_CMD_DENY_ADDRESS = 63 -.equ CPRO_CMD_ADDRESS_RANGE = 64 +.equ CPRO_CMD_PING = 10 +.equ CPRO_CMD_PONG = 11 +.equ CPRO_CMD_COMSENDSTATS = 20 +.equ CPRO_CMD_COMRECVSTATS = 21 +.equ CPRO_CMD_TWIBUSMEMBER = 30 +.equ CPRO_CMD_DEBUG = 40 +.equ CPRO_CMD_VALUE = 51 ; was 50 when sending timestamp instead of uid +.equ CPRO_CMD_NEED_ADDRESS = 60 +.equ CPRO_CMD_HAVE_ADDRESS = 61 +.equ CPRO_CMD_CLAIM_ADDRESS = 62 +.equ CPRO_CMD_DENY_ADDRESS = 63 +.equ CPRO_CMD_ADDRESS_RANGE = 64 -.equ CPRO_CMD_FLASH_START = 70 -.equ CPRO_CMD_FLASH_END = 71 -.equ CPRO_CMD_FLASH_READY = 72 -.equ CPRO_CMD_FLASH_DATA = 73 -.equ CPRO_CMD_FLASH_RSP = 74 +.equ CPRO_CMD_FLASH_START = 70 +.equ CPRO_CMD_FLASH_END = 71 +.equ CPRO_CMD_FLASH_READY = 72 +.equ CPRO_CMD_FLASH_DATA = 73 +.equ CPRO_CMD_FLASH_RSP = 74 -.equ CPRO_CMD_DEVICE = 80 -.equ CPRO_CMD_MEMSTATS = 81 -.equ CPRO_CMD_SYSSTATS = 82 +.equ CPRO_CMD_DEVICE = 80 +.equ CPRO_CMD_MEMSTATS = 81 +.equ CPRO_CMD_SYSSTATS = 82 -.equ CPRO_CMD_REBOOT_REQUEST = 90 -.equ CPRO_CMD_REBOOT_RESPONSE = 91 +.equ CPRO_CMD_REBOOT_REQUEST = 90 +.equ CPRO_CMD_REBOOT_RESPONSE = 91 + +.equ CPRO_CMD_CONFIG_MODULE_REQUEST = 100 +.equ CPRO_CMD_CONFIG_MODULE_RESPONSE = 101 .equ CPRO_PACKET_HAVEADDR_OFFS_ADDRESS = COM2_MSG_OFFS_PAYLOAD+4 @@ -48,6 +51,11 @@ .equ CPRO_PACKET_DENYADDR_OFFS_ADDRESS = COM2_MSG_OFFS_PAYLOAD+4 .equ CPRO_PACKET_REBOOTREQ_OFFS_UID = COM2_MSG_OFFS_PAYLOAD+0 +.equ CPRO_PACKET_CFGMOD_REQUEST_OFFS_MODID = COM2_MSG_OFFS_PAYLOAD+0 +.equ CPRO_PACKET_CFGMOD_REQUEST_OFFS_MODCMD = COM2_MSG_OFFS_PAYLOAD+1 +.equ CPRO_PACKET_CFGMOD_REQUEST_OFFS_DATA = COM2_MSG_OFFS_PAYLOAD+2 + + .equ CPRO_WAITTIME_INITIAL = 10 .equ CPRO_WAITTIME_GETADDR = 130 .equ CPRO_WAITTIME_CLAIMADDR = 17 diff --git a/avr/modules/reed/main.asm b/avr/modules/reed/main.asm index 3ed6d0c..fdc1eb2 100644 --- a/avr/modules/reed/main.asm +++ b/avr/modules/reed/main.asm @@ -8,6 +8,41 @@ ; *************************************************************************** +; This module monitors up to two reed contacts to determine whether a windows +; door is open. +; +; It has two modes. +; +; Standard Mode +; ------------- +; +; In this mode up to two windows can be monitored. Each reed contact is reported on separately. +; If a window/door is open a value of 255 is reported, 0 otherwise. + +; Tilt Detect Mode +; ---------------- +; +; In this mode both reed sensors are handled together to determine whether a window +; or door is closed, tilted or fully open. +; - if exactly one of two reed contacts is open the window/door is reported as tilted (value 128) +; - if both reed contacts are open the window/door is reported as fully open (value 255) +; - if both reed contacts are closed the window/door is reported as closed (value 0) +; +; +; The window state is reported via the VALUE message with a value id of VALUE_ID_REED1 for the +; first reed contact (or for the whole window/door if in tilt detection mode), for the second +; reed contact a value id of VALUE_ID_REED2 is used. Value type is always AQHOME_VALUETYPE_DOOR +; (i.e. for doors and windows). +; +; There are basically two types of reed contacts. +; - normally closed (NC): The contact is closed as long as the magnet is near the switch. +; If the magnet is removed the contact opens. +; This is the default working mode of this module. +; - normally open (NO): The contact is open as long as the magnet is near the switch. +; If the magnet is removed the contact closes. +; To account for those different types of working modes this mode is configurable. + + ; The state byte contains the state for two reed contacts (one in each nibble). ; @@ -28,16 +63,25 @@ .equ REED_STATE_MASK_BEFORELAST = 0x2 .equ REED_STATE_MASK_LAST = 0x1 -.equ REED_STATE_MASK_LASTVALUES = 0x3 ; bits 0 and 1 -.equ REED_STATE_BIT_CURRENT = 3 -.equ REED_STATE_BIT_CHANGED = 2 +.equ REED_STATE_MASK_LASTVALUES = 0x3 ; bits 0 and 1 +.equ REED_STATE_BIT_CURRENT = 3 +.equ REED_STATE_BIT_CHANGED = 2 -.equ REED_CONFIG_MASK_SET = 0x80 -.equ REED_CONFIG_MASK_MULTI = 0x40 -.equ REED_CONFIG_MASK_NO = 0x20 ; if set: normally open (e.g. disconnected when magnet near) +.equ REED_CONFIG_MASK_SET = 0x80 +.equ REED_CONFIG_MASK_TILTDETECT = 0x40 ; use both reed contacts to detect tilted windows +.equ REED_CONFIG_MASK_NO = 0x20 ; if set: normally open (e.g. disconnected when magnet near) + +.equ REED_CONFIG_BIT_TILTDETECT = 6 +.equ REED_CONFIG_BIT_NO = 5 + + +.equ REED_INITIAL_CONFIG = REED_CONFIG_MASK_SET + + +.equ REED_CFGMOD_CMD_SETCONFIG = 1 ; only command for now + -.equ REED_INITIAL_CONFIG = REED_CONFIG_MASK_SET @@ -54,6 +98,9 @@ reedDataEnd: + + + ; *************************************************************************** ; code @@ -99,6 +146,7 @@ REED_Fini: REED_Run: + clc ; debug ret ; debug push r15 in r15, SREG @@ -106,6 +154,7 @@ REED_Run: rcall reedHandleChanges out SREG, r15 pop r15 + clc ret @@ -150,7 +199,8 @@ reedSetupConfig: brne reedSetupConfig_haveConfig reedSetupConfig_noConfig: ldi r16, REED_INITIAL_CONFIG - rcall Utils_WriteEepromIncr +; disabled for now +; debug rcall Utils_WriteEepromIncr reedSetupConfig_haveConfig: sts reedConfigFromEeprom, r16 reedSetupConfig_end: @@ -164,6 +214,20 @@ reedSetupConfig_end: ; @clobbers all reedHandleChanges: + lds r16, reedConfigFromEeprom + sbrc r16, REED_CONFIG_BIT_TILTDETECT + rjmp reedHandleChangesTiltDetectMode + rjmp reedHandleChangesSingleMode +; @end + + + +; --------------------------------------------------------------------------- +; @routine reedHandleChangesSingleMode +; +; @clobbers all + +reedHandleChangesSingleMode: lds r19, reedState ; reed 1 @@ -194,6 +258,54 @@ reedHandleChanges: +; --------------------------------------------------------------------------- +; @routine reedHandleChangesTiltDetectMode +; +; Handle changes in multi reed contact mode. +; This allows for detection of tilted windows/doors. +; +; @clobbers all + +reedHandleChangesTiltDetectMode: + lds r19, reedState + + mov r16, r19 + andi r16, (REED_STATE_MASK_CHANGED | (REED_STATE_MASK_CHANGED<<4)) + breq reedHandleChangesTiltDetectMode_end ; no changes + ; at least one contact changed, handle new state + clr r16 + sbrc r19, REED_STATE_BIT_CURRENT + inc r16 + sbrc r19, (REED_STATE_BIT_CURRENT+4) + inc r16 + ; no check for full state (0=closed, 1=tilted, 2=fully open) + tst r16 + breq reedHandleChangesTiltDetectMode_closed + cpi r16, 1 + breq reedHandleChangesTiltDetectMode_tilted + ; otherwise fully open, fallthrough + ldi r16, 255 + rjmp reedHandleChangesTiltDetectMode_sendChanges +reedHandleChangesTiltDetectMode_closed: + ldi r16, 0 + rjmp reedHandleChangesTiltDetectMode_sendChanges +reedHandleChangesTiltDetectMode_tilted: + ldi r16, 128 +reedHandleChangesTiltDetectMode_sendChanges: + ldi r17, VALUE_ID_REED1 + push r19 + rcall reedSendChange + pop r19 + brcc reedHandleChangesTiltDetectMode_end + ; changes handled, clear change flags and write back + andi r19, ~(REED_STATE_MASK_CHANGED | (REED_STATE_MASK_CHANGED<<4)) + sts reedState, r19 +reedHandleChangesTiltDetectMode_end: + ret +; @end + + + ; --------------------------------------------------------------------------- ; @routine reedSendValueIfChanged ; @@ -250,26 +362,34 @@ reedSendChange: ; ; Updates SDRAM variable reedState according to current pin states. ; -; @clobbers r16, r17, r18, r19 +; @clobbers r16, r17, r18, r19, r20 reedUpdateState: lds r19, reedState ; current reed state + lds r20, reedConfigFromEeprom + ; handle reed 1 (low nibble state) - rcall reedReadValue1 ; (r16) + rcall reedReadValue1 ; (r16) + sbrc r20, REED_CONFIG_BIT_NO + com r16 ; invert reed data if "normally open" contact + andi r16, 1 mov r17, r16 mov r16, r19 - rcall reedUpdateStateNibble ; (r18) + rcall reedUpdateStateNibble ; (r18) ; replace lower state nibble with new value - andi r16, 0x0f ; only keep low nibble - andi r19, 0xf0 ; clear out low nibble before or'ing new value in + andi r16, 0x0f ; only keep low nibble + andi r19, 0xf0 ; clear out low nibble before or'ing new value in or r19, r16 ; handle reed2 (high nibble state) - rcall reedReadValue2 ; (r16) + rcall reedReadValue2 ; (r16) + sbrc r20, REED_CONFIG_BIT_NO + com r16 ; invert reed data if "normally open" contact + andi r16, 1 mov r17, r16 mov r16, r19 swap r16 - rcall reedUpdateStateNibble ; (r18) + rcall reedUpdateStateNibble ; (r18) swap r16 ; replace higher state nibble with new value andi r16, 0xf0