diff --git a/platforms/BK723x/OpenBeken.mk b/platforms/BK723x/OpenBeken.mk index f827c8ece..da907cc5e 100644 --- a/platforms/BK723x/OpenBeken.mk +++ b/platforms/BK723x/OpenBeken.mk @@ -115,6 +115,7 @@ APP_C += $(OBK_DIR)/driver/drv_rn8209.c APP_C += $(OBK_DIR)/driver/drv_sgp.c APP_C += $(OBK_DIR)/driver/drv_shiftRegister.c APP_C += $(OBK_DIR)/driver/drv_sht3x.c +APP_C += $(OBK_DIR)/driver/drv_pir.c #APP_C += $(OBK_DIR)/driver/drv_sm15155e.c #APP_C += $(OBK_DIR)/driver/drv_sm16703P.c APP_C += $(OBK_DIR)/driver/drv_sm2135.c diff --git a/src/driver/drv_pir.c b/src/driver/drv_pir.c index 029c32c0b..4dc50d6b7 100644 --- a/src/driver/drv_pir.c +++ b/src/driver/drv_pir.c @@ -35,6 +35,7 @@ static int ch_lightAdc; // light level static int ch_motion; // pir 1 or 0 static int ch_sens; // pir sens static int g_timeLeft = 0; +static int g_isDark = 0; #define VAR_TIME SPECIAL_CHANNEL_FLASHVARS_LAST #define VAR_SENS (SPECIAL_CHANNEL_FLASHVARS_LAST-1) @@ -48,7 +49,13 @@ void PIR_Init() { g_lightLevelMargin = HAL_FlashVars_GetChannelValue(VAR_LIGHTLEVEL); ch_lightAdc = CHANNEL_FindIndexForPinType(IOR_ADC); ch_motion = CHANNEL_FindIndexForType(ChType_Motion); - ch_sens = CHANNEL_FindIndexForPinType(IOR_PWM_ScriptOnly); + if (ch_motion == -1) { + ch_motion = CHANNEL_FindIndexForPinType2(IOR_DigitalInput, IOR_DigitalInput_n); + if (ch_motion == -1) { + ch_motion = CHANNEL_FindIndexForPinType2(IOR_DigitalInput_NoPup, IOR_DigitalInput_NoPup_n); + } + } + ch_sens = CHANNEL_FindIndexForPinType2(IOR_PWM_ScriptOnly, IOR_PWM_ScriptOnly_n); } void PIR_OnEverySecond() { @@ -58,19 +65,20 @@ void PIR_OnEverySecond() { if (g_mode == 1) { // "Value seems to go down if MORE light is here and UP is LESS light is here" int lightLevel = CHANNEL_Get(ch_lightAdc); - if (lightLevel > g_lightLevelMargin) { + g_isDark = lightLevel > g_lightLevelMargin; + if (g_isDark) { // auto mode int motion = CHANNEL_Get(ch_motion); if (motion) { g_timeLeft = g_onTime; LED_SetEnableAll(true); } - if (g_timeLeft > 0) { - g_timeLeft--; - if (g_timeLeft <= 0) { - // turn off - LED_SetEnableAll(false); - } + } + if (g_timeLeft > 0) { + g_timeLeft--; + if (g_timeLeft <= 0) { + // turn off + LED_SetEnableAll(false); } } } @@ -121,7 +129,7 @@ void PIR_AppendInformationToHTTPIndexPage(http_request_t *request, int bPreState } else { if (g_mode == 1) { - hprintf255(request, "PIR current state: Automatic, motion: %i, timeLeft: %i
", CHANNEL_Get(ch_motion), g_timeLeft); + hprintf255(request, "PIR current state: Automatic, motion: %i, isDark %i, timeLeft: %i
", CHANNEL_Get(ch_motion), g_isDark, g_timeLeft); } else { hprintf255(request, "PIR current state: Manual
"); diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index 7dd1755de..f502f8c38 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -540,6 +540,9 @@ const char* htmlPinRoleNames[] = { "KP18058_DAT", "DS1820_IO", "PWM_ScriptOnly", + "PWM_ScriptOnly_n", + "error", + "error", "error", "error", }; diff --git a/src/new_pins.c b/src/new_pins.c index 2e32d55d7..245f962ed 100644 --- a/src/new_pins.c +++ b/src/new_pins.c @@ -693,6 +693,16 @@ int CHANNEL_FindIndexForPinType(int requiredType) { } return -1; } + +int CHANNEL_FindIndexForPinType2(int requiredType, int requiredType2) { + int i; + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { + if (g_cfg.pins.roles[i] == requiredType || g_cfg.pins.roles[i] == requiredType2) { + return g_cfg.pins.channels[i]; + } + } + return -1; +} int CHANNEL_FindIndexForType(int requiredType) { int i; for (i = 0; i < CHANNEL_MAX; i++) { @@ -742,6 +752,7 @@ void CHANNEL_SetAll(int iVal, int iFlags) { case IOR_PWM: case IOR_PWM_ScriptOnly: case IOR_PWM_n: + case IOR_PWM_ScriptOnly_n: CHANNEL_Set(g_cfg.pins.channels[i], iVal, iFlags); break; case IOR_BridgeForward: @@ -859,6 +870,7 @@ void PIN_SetPinRoleForPinIndex(int index, int role) { // Disable PWM for previous pin role case IOR_PWM_n: case IOR_PWM_ScriptOnly: + case IOR_PWM_ScriptOnly_n: case IOR_PWM: { HAL_PIN_PWM_Stop(index); @@ -1056,6 +1068,7 @@ void PIN_SetPinRoleForPinIndex(int index, int role) { break; case IOR_PWM_n: case IOR_PWM_ScriptOnly: + case IOR_PWM_ScriptOnly_n: case IOR_PWM: { int channelIndex; @@ -1075,7 +1088,8 @@ void PIN_SetPinRoleForPinIndex(int index, int role) { HAL_PIN_PWM_Start(index, useFreq); - if (role == IOR_PWM_n) { + if (role == IOR_PWM_n + || role == IOR_PWM_ScriptOnly_n) { // inversed PWM HAL_PIN_PWM_Update(index, 100.0f - channelValue); } @@ -1152,7 +1166,7 @@ static void Channel_OnChanged(int ch, int prevValue, int iFlags) { else if (g_cfg.pins.roles[i] == IOR_PWM || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly) { HAL_PIN_PWM_Update(i, iVal); } - else if (g_cfg.pins.roles[i] == IOR_PWM_n) { + else if (g_cfg.pins.roles[i] == IOR_PWM_n || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly_n) { HAL_PIN_PWM_Update(i, 100 - iVal); } } @@ -1404,7 +1418,7 @@ void CHANNEL_Set_FloatPWM(int ch, float fVal, int iFlags) { if (g_cfg.pins.roles[i] == IOR_PWM || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly) { HAL_PIN_PWM_Update(i, fVal); } - else if (g_cfg.pins.roles[i] == IOR_PWM_n) { + else if (g_cfg.pins.roles[i] == IOR_PWM_n || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly_n) { HAL_PIN_PWM_Update(i, 100.0f - fVal); } } @@ -1563,7 +1577,7 @@ int CHANNEL_FindMaxValueForChannel(int ch) { if (g_cfg.pins.roles[i] == IOR_PWM || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly) { return 100; } - if (g_cfg.pins.roles[i] == IOR_PWM_n) { + if (g_cfg.pins.roles[i] == IOR_PWM_n || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly_n) { return 100; } } @@ -1743,6 +1757,7 @@ int CHANNEL_GetRoleForOutputChannel(int ch) { case IOR_PWM_n: case IOR_PWM: case IOR_PWM_ScriptOnly: + case IOR_PWM_ScriptOnly_n: return g_cfg.pins.roles[i]; case IOR_BridgeForward: case IOR_BridgeReverse: @@ -2008,7 +2023,7 @@ void PIN_ticks(void* param) if (g_cfg.pins.roles[i] == IOR_PWM || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly) { HAL_PIN_PWM_Update(i, g_channelValuesFloats[g_cfg.pins.channels[i]]); } - else if (g_cfg.pins.roles[i] == IOR_PWM_n) { + else if (g_cfg.pins.roles[i] == IOR_PWM_n || g_cfg.pins.roles[i] == IOR_PWM_ScriptOnly_n) { // invert PWM value HAL_PIN_PWM_Update(i, 100 - g_channelValuesFloats[g_cfg.pins.channels[i]]); } @@ -2393,6 +2408,7 @@ void PIN_get_Relay_PWM_Count(int* relayCount, int* pwmCount, int* dInputCount) { //(*pwmCount)++; break; case IOR_PWM_ScriptOnly: + case IOR_PWM_ScriptOnly_n: // DO NOT COUNT SCRIPTONLY PWM HERE! // As in title - it's only for scripts. // It should not generate lights! diff --git a/src/new_pins.h b/src/new_pins.h index bf82b2282..47e92deb9 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -567,6 +567,13 @@ typedef enum ioRole_e { //iodetail:"file":"new_pins.h", //iodetail:"driver":""} IOR_PWM_ScriptOnly, + //iodetail:{"name":"PWM_ScriptOnly_n", + //iodetail:"title":"TODO", + //iodetail:"descr":"", + //iodetail:"enum":"PWM_ScriptOnly_n", + //iodetail:"file":"new_pins.h", + //iodetail:"driver":""} + IOR_PWM_ScriptOnly_n, //iodetail:{"name":"Total_Options", //iodetail:"title":"TODO", //iodetail:"descr":"Current total number of available IOR roles", @@ -1472,7 +1479,8 @@ bool CHANNEL_IsInUse(int ch); void Channel_SaveInFlashIfNeeded(int ch); int CHANNEL_FindMaxValueForChannel(int ch); int CHANNEL_FindIndexForType(int requiredType); -int CHANNEL_FindIndexForPinType(int requiredType); +int CHANNEL_FindIndexForPinType(int requiredType); +int CHANNEL_FindIndexForPinType2(int requiredType, int requiredType2); // cmd_channels.c bool CHANNEL_HasLabel(int ch); const char* CHANNEL_GetLabel(int ch); diff --git a/src/obk_config.h b/src/obk_config.h index 396c5cf4b..8010bcef8 100644 --- a/src/obk_config.h +++ b/src/obk_config.h @@ -173,6 +173,7 @@ #elif PLATFORM_BEKEN +//#define ENABLE_DRIVER_PIR 1 #define ENABLE_HA_DISCOVERY 1 #define ENABLE_SEND_POSTANDGET 1 #define ENABLE_MQTT 1 diff --git a/src/selftest/selftest_berry.c b/src/selftest/selftest_berry.c index fcb8eb4e0..d3bd4e60c 100644 --- a/src/selftest/selftest_berry.c +++ b/src/selftest/selftest_berry.c @@ -1347,8 +1347,95 @@ void Test_Berry_NTP() { SELFTEST_ASSERT_CHANNEL(5, 5); } +void Test_PIR() { + SIM_ClearOBK(0); + CMD_ExecuteCommand("lfs_format", 0); + + PIN_SetPinRoleForPinIndex(6, IOR_DigitalInput); + PIN_SetPinChannelForPinIndex(6, 11); + + PIN_SetPinRoleForPinIndex(8, IOR_PWM); + PIN_SetPinChannelForPinIndex(8, 4); + + PIN_SetPinRoleForPinIndex(9, IOR_PWM_n); + PIN_SetPinChannelForPinIndex(9, 5); + + PIN_SetPinRoleForPinIndex(23, IOR_ADC); + PIN_SetPinChannelForPinIndex(23, 12); + + PIN_SetPinRoleForPinIndex(26, IOR_PWM_ScriptOnly); + PIN_SetPinChannelForPinIndex(26, 10); + + CMD_ExecuteCommand("startDriver PIR", 0); + + Test_FakeHTTPClientPacket_GET("index?pirMode=1"); + // time on + Test_FakeHTTPClientPacket_GET("index?pirTime=5"); + // margin light value - 2000 + Test_FakeHTTPClientPacket_GET("index?light=2000"); + // simulate light value - 3000 + SIM_SetIntegerValueADCPin(23, 3000); + // no light + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + for (int i = 0; i < 3; i++) { + // Motion channel off + SIM_SetSimulatedPinValue(6, false); + Sim_RunSeconds(1, false); + // no light + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + } + // Motion channel goes to 1 + SIM_SetSimulatedPinValue(6, true); + // tick + Sim_RunSeconds(2, false); + // light is on + SELFTEST_ASSERT(LED_GetEnableAll() == 1); + // there is still motion, so no timer + for (int i = 0; i < 3; i++) { + // Motion channel on + SIM_SetSimulatedPinValue(6, true); + Sim_RunSeconds(1, false); + // light is on + SELFTEST_ASSERT(LED_GetEnableAll() == 1); + } + // now motion goes away + SIM_SetSimulatedPinValue(6, false); + // I set timer to 5 seconds, so 7? + Sim_RunSeconds(7, false); + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + // now nothing happens for long time + for (int i = 0; i < 10; i++) { + // Motion channel off + SIM_SetSimulatedPinValue(6, false); + Sim_RunSeconds(1, false); + // no light + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + } + // Motion channel goes to 1 + SIM_SetSimulatedPinValue(6, true); + // tick + Sim_RunSeconds(2, false); + // light is on + SELFTEST_ASSERT(LED_GetEnableAll() == 1); + // but now it's day and it's bright + SIM_SetIntegerValueADCPin(23, 500); + // times goes down + // I set timer to 5 seconds, so 7? + Sim_RunSeconds(7, false); + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + // so now, motion can be present, but light is still off + for (int i = 0; i < 10; i++) { + // Motion can be present + SIM_SetSimulatedPinValue(6, true); + Sim_RunSeconds(1, false); + // no light + SELFTEST_ASSERT(LED_GetEnableAll() == 0); + } +} void Test_Berry() { + Test_PIR(); + Test_Berry_Button(); Test_Berry_Import_Autorun(); Test_Berry_HTTP2();