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();