Improved state change mechanism

This commit is contained in:
Dejvino 2026-02-15 19:05:19 +01:00
parent 2cdb05b4d8
commit eba13c6181

View File

@ -56,10 +56,9 @@ BH1750 lightMeter;
// Thresholds // Thresholds
const float LIGHT_ACTIVATION_THRESHOLD = 50.0; const float LIGHT_ACTIVATION_THRESHOLD = 50.0;
const float LIGHT_DEACTIVATION_THRESHOLD = 20.0; const unsigned long WINDOW_DURATION = 10000; // 10 seconds
const unsigned long VIBRATION_STATE_CHANGE_INTERVAL = 10000; // 1000 = 1 second const int REQUIRED_CONSECUTIVE_WINDOWS = 6;
const unsigned long VIBRATION_ACTIVE_THRESHOLD = 100000; const unsigned long VIBRATION_ACTIVE_THRESHOLD = 100000;
const int VIBRATION_WINDOW_SIZE = 6; // X * VIBRATION_STATE_CHANGE_INTERVAL seconds window
const unsigned long WARMUP_DURATION = 30000; // 20 seconds warmup const unsigned long WARMUP_DURATION = 30000; // 20 seconds warmup
// Device state // Device state
@ -67,9 +66,7 @@ bool isVibrationActive = false;
bool isLightActive = false; bool isLightActive = false;
// Time tracking for sensor states // Time tracking for sensor states
unsigned long lastVibrationCheckTime = 0; unsigned long lastWindowStartTime = 0;
unsigned long lightHighStartTime = 0;
unsigned long lightLowStartTime = 0;
// OLED display data // OLED display data
#ifdef ENABLE_DISPLAY #ifdef ENABLE_DISPLAY
@ -91,10 +88,12 @@ QueueHandle_t notificationQueue;
volatile bool isNetworkActive = false; volatile bool isNetworkActive = false;
#ifdef ENABLE_SENSORS #ifdef ENABLE_SENSORS
unsigned long vibrationHistory[VIBRATION_WINDOW_SIZE];
int vibrationHistoryIdx = 0;
unsigned long vibrationWindowTotal = 0;
unsigned long vibrationTotalLow = 0; unsigned long vibrationTotalLow = 0;
int vibConsecutiveOn = 0;
int vibConsecutiveOff = 0;
int lightConsecutiveOn = 0;
int lightConsecutiveOff = 0;
float maxLightInWindow = 0.0;
volatile unsigned long lastChangeTime = 0; volatile unsigned long lastChangeTime = 0;
volatile unsigned long lowTimeAccumulator = 0; volatile unsigned long lowTimeAccumulator = 0;
volatile unsigned long highTimeAccumulator = 0; volatile unsigned long highTimeAccumulator = 0;
@ -186,9 +185,6 @@ void setup() {
lastChangeTime = micros(); lastChangeTime = micros();
attachInterrupt(digitalPinToInterrupt(VIBRATION_PIN), onChange, CHANGE); attachInterrupt(digitalPinToInterrupt(VIBRATION_PIN), onChange, CHANGE);
// Initialize history buffer
for(int i=0; i<VIBRATION_WINDOW_SIZE; i++) vibrationHistory[i] = 0;
// Initialize light sensor // Initialize light sensor
if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) { if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
Serial.println(F("Could not find a valid BH1750 sensor, check wiring!")); Serial.println(F("Could not find a valid BH1750 sensor, check wiring!"));
@ -250,6 +246,9 @@ void loop() {
// Sensor readings // Sensor readings
#ifdef ENABLE_SENSORS #ifdef ENABLE_SENSORS
float currentLightLevel = lightMeter.readLightLevel(); float currentLightLevel = lightMeter.readLightLevel();
if (currentLightLevel > maxLightInWindow) {
maxLightInWindow = currentLightLevel;
}
#else #else
float currentLightLevel = 0.0; float currentLightLevel = 0.0;
#endif #endif
@ -257,11 +256,12 @@ void loop() {
bool previousVibrationState = isVibrationActive; bool previousVibrationState = isVibrationActive;
bool previousLightState = isLightActive; bool previousLightState = isLightActive;
// Vibration state change logic // Window Logic
#ifdef ENABLE_SENSORS if (currentTime - lastWindowStartTime >= WINDOW_DURATION) {
if (currentTime - lastVibrationCheckTime >= VIBRATION_STATE_CHANGE_INTERVAL) { lastWindowStartTime = currentTime;
lastVibrationCheckTime = currentTime;
// 1. Process Vibration
#ifdef ENABLE_SENSORS
noInterrupts(); noInterrupts();
unsigned long now = micros(); unsigned long now = micros();
unsigned long duration = now - lastChangeTime; unsigned long duration = now - lastChangeTime;
@ -278,40 +278,42 @@ void loop() {
highTimeAccumulator = 0; highTimeAccumulator = 0;
interrupts(); interrupts();
vibrationWindowTotal -= vibrationHistory[vibrationHistoryIdx]; bool vibWindowOn = (vibrationTotalLow > VIBRATION_ACTIVE_THRESHOLD);
vibrationHistory[vibrationHistoryIdx] = vibrationTotalLow;
vibrationWindowTotal += vibrationTotalLow;
vibrationHistoryIdx = (vibrationHistoryIdx + 1) % VIBRATION_WINDOW_SIZE;
if (vibrationWindowTotal > VIBRATION_ACTIVE_THRESHOLD && currentTime > WARMUP_DURATION) { if (vibWindowOn) {
isVibrationActive = true; vibConsecutiveOn++;
vibConsecutiveOff = 0;
} else { } else {
isVibrationActive = false; vibConsecutiveOff++;
vibConsecutiveOn = 0;
} }
if (vibConsecutiveOn >= REQUIRED_CONSECUTIVE_WINDOWS && currentTime > WARMUP_DURATION) {
isVibrationActive = true;
} else if (vibConsecutiveOff >= REQUIRED_CONSECUTIVE_WINDOWS) {
isVibrationActive = false;
} }
#endif #endif
// Light state change logic // 2. Process Light
if (currentLightLevel >= LIGHT_ACTIVATION_THRESHOLD && !isLightActive) { bool lightWindowOn = (maxLightInWindow > LIGHT_ACTIVATION_THRESHOLD);
if (lightHighStartTime == 0) {
lightHighStartTime = currentTime; if (lightWindowOn) {
lightConsecutiveOn++;
lightConsecutiveOff = 0;
} else {
lightConsecutiveOff++;
lightConsecutiveOn = 0;
} }
if (currentTime - lightHighStartTime >= VIBRATION_STATE_CHANGE_INTERVAL && currentTime > WARMUP_DURATION) {
if (lightConsecutiveOn >= REQUIRED_CONSECUTIVE_WINDOWS && currentTime > WARMUP_DURATION) {
isLightActive = true; isLightActive = true;
} } else if (lightConsecutiveOff >= REQUIRED_CONSECUTIVE_WINDOWS) {
lightLowStartTime = 0;
} else if (currentLightLevel < LIGHT_DEACTIVATION_THRESHOLD && isLightActive) {
if (lightLowStartTime == 0) {
lightLowStartTime = currentTime;
}
if (currentTime - lightLowStartTime >= VIBRATION_STATE_CHANGE_INTERVAL) {
isLightActive = false; isLightActive = false;
} }
lightHighStartTime = 0;
} else if(currentLightLevel >= LIGHT_ACTIVATION_THRESHOLD) { // Reset Light Accumulator
lightLowStartTime = 0; maxLightInWindow = 0.0;
} else {
lightHighStartTime = 0;
} }
// Device 1 (Vibration) Notifications // Device 1 (Vibration) Notifications
@ -382,10 +384,10 @@ void loop() {
#ifdef ENABLE_DISPLAY #ifdef ENABLE_DISPLAY
// Update display data // Update display data
displayData[0] = String(DEVICE1_NAME) + ": " + String(vibrationWindowTotal); displayData[0] = String(DEVICE1_NAME) + ": " + (vibrationTotalLow > VIBRATION_ACTIVE_THRESHOLD ? "YES" : "NO");
displayData[1] = "Vibra: " + String(isVibrationActive ? "ON" : "OFF"); displayData[1] = "Vibra: " + String(isVibrationActive ? "OFF? " + String(vibConsecutiveOff) : "ON? " + String(vibConsecutiveOn)) + "/" + String(REQUIRED_CONSECUTIVE_WINDOWS);
displayData[2] = String(DEVICE2_NAME) + ": " + String(currentLightLevel, 0); displayData[2] = String(DEVICE2_NAME) + ": " + String(currentLightLevel, 0);
displayData[3] = "Light: " + String(isLightActive ? "ON" : "OFF"); displayData[3] = "Light: " + String(isLightActive ? "OFF? " + String(lightConsecutiveOff) : "ON? " + String(lightConsecutiveOn)) + "/" + String(REQUIRED_CONSECUTIVE_WINDOWS);
displayDataLines = 4; displayDataLines = 4;
// Update display // Update display