From 601005f837a527291e642179bec1c965427f7061 Mon Sep 17 00:00:00 2001 From: Egor Chernodarov Date: Fri, 2 Apr 2021 23:04:10 +0700 Subject: [PATCH 1/7] Support of simple gestures for VL53L0X laser sensor --- usermods/VL53L0X_gestures/readme.md | 35 +++++ .../usermod_vl53l0x_gestures.h | 121 ++++++++++++++++++ wled00/const.h | 1 + wled00/usermods_list.cpp | 9 ++ wled00/wled.h | 2 +- 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 usermods/VL53L0X_gestures/readme.md create mode 100644 usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h diff --git a/usermods/VL53L0X_gestures/readme.md b/usermods/VL53L0X_gestures/readme.md new file mode 100644 index 00000000..dec84130 --- /dev/null +++ b/usermods/VL53L0X_gestures/readme.md @@ -0,0 +1,35 @@ +# Description + +That usermod implements support of simple hand gestures with VL53L0X sensor: on/off and brightness correction. +It can be useful for kitchen strips to avoid any touches. + - on/off - just swipe a hand below your sensor ("shortPressAction" is called and can be customized through WLED macros) + - brightness correction - keep your hand below sensor for 1 second to switch to "brightness" mode. + Configure brightness by changing distance to the sensor (see parameters below for customization). + "macroLongPress" is also called here. + +## Installation + +1. Attach VL53L0X sensor to i2c pins according to default pins for your board. +2. Add `-D USERMOD_VL53L0X_GESTURES` to your build flags at platformio.ini (plaformio_override.ini) for needed environment. +In my case, for example: `build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES` +3. Add "pololu/VL53L0X" dependency below to `lib_deps` like this: +```ini +lib_deps = ${env.lib_deps} + pololu/VL53L0X @ ^1.3.0 +``` + +My entire `platformio_override.ini` for example (for nodemcu board): +```ini +[platformio] +default_envs = nodemcu + +[env:nodemcu] +board = nodemcu +platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} +board_build.ldscript = ${common.ldscript_4m1m} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES +lib_deps = ${env.lib_deps} + pololu/VL53L0X @ ^1.3.0 +``` \ No newline at end of file diff --git a/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h b/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h new file mode 100644 index 00000000..83f26e08 --- /dev/null +++ b/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h @@ -0,0 +1,121 @@ +/* + * That usermod implements support of simple hand gestures with VL53L0X sensor: on/off and brightness correction. + * It can be useful for kitchen strips to avoid any touches. + * - on/off - just swipe a hand below your sensor ("shortPressAction" is called and can be customized through WLED macros) + * - brightness correction - keep your hand below sensor for 1 second to switch to "brightness" mode. + * Configure brightness by changing distance to the sensor (see parameters below for customization). + * "macroLongPress" is also called here. + * + * Enabling this mod usermod: + * 1. Attach VL53L0X sensor to i2c pins according to default pins for your board. + * 2. Add "-D USERMOD_VL53L0X_GESTURES" to your build flags at platformio.ini (plaformio_override.ini) for needed environment. + * In my case, for example: build_flags = ${common.build_flags_esp8266} -D RLYPIN=12 -D USERMOD_VL53L0X_GESTURES + * 3. Add "pololu/VL53L0X" dependency to lib_deps like this: + * lib_deps = ${env.lib_deps} + * pololu/VL53L0X @ ^1.3.0 + */ +#pragma once + +#include "wled.h" + +#include +#include + +#ifndef VL53L0X_MAX_RANGE_MM +#define VL53L0X_MAX_RANGE_MM 230 // max height in millimiters to react for motions +#endif + +#ifndef VL53L0X_MIN_RANGE_OFFSET +#define VL53L0X_MIN_RANGE_OFFSET 60 // minimal range in millimiters that sensor can detect. Used in long motions to correct brightnes calculation. +#endif + +#ifndef VL53L0X_DELAY_MS +#define VL53L0X_DELAY_MS 100 // how often to get data from sensor +#endif + +#ifndef VL53L0X_LONG_MOTION_DELAY_MS +#define VL53L0X_LONG_MOTION_DELAY_MS 1000 // how often to get data from sensor +#endif + +class UsermodVL53L0XGestures : public Usermod { + private: + //Private class members. You can declare variables and functions only accessible to your usermod here + unsigned long lastTime = 0; + VL53L0X sensor; + + bool wasMotionBefore = false; + bool isLongMotion = false; + unsigned long motionStartTime = 0; + + public: + + void setup() { + Wire.begin(); + + sensor.setTimeout(150); + if (!sensor.init()) + { + DEBUG_PRINTLN(F("Failed to detect and initialize VL53L0X sensor!")); + } else { + sensor.setMeasurementTimingBudget(20000); // set high speed mode + } + } + + + void loop() { + if (millis() - lastTime > VL53L0X_DELAY_MS) + { + lastTime = millis(); + + int range = sensor.readRangeSingleMillimeters(); + DEBUG_PRINTF(F("range: %d, brightness: %d"), range, bri); + + if (range < VL53L0X_MAX_RANGE_MM) + { + if (!wasMotionBefore) + { + motionStartTime = millis(); + DEBUG_PRINTF(F("motionStartTime: %d"), motionStartTime); + } + wasMotionBefore = true; + + if (millis() - motionStartTime > VL53L0X_LONG_MOTION_DELAY_MS) //long motion + { + DEBUG_PRINTF(F("long motion: %d"), motionStartTime); + if (!isLongMotion) + { + if (macroLongPress) + { + applyMacro(macroLongPress); + } + isLongMotion = true; + } + + // set brightness according to range + bri = (VL53L0X_MAX_RANGE_MM - max(range, VL53L0X_MIN_RANGE_OFFSET)) * 255 / (VL53L0X_MAX_RANGE_MM - VL53L0X_MIN_RANGE_OFFSET); + DEBUG_PRINTF(F("new brightness: %d"), bri); + colorUpdated(1); + } + } else if (wasMotionBefore) { //released + long dur = millis() - motionStartTime; + + if (!isLongMotion) + { //short press + DEBUG_PRINTF(F("shortPressAction...")); + shortPressAction(); + } + wasMotionBefore = false; + isLongMotion = false; + } + } + } + + /* + * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). + * This could be used in the future for the system to determine whether your usermod is installed. + */ + uint16_t getId() + { + return USERMOD_ID_VL53L0X; + } +}; \ No newline at end of file diff --git a/wled00/const.h b/wled00/const.h index 8ce63372..e6d6d1f3 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -32,6 +32,7 @@ #define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h" #define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" #define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" +#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 518aef3a..fb26c93e 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -45,6 +45,11 @@ #include "../usermods/DHT/usermod_dht.h" #endif +#ifdef USERMOD_VL53L0X_GESTURES +#include //it's needed here to correctly resolve dependencies +#include "../usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h" +#endif + void registerUsermods() { /* @@ -87,4 +92,8 @@ void registerUsermods() #ifdef USERMOD_DHT usermods.add(new UsermodDHT()); #endif + +#ifdef USERMOD_VL53L0X_GESTURES + usermods.add(new UsermodVL53L0XGestures()); +#endif } \ No newline at end of file diff --git a/wled00/wled.h b/wled00/wled.h index 2fe5a792..dfee80cc 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -577,7 +577,7 @@ WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager()); #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) - #define DEBUG_PRINTF(x) + #define DEBUG_PRINTF(x...) #endif #ifdef WLED_DEBUG_FS From a69dcfc49d104e6dc899179a121a2170e27be5ed Mon Sep 17 00:00:00 2001 From: Mike Kolcun Date: Fri, 2 Apr 2021 14:04:27 -0400 Subject: [PATCH 2/7] Increase buffer size Avoid buffer overflows with longer mqtt topics mqtDeviceTopic in wled.h is defined with a size of 33, so this should be set to 45 to accommodate the additional 12 characters - /temperature --- usermods/Temperature/usermod_temperature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index 1ce0322e..9019fd17 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -120,7 +120,7 @@ class UsermodTemperature : public Usermod { getTemperature(); if (WLED_MQTT_CONNECTED) { - char subuf[38]; + char subuf[45]; strcpy(subuf, mqttDeviceTopic); if (-100 <= temperature) { // dont publish super low temperature as the graph will get messed up From f18dced2f34645b7b99da4071bf12a823868dd6a Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 5 Apr 2021 16:08:35 +0200 Subject: [PATCH 3/7] use constrain to keep in segment limits --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index f6509e52..eec9192b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3108,7 +3108,7 @@ uint16_t WS2812FX::mode_drip(void) drops[j].vel += gravity; for (uint16_t i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets - uint16_t pos = uint16_t(drops[j].pos) +i; //this is BAD, returns a pos >= SEGLEN occasionally + uint16_t pos = constrain(uint16_t(drops[j].pos) +i, 0, SEGLEN-1); //this is BAD, returns a pos >= SEGLEN occasionally setPixelColor(pos,color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling } From ffab9bb8935c76eab58deb9e6f524990172434c9 Mon Sep 17 00:00:00 2001 From: Blaz Kristan Date: Mon, 5 Apr 2021 21:14:36 +0200 Subject: [PATCH 4/7] Ledmap multisegment fix. --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 58343c08..1a07dc1a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -192,8 +192,8 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) for (uint16_t j = 0; j < SEGMENT.grouping; j++) { int16_t indexSet = realIndex + (reversed ? -j : j); - if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) { + if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; busses.setPixelColor(indexSet + skip, col); if (IS_MIRROR) { //set the corresponding mirrored pixel uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1; From 90da471084238fde83741c161e457bf93044bc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Kristan?= Date: Tue, 6 Apr 2021 07:48:12 +0200 Subject: [PATCH 5/7] Fix for mirrored segments. --- wled00/FX_fcn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 1a07dc1a..257307d9 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -193,13 +193,13 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) for (uint16_t j = 0; j < SEGMENT.grouping; j++) { int16_t indexSet = realIndex + (reversed ? -j : j); if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) { - if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; - busses.setPixelColor(indexSet + skip, col); if (IS_MIRROR) { //set the corresponding mirrored pixel uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1; if (indexMir < customMappingSize) indexMir = customMappingTable[indexMir]; busses.setPixelColor(indexMir + skip, col); } + if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet]; + busses.setPixelColor(indexSet + skip, col); } } } else { //live data, etc. From 789c00dde12634a9db415e012d06550f3d0370e5 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 6 Apr 2021 11:42:21 +0200 Subject: [PATCH 6/7] Change indexSet to signed 32 bit --- wled00/FX_fcn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 257307d9..9e0e7990 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -191,7 +191,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) uint16_t realIndex = realPixelIndex(i); for (uint16_t j = 0; j < SEGMENT.grouping; j++) { - int16_t indexSet = realIndex + (reversed ? -j : j); + int indexSet = realIndex + (reversed ? -j : j); if (indexSet >= SEGMENT.start && indexSet < SEGMENT.stop) { if (IS_MIRROR) { //set the corresponding mirrored pixel uint16_t indexMir = SEGMENT.stop - indexSet + SEGMENT.start - 1; From ad8e614ae809721c16030f8daa417d537436b357 Mon Sep 17 00:00:00 2001 From: Udo Waechter Date: Fri, 9 Apr 2021 17:50:26 +0200 Subject: [PATCH 7/7] updated bottom/top sensor bottomsensor and topsensor were incorrect: bottom-sensor / top-sensor according to API --- usermods/Animated_Staircase/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/usermods/Animated_Staircase/README.md b/usermods/Animated_Staircase/README.md index 6e84b544..1ee6c28c 100644 --- a/usermods/Animated_Staircase/README.md +++ b/usermods/Animated_Staircase/README.md @@ -93,8 +93,8 @@ or remove them and put everything on one line. | segment-delay-ms | Delay (milliseconds) between switching on/off each step | 150 | | on-time-s | Time (seconds) the stairs stay lit after last detection | 5 | | bottom-echo-us | Detection range of ultrasonic sensor | 1749 | -| bottomsensor | Manually trigger a down to up animation via API | false | -| topsensor | Manually trigger an up to down animation via API | false | +| bottom-sensor | Manually trigger a down to up animation via API | false | +| top-sensor | Manually trigger an up to down animation via API | false | To read the current settings, open a browser to `http://xxx.xxx.xxx.xxx/json/state` (use your WLED @@ -108,8 +108,8 @@ The staircase settings and sensor states are inside the WLED status element: "enabled": true, "segment-delay-ms": 150, "on-time-s": 5, - "bottomsensor": false, - "topsensor": false + "bottom-sensor": false, + "tops-ensor": false }, } ``` @@ -187,7 +187,7 @@ the API. To simulate triggering the bottom sensor, use: ```bash curl -X POST -H "Content-Type: application/json" \ - -d '{"staircase":{"bottomsensor":true}}' \ + -d '{"staircase":{"bottom-sensor":true}}' \ xxx.xxx.xxx.xxx/json/state ``` @@ -195,7 +195,7 @@ Likewise, to trigger the top sensor, use: ```bash curl -X POST -H "Content-Type: application/json" \ - -d '{"staircase":{"topsensor":true}}' \ + -d '{"staircase":{"top-sensor":true}}' \ xxx.xxx.xxx.xxx/json/state ```