From 53c079c8c2c804312b5dc4c10c23bea721ff369c Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Wed, 30 Apr 2025 03:41:37 +0200 Subject: [PATCH 1/9] feat(buttons): allow isPressed() to accept 'A', 'B', 'C' as input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added support for character and string-based input to `isPressed()` in `ModulinoButtons`, so it now accepts both index (0–2) and letter identifiers (`'A'`, `'B'`, `'C'`) matching the physical button labeling. Closes #3 --- .gitignore | 28 ++++++++++++++++++++++++++++ src/Modulino.h | 19 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5577b0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Compiled object files +*.o +*.a +*.so +*.out + +# Arduino build folder +build/ +*.elf +*.bin +*.hex +*.eep + +# Arduino CLI and IDE cache +*.d +*.dep +*.map +*.lst + +# MacOS specific +.DS_Store + +# Backup files +*~ +*.swp + +# VS Code (se lo usi) +.vscode/ \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index 6f62aaf..f768d24 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -127,6 +127,17 @@ class ModulinoButtons : public Module { PinStatus isPressed(int index) { return last_status[index] ? HIGH : LOW; } + PinStatus isPressed(char button) { + int index = buttonToIndex(button); + if (index < 0) return LOW; + return isPressed(index); + } + PinStatus isPressed(const char *button) { + if (button == nullptr || button[0] == '\0' || button[1] != '\0') { + return LOW; + } + return isPressed(button[0]); + } bool update() { uint8_t buf[3]; auto res = read((uint8_t*)buf, 3); @@ -154,6 +165,14 @@ class ModulinoButtons : public Module { } private: bool last_status[3]; + int buttonToIndex(char button) { + switch (toupper(button)) { + case 'A': return 0; + case 'B': return 1; + case 'C': return 2; + default: return -1; + } + } protected: uint8_t match[1] = { 0x7C }; // same as fw main.c }; From 59aef641723f70071cb29d06fe6ffb2409907973 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Wed, 30 Apr 2025 03:57:53 +0200 Subject: [PATCH 2/9] Update example to document support for both numeric and letter indices :recycle: --- .../Buttons_Basic/Buttons_Basic.ino | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino index f29f96b..b097834 100644 --- a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino +++ b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino @@ -24,23 +24,25 @@ void setup() { // Turn on the LEDs above buttons A, B, and C buttons.setLeds(true, true, true); } + void loop() { // Check for new button events, returns true when button state changes if (buttons.update()) { - // Check which button was pressed (0=A, 1=B, 2=C) - // Also toggle the corresponding LED, for each of the three buttons - if (buttons.isPressed(0)) { + // You can use either index (0=A, 1=B, 2=C) or letter ('A', 'B', 'C') to check buttons + // Below we use the letter-based method for better readability + + if (buttons.isPressed('A')) { Serial.println("Button A pressed!"); button_a = !button_a; - } else if (buttons.isPressed(1)) { + } else if (buttons.isPressed("B")) { Serial.println("Button B pressed!"); button_b = !button_b; - } else if (buttons.isPressed(2)) { + } else if (buttons.isPressed('C')) { Serial.println("Button C pressed!"); button_c = !button_c; } - - // Update the LEDs above buttons, depending on the variables value + + // Update the LEDs above buttons, depending on the variables' value buttons.setLeds(button_a, button_b, button_c); } } \ No newline at end of file From e53f80347fee2c228887ff363501eb44eeede48a Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 1 May 2025 04:03:06 +0200 Subject: [PATCH 3/9] Add getDirection() support to ModulinoKnob and example :zap: --- .../Modulino_Knob/Knob_Basic/Knob_Basic.ino | 13 +++++++++++-- src/Modulino.h | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino index b933002..4124081 100644 --- a/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino +++ b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino @@ -24,12 +24,21 @@ void loop(){ int position = knob.get(); // Check if the knob has been pressed (clicked) bool click = knob.isPressed(); + // Get the rotation direction + int8_t direction = knob.getDirection(); Serial.print("Current position is: "); Serial.println(position); - if(click){ + if (click) { Serial.println("Clicked!"); } -} \ No newline at end of file + if (direction == 1) { + Serial.println("Rotated clockwise"); + } else if (direction == -1) { + Serial.println("Rotated counter-clockwise"); + } + + delay(10); // optional small delay to reduce serial spam +} \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index f768d24..79b84b8 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -274,12 +274,27 @@ class ModulinoKnob : public Module { } return ret; } - int16_t get() { + bool update() { uint8_t buf[3]; auto res = read(buf, 3); if (res == false) { return 0; } + get(buf); + return 1; + } + int16_t get(uint8_t * buf = nullptr) { + if (buf == nullptr) { + buf = (uint8_t*)malloc(3); + if (buf == nullptr) { + return 0; + } + auto res = read(buf, 3); + if (res == false) { + _pressed = false; + return 0; + } + } _pressed = (buf[2] != 0); int16_t ret = buf[0] | (buf[1] << 8); return ret; From 9a2a9cf1d6d5e548d8532f150a8a292230353877 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 1 May 2025 04:12:11 +0200 Subject: [PATCH 4/9] Fix: :fire: --- .gitignore | 28 ----------- .../Buttons_Basic/Buttons_Basic.ino | 48 ------------------- src/Modulino.h | 19 -------- 3 files changed, 95 deletions(-) delete mode 100644 .gitignore delete mode 100644 examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5577b0d..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Compiled object files -*.o -*.a -*.so -*.out - -# Arduino build folder -build/ -*.elf -*.bin -*.hex -*.eep - -# Arduino CLI and IDE cache -*.d -*.dep -*.map -*.lst - -# MacOS specific -.DS_Store - -# Backup files -*~ -*.swp - -# VS Code (se lo usi) -.vscode/ \ No newline at end of file diff --git a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino deleted file mode 100644 index b097834..0000000 --- a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Modulino Buttons - Basic - * - * This example code is in the public domain. - * Copyright (c) 2025 Arduino - * SPDX-License-Identifier: MPL-2.0 - */ - -#include - -// Create a ModulinoButtons object -ModulinoButtons buttons; - -bool button_a = true; -bool button_b = true; -bool button_c = true; - -void setup() { - Serial.begin(9600); - // Initialize Modulino I2C communication - Modulino.begin(); - // Detect and connect to buttons module - buttons.begin(); - // Turn on the LEDs above buttons A, B, and C - buttons.setLeds(true, true, true); -} - -void loop() { - // Check for new button events, returns true when button state changes - if (buttons.update()) { - // You can use either index (0=A, 1=B, 2=C) or letter ('A', 'B', 'C') to check buttons - // Below we use the letter-based method for better readability - - if (buttons.isPressed('A')) { - Serial.println("Button A pressed!"); - button_a = !button_a; - } else if (buttons.isPressed("B")) { - Serial.println("Button B pressed!"); - button_b = !button_b; - } else if (buttons.isPressed('C')) { - Serial.println("Button C pressed!"); - button_c = !button_c; - } - - // Update the LEDs above buttons, depending on the variables' value - buttons.setLeds(button_a, button_b, button_c); - } -} \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index 79b84b8..6d7b45f 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -127,17 +127,6 @@ class ModulinoButtons : public Module { PinStatus isPressed(int index) { return last_status[index] ? HIGH : LOW; } - PinStatus isPressed(char button) { - int index = buttonToIndex(button); - if (index < 0) return LOW; - return isPressed(index); - } - PinStatus isPressed(const char *button) { - if (button == nullptr || button[0] == '\0' || button[1] != '\0') { - return LOW; - } - return isPressed(button[0]); - } bool update() { uint8_t buf[3]; auto res = read((uint8_t*)buf, 3); @@ -165,14 +154,6 @@ class ModulinoButtons : public Module { } private: bool last_status[3]; - int buttonToIndex(char button) { - switch (toupper(button)) { - case 'A': return 0; - case 'B': return 1; - case 'C': return 2; - default: return -1; - } - } protected: uint8_t match[1] = { 0x7C }; // same as fw main.c }; From 3d48585b9d39591eba6e9bbe13936986f31f8139 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 1 May 2025 04:22:32 +0200 Subject: [PATCH 5/9] Fix: restore files :fire: --- .gitignore | 28 +++++++++++ .../Buttons_Basic/Buttons_Basic.ino | 46 +++++++++++++++++++ src/Modulino.h | 24 +++++++++- 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..25bea27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +# Compiled object files +*.o +*.a +*.so +*.out + +# Arduino build folder +build/ +*.elf +*.bin +*.hex +*.eep + +# Arduino CLI and IDE cache +*.d +*.dep +*.map +*.lst + +# MacOS specific +.DS_Store + +# Backup files +*~ +*.swp + +# VS Code +.vscode/ \ No newline at end of file diff --git a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino new file mode 100644 index 0000000..e320582 --- /dev/null +++ b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino @@ -0,0 +1,46 @@ +/* + * Modulino Buttons - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +// Create a ModulinoButtons object +ModulinoButtons buttons; + +bool button_a = true; +bool button_b = true; +bool button_c = true; + +void setup() { +Serial.begin(9600); +// Initialize Modulino I2C communication +Modulino.begin(); +// Detect and connect to buttons module +buttons.begin(); +// Turn on the LEDs above buttons A, B, and C +buttons.setLeds(true, true, true); +} +void loop() { +// Check for new button events, returns true when button state changes +if (buttons.update()) { + // Check which button was pressed (0=A, 1=B, 2=C) + // Also toggle the corresponding LED, for each of the three buttons + if (buttons.isPressed(0)) { + Serial.println("Button A pressed!"); + button_a = !button_a; + } else if (buttons.isPressed(1)) { + Serial.println("Button B pressed!"); + button_b = !button_b; + } else if (buttons.isPressed(2)) { + Serial.println("Button C pressed!"); + button_c = !button_c; + } + + // Update the LEDs above buttons, depending on the variables value + buttons.setLeds(button_a, button_b, button_c); +} +} \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index 6d7b45f..d42ac8b 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -243,8 +243,9 @@ class ModulinoKnob : public Module { bool begin() { auto ret = Module::begin(); if (ret) { - // check for set() bug auto _val = get(); + _lastPosition = _val; + _lastDebounceTime = millis(); set(100); if (get() != 100) { _bug_on_set = true; @@ -292,6 +293,24 @@ class ModulinoKnob : public Module { get(); return _pressed; } + int8_t getDirection() { + unsigned long now = millis(); + if (now - _lastDebounceTime < DEBOUNCE_DELAY) { + return 0; + } + int16_t current = get(); + int8_t direction = 0; + if (current > _lastPosition) { + direction = 1; + } else if (current < _lastPosition) { + direction = -1; + } + if (direction != 0) { + _lastDebounceTime = now; + _lastPosition = current; + } + return direction; + } virtual uint8_t discover() { for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { if (scan(match[i])) { @@ -303,6 +322,9 @@ class ModulinoKnob : public Module { private: bool _pressed = false; bool _bug_on_set = false; + int16_t _lastPosition = 0; + unsigned long _lastDebounceTime = 0; + static constexpr unsigned long DEBOUNCE_DELAY = 30; protected: uint8_t match[2] = { 0x74, 0x76 }; }; From c70097d57f19968c2de7d434dd5057f589b5e180 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 8 May 2025 17:04:55 +0200 Subject: [PATCH 6/9] Minor fixes :recycle: --- .gitignore | 28 --------------- .../Buttons_Basic/Buttons_Basic.ino | 34 +++++++++---------- src/Modulino.h | 17 +--------- 3 files changed, 18 insertions(+), 61 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 25bea27..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Compiled object files -*.o -*.a -*.so -*.out - -# Arduino build folder -build/ -*.elf -*.bin -*.hex -*.eep - -# Arduino CLI and IDE cache -*.d -*.dep -*.map -*.lst - -# MacOS specific -.DS_Store - -# Backup files -*~ -*.swp - -# VS Code -.vscode/ \ No newline at end of file diff --git a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino index e320582..f29f96b 100644 --- a/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino +++ b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino @@ -16,31 +16,31 @@ bool button_b = true; bool button_c = true; void setup() { -Serial.begin(9600); -// Initialize Modulino I2C communication -Modulino.begin(); -// Detect and connect to buttons module -buttons.begin(); -// Turn on the LEDs above buttons A, B, and C -buttons.setLeds(true, true, true); + Serial.begin(9600); + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to buttons module + buttons.begin(); + // Turn on the LEDs above buttons A, B, and C + buttons.setLeds(true, true, true); } void loop() { -// Check for new button events, returns true when button state changes -if (buttons.update()) { + // Check for new button events, returns true when button state changes + if (buttons.update()) { // Check which button was pressed (0=A, 1=B, 2=C) // Also toggle the corresponding LED, for each of the three buttons if (buttons.isPressed(0)) { - Serial.println("Button A pressed!"); - button_a = !button_a; + Serial.println("Button A pressed!"); + button_a = !button_a; } else if (buttons.isPressed(1)) { - Serial.println("Button B pressed!"); - button_b = !button_b; + Serial.println("Button B pressed!"); + button_b = !button_b; } else if (buttons.isPressed(2)) { - Serial.println("Button C pressed!"); - button_c = !button_c; + Serial.println("Button C pressed!"); + button_c = !button_c; } - + // Update the LEDs above buttons, depending on the variables value buttons.setLeds(button_a, button_b, button_c); -} + } } \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index d42ac8b..365d3c1 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -256,27 +256,12 @@ class ModulinoKnob : public Module { } return ret; } - bool update() { + int16_t get() { uint8_t buf[3]; auto res = read(buf, 3); if (res == false) { return 0; } - get(buf); - return 1; - } - int16_t get(uint8_t * buf = nullptr) { - if (buf == nullptr) { - buf = (uint8_t*)malloc(3); - if (buf == nullptr) { - return 0; - } - auto res = read(buf, 3); - if (res == false) { - _pressed = false; - return 0; - } - } _pressed = (buf[2] != 0); int16_t ret = buf[0] | (buf[1] << 8); return ret; From 66200f1d921e72c0387ec07ba85a3dd7e17f2008 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 8 May 2025 17:09:43 +0200 Subject: [PATCH 7/9] Update API docs :recycle: --- docs/api.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api.md b/docs/api.md index 7c463c0..59529c9 100644 --- a/docs/api.md +++ b/docs/api.md @@ -90,6 +90,11 @@ Represents a Modulino Knob module. - **`bool isPressed()`** Returns `true` if the button on the knob is pressed, `false` otherwise. +- **`int8_t getDirection()`** + Returns the direction of the knob rotation. + - `1` for clockwise + - `-1` for counter-clockwise + - **`void set(int16_t value)`** Sets the knob value. From cff95ab82f7321a9ce6a1c9a7476aeb82a91a6b8 Mon Sep 17 00:00:00 2001 From: Antonio Bernardini Date: Thu, 8 May 2025 18:39:56 +0200 Subject: [PATCH 8/9] Update API docs :recycle: --- docs/api.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api.md b/docs/api.md index 59529c9..225181b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -94,6 +94,7 @@ Represents a Modulino Knob module. Returns the direction of the knob rotation. - `1` for clockwise - `-1` for counter-clockwise + - `0` if no movement is detected - **`void set(int16_t value)`** Sets the knob value. From 812cd950929bb1c4cc8792ea1726c46d42725092 Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis <45899760+leonardocavagnis@users.noreply.github.com> Date: Fri, 9 May 2025 10:04:51 +0200 Subject: [PATCH 9/9] Update examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino --- examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino index 4124081..60dc248 100644 --- a/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino +++ b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino @@ -30,7 +30,7 @@ void loop(){ Serial.print("Current position is: "); Serial.println(position); - if (click) { + if(click){ Serial.println("Clicked!"); }