diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 7c9ed7c..c058661 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -47,6 +47,7 @@ jobs: - source-path: ./ # Install library dependencies. - name: STM32duino VL53L4CD + - name: STM32duino VL53L4ED - name: Arduino_LSM6DSOX - name: Arduino_LPS22HB - name: Arduino_HS300x diff --git a/README.md b/README.md new file mode 100644 index 0000000..45f68f1 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# 🧩 Arduino Modulino® Library + +The Arduino Modulino® Library simplifies the integration and management of Modulino® modules on Arduino boards. + +A Modulino® is a compact, modular electronic device that connects easily to Arduino via the Qwiic connector and communicates using the I2C (`Wire`) protocol. These modules include sensors, actuators, and more. + +📖 For more information about this library please read the documentation [here](./docs/). + +## Hardware Compatibility +This library is compatible with all Arduino boards that feature an I2C interface (`Wire`). + +## Support and Contributions +If you find this library helpful, consider supporting us through [donations](https://www.arduino.cc/en/donate/), [sponsorship](https://github.com/sponsors/arduino) or check out our [store](https://store.arduino.cc/). \ No newline at end of file diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..f52c482 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,198 @@ +# Arduino Modulino Library API + +## Summary + + Members | Descriptions +--------------------------------------------|------------------------------------------ +| `class` [`ModulinoClass`](#modulinoclass) | The base class for all Modulino components, providing essential functionality and structure for all subsequent Modulino modules. | +| `class` [`ModulinoButtons`](#modulinobuttons) | Handles the functionality of Modulino Buttons, enabling detection of presses and handling input events. | +| `class` [`ModulinoBuzzer`](#modulinobuttons) |Handles the functionality of Modulino Buzzer, enabling the sound generation for feedback or alerts. | +| `class` [`ModulinoPixels`](#modulinopixels) | Handles the functionality of Modulino Pixels, managing LEDs strip color, status and brightness. | +| `class` [`ModulinoKnob`](#modulinoknob) | Handles the functionality of Modulino Knob, interfacing with the rotary knob position. | +| `class` [`ModulinoMovement`](#modulinomovement) | Handles the functionality of Modulino Movement,interfacing with the IMU sensor to get acceleration readings. | +| `class` [`ModulinoThermo`](#modulinothermo) | Handles the functionality of Modulino Thermo, managing temperature sensors to provide real-time temperature and humidity readings. | +| `class` [`ModulinoDistance`](#modulinodistance) | Handles the functionality of Modulino Distance, enabling distance measurement using ToF (Time-of-Flight) sensors for precise range detection. | + +### ModulinoClass + +The `ModulinoClass` is the main class that handles the initialization of the I2C communication bus. + +#### Methods + +- **`void begin(HardwareI2C& wire = Wire)`** + Initializes the I2C communication. The default I2C bus is `Wire`, but you can specify another one (e.g., `Wire1`). + +--- + +### ModulinoButtons + +Represents a Modulino Buttons module. + +#### Methods + +- **`PinStatus isPressed(int index)`** + Returns the press status (HIGH/LOW) of the button at the specified index (_0-A, 1-B, 2-C_). + +- **`PinStatus isPressed(char button)`** + Returns the press status (HIGH/LOW) of the button specified by its character ('A', 'B', 'C'). + +- **`PinStatus isPressed(const char *button)`** + Returns the press status (HIGH/LOW) of the button specified by its string ("A", "B", "C"). + +- **`bool update()`** + Updates the button status. Returns `true` if the status has changed, `false` otherwise. + +- **`void setLeds(bool a, bool b, bool c)`** + Sets the LED states. Each argument corresponds to one LED's state (on/off). + +--- + +### ModulinoBuzzer + +Represents a Modulino Buzzer module. + +#### Methods + +- **`void tone(size_t freq, size_t len_ms)`** + Plays a tone at the specified frequency (`freq`) and duration (`len_ms`). + +- **`void noTone()`** + Stops any tone currently playing. + +--- + +### ModulinoPixels + +Represents a Modulino Pixels module. + +#### Methods + +- **`void set(int idx, ModulinoColor rgb, uint8_t brightness = 25)`** + Sets the color of the LED at the specified index. + +- **`void set(int idx, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness = 5)`** + Sets the color of the LED at the specified index using RGB values. + +- **`void clear(int idx)`** + Clears the LED at the specified index (turns it off). + +- **`void clear()`** + Clears all LEDs (turns them all off). + +- **`void show()`** + Updates the LEDs to display the current color data. + +--- + +### ModulinoKnob + +Represents a Modulino Knob module. + +#### Methods + +- **`int16_t get()`** + Gets the current value of the knob. + +- **`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 + - `0` if no movement is detected + +- **`void set(int16_t value)`** + Sets the knob value. + +--- + +### ModulinoMovement + +Represents a Modulino Movement module. + +#### Methods + +- **`int update()`** + Updates the sensor data and reads the acceleration values. + +- **`int available()`** + Returns `true` if acceleration data is available. + +- **`float getX()`** + Returns the X-axis acceleration. + +- **`float getY()`** + Returns the Y-axis acceleration. + +- **`float getZ()`** + Returns the Z-axis acceleration. + +- **`float getRoll()`** + Returns the angular velocity around X-axis. + +- **`float getPitch()`** + Returns the angular velocity around Y-axis. + +- **`float getYaw()`** + Returns the angular velocity around Z-axis. + +--- + +### ModulinoThermo + +Represents a Modulino Thermo module. + +#### Methods + +- **`float getHumidity()`** + Returns the humidity reading. + +- **`float getTemperature()`** + Returns the temperature reading. + +--- + +### ModulinoDistance + +Represents a Modulino Distance module. + +#### Methods + +- **`available()`** + Checks if new distance data is available from the sensor. If data is ready, it reads the data and updates the distance value. + `true` if distance data is available, `false` if distance data is not available. + +- **`float get()`** + Returns the distance measured by the sensor in millimeters. + The measured distance in millimeters if available, `NAN` if the distance reading is invalid. + +## Constants + +- **`ModulinoColor RED`** + Represents the color red for Modulino Pixels modules. + +- **`ModulinoColor BLUE`** + Represents the color blue for Modulino Pixels modules. + +- **`ModulinoColor GREEN`** + Represents the color green for Modulino Pixels modules. + +- **`ModulinoColor VIOLET`** + Represents the color violet for Modulino Pixels modules. + +- **`ModulinoColor WHITE`** + Represents the color white for Modulino Pixels modules. + +### ModulinoColor + +Represents a color for Modulino Pixels modules. + +#### Constructor + +- **`ModulinoColor(uint8_t r, uint8_t g, uint8_t b)`** + Creates a color with the specified red (`r`), green (`g`), and blue (`b`) components. + +## License + +This library is released under the [MPL-2.0 license](../LICENSE). \ No newline at end of file diff --git a/docs/images/modulino-buttons.jpeg b/docs/images/modulino-buttons.jpeg new file mode 100644 index 0000000..229e68c Binary files /dev/null and b/docs/images/modulino-buttons.jpeg differ diff --git a/docs/images/modulino-buzzer.jpg b/docs/images/modulino-buzzer.jpg new file mode 100644 index 0000000..fb9a730 Binary files /dev/null and b/docs/images/modulino-buzzer.jpg differ diff --git a/docs/images/modulino-distance.jpg b/docs/images/modulino-distance.jpg new file mode 100644 index 0000000..806734a Binary files /dev/null and b/docs/images/modulino-distance.jpg differ diff --git a/docs/images/modulino-knob.jpg b/docs/images/modulino-knob.jpg new file mode 100644 index 0000000..6c68a16 Binary files /dev/null and b/docs/images/modulino-knob.jpg differ diff --git a/docs/images/modulino-movement.jpg b/docs/images/modulino-movement.jpg new file mode 100644 index 0000000..97d0d2d Binary files /dev/null and b/docs/images/modulino-movement.jpg differ diff --git a/docs/images/modulino-pixels.jpg b/docs/images/modulino-pixels.jpg new file mode 100644 index 0000000..8140a10 Binary files /dev/null and b/docs/images/modulino-pixels.jpg differ diff --git a/docs/images/modulino-thermo.jpg b/docs/images/modulino-thermo.jpg new file mode 100644 index 0000000..b5158d6 Binary files /dev/null and b/docs/images/modulino-thermo.jpg differ diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..de7bc45 --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,181 @@ +# Arduino Modulino® Library + +The **Modulino** library is designed to simplify integration with various Modulino. It supports a variety of modules, such as motion sensors, buttons, buzzers, LED displays, and more, all through an I2C (`Wire`) interface. + +## Hardware Compatibility + +The library is compatible with Arduino boards that support I2C (`Wire`) communication. + +Each Modulino has a fixed I2C address assigned by default. If you wish to change the I2C address, you can refer to the [Utilities](#utilities) section. + +## Main Features + +The **Modulino** library supports the following hardware modules: + +- **Buttons (`ModulinoButtons`)**: Read the state of buttons and control the associated LEDs. +- **Buzzer (`ModulinoBuzzer`)**: Activate and deactivate the buzzer and set its frequency. +- **LEDs (`ModulinoPixels`)**: Control RGB LEDs with customizable display modes. +- **Knob (`ModulinoKnob`)**: Read the value of a rotary encoder. +- **Motion (`ModulinoMovement`)**: Interface with the LSM6DSOX IMU sensor to get acceleration values. +- **Temperature & Humidity (`ModulinoThermo`)**: Get temperature and humidity readings from the HS300x sensor. +- **Distance (`ModulinoDistance`)**: Measures distance using a Time-of-Flight (ToF) sensor (VL53L0x). + +## Library Initialization + +To initialize the **Modulino** library, include the header file and call the `begin()` method. This will set up the I2C communication and prepare the library for use with the modules. + +```cpp +#include +Modulino.begin(); // Initialize the Modulino library +``` + +## Supported Modules + +You can initialize a Modulino board easily. The basic setup requires just a call to the `begin()` method for each module. For example: + +```cpp +ModulinoType modulino_name; +modulino_name.begin(); // Initialize the ModulinoType module +``` + +### ModulinoButtons +Manages the state of three buttons and controls their associated LED states. You can read the state of each button and send commands to turn the LEDs on/off. + +![Modulino Buttons](./images/modulino-buttons.jpeg) + +```cpp +ModulinoButtons buttons; +buttons.begin(); +buttons.setLeds(true, false, true); // Turn on LED 1 and LED 3 +``` + +### ModulinoBuzzer +Allows you to emit sounds through the buzzer. You can set the frequency and duration of the sound. + +![Modulino Buzzer](./images/modulino-buzzer.jpg) + +```cpp +ModulinoBuzzer buzzer; +buzzer.begin(); +buzzer.tone(440, 1000); // 440Hz frequency for 1000ms +``` + +### ModulinoPixels +Controls an array of 8 RGB LEDs, allowing you to set the colors and brightness. You can also clear individual LEDs or the entire array. + +![Modulino Pixels](./images/modulino-pixels.jpg) + +```cpp +ModulinoPixels leds; +leds.set(0, ModulinoColor(255, 0, 0)); // Set the first LED (Position: 0) to red +leds.show(); // Display the LEDs +``` + +### ModulinoKnob +Manages a rotary encoder, allowing you to read the potentiometer value and check if the knob is pressed. + +![Modulino Knob](./images/modulino-knob.jpg) + +```cpp +ModulinoKnob knob; +knob.begin(); +int16_t value = knob.get(); // Get the value of the encoder +``` + +### ModulinoMovement +Interfaces with the LSM6DSOX IMU sensor to get acceleration readings. + +![Modulino Movement](./images/modulino-movement.jpg) + +```cpp +ModulinoMovement movement; +movement.begin(); +float x = movement.getX(); +``` + +### ModulinoThermo +Reads temperature and humidity data from the HS300x sensor. + +![Modulino Thermo](./images/modulino-thermo.jpg) + +```cpp +ModulinoThermo thermo; +thermo.begin(); +float temperature = thermo.getTemperature(); +float humidity = thermo.getHumidity(); +``` + +### ModulinoDistance +Measures distance using a ToF (Time-of-Flight) sensor. + +![Modulino Distance](./images/modulino-distance.jpg) + +```cpp +ModulinoDistance distance; +distance.begin(); +float distanceValue = distance.get(); +``` + +## Example Usage + +Here’s an example of how to use some Modulino in a program: + +```cpp +// This sketch demonstrates how to use the Modulino library to control buttons, LEDs, and a buzzer. +// It listens for a button press (Button A), turns on the LED 0, and plays a sound through the buzzer when pressed. + +#include + +ModulinoButtons buttons; // Declare a Buttons Modulino +ModulinoPixels leds; // Declare a Pixels Modulino +ModulinoBuzzer buzzer; // Declare a Buzzer Modulino + +int frequency = 440; // Set frequency to 440Hz +int duration = 1000; // Set duration to 1000ms + +void setup() { + Serial.begin(9600); + + Modulino.begin(); // Initialize the Modulino library + + buttons.begin(); // Initialize the Buttons module + leds.begin(); // Initialize the Pixels module + buzzer.begin(); // Initialize the Buzzer module +} + +void loop() { + if (buttons.update()) { // Update the button states + if (buttons.isPressed(0)) { // Check if Button A (button 0) is pressed + Serial.println("Button A pressed!"); + leds.set(0, RED); // Turn on LED 0 to red + leds.show(); + + buzzer.tone(frequency, duration); // Play buzzer sound with the specified frequency and duration + delay(duration); + } else { + leds.clear(0); // Turn off LED 0 + leds.show(); + } + } +} +``` + +## Examples + +The examples folder is organized by Modulino type. Each module has its own folder with example sketches that demonstrate both basic and advanced usage (where applicable). + +You can explore the examples [here](../examples). + +### Utilities + +In the [Utilities](../examples/Utilities) folder, you will find programs designed to help you manage and manipulate the Modulino: + +- [AddressChanger](../examples/Utilities/AddressChanger/): This program allows you to change the I2C address of a Modulino module. It’s helpful when you need to reassign addresses to avoid conflicts or organize your I2C network. + +## API + +The API documentation can be found [here](./api.md). + +## License + +This library is released under the [MPL-2.0 license](../LICENSE). diff --git a/examples/Modulino_Buttons/Basic/Basic.ino b/examples/Modulino_Buttons/Basic/Basic.ino deleted file mode 100644 index c40209b..0000000 --- a/examples/Modulino_Buttons/Basic/Basic.ino +++ /dev/null @@ -1,28 +0,0 @@ -#include - -ModulinoButtons buttons; - -bool button_a = false; -bool button_b = false; -bool button_c = false; - -void setup() { - Serial.begin(9600); - Modulino.begin(); - buttons.begin(); - //function to control the LEDs on top of each button - buttons.setLeds(true, true, true); -} -void loop() { - //request new data from the Modulino buttons - if (buttons.update()) { - //Check if the buttons has been pressed - if (buttons.isPressed(0)) { - Serial.println("Button A pressed!"); - } else if (buttons.isPressed(1)) { - Serial.println("Button B pressed!"); - } else if (buttons.isPressed(2)) { - Serial.println("Button C pressed!"); - } - } -} \ No newline at end of file diff --git a/examples/Modulino_Buttons/Button2Integration/Button2Integration.ino b/examples/Modulino_Buttons/Button2Integration/Button2Integration.ino index 883bb6c..9f092c0 100644 --- a/examples/Modulino_Buttons/Button2Integration/Button2Integration.ino +++ b/examples/Modulino_Buttons/Button2Integration/Button2Integration.ino @@ -1,4 +1,11 @@ -// Integration with https://github.com/LennartHennigs/Button2 +/* + * Modulino Buttons - Button2 Integration + * Integration with https://github.com/LennartHennigs/Button2 + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ #include "Modulino.h" #include "Button2.h" 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..9d5e4da --- /dev/null +++ b/examples/Modulino_Buttons/Buttons_Basic/Buttons_Basic.ino @@ -0,0 +1,48 @@ +/* + * 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/examples/Modulino_Buzzer/Basic/Basic.ino b/examples/Modulino_Buzzer/Basic/Basic.ino deleted file mode 100644 index b66e419..0000000 --- a/examples/Modulino_Buzzer/Basic/Basic.ino +++ /dev/null @@ -1,20 +0,0 @@ -#include - -ModulinoBuzzer buzzer; - -int frequency = 440; -int duration = 1000; - -void setup(){ - Modulino.begin(); - buzzer.begin(); -} - -void loop(){ - - buzzer.tone(frequency, duration); - delay(1000); - buzzer.tone(0, duration); - delay(1000); - -} \ No newline at end of file diff --git a/examples/Modulino_Buzzer/Buzzer_Basic/Buzzer_Basic.ino b/examples/Modulino_Buzzer/Buzzer_Basic/Buzzer_Basic.ino new file mode 100644 index 0000000..47ebcf9 --- /dev/null +++ b/examples/Modulino_Buzzer/Buzzer_Basic/Buzzer_Basic.ino @@ -0,0 +1,33 @@ +/* + * Modulino Buzzer - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +// Create a ModulinoBuzzer object +ModulinoBuzzer buzzer; + +int frequency = 440; +int duration = 1000; + +void setup(){ + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to buzzer module + buzzer.begin(); +} + +void loop(){ + + // Play tone at specified frequency and duration + buzzer.tone(frequency, duration); + delay(1000); + // Stop the tone (0 frequency) + buzzer.tone(0, duration); + delay(1000); + +} \ No newline at end of file diff --git a/examples/Modulino_Buzzer/Simple_melody/Simple_melody.ino b/examples/Modulino_Buzzer/Simple_melody/Simple_melody.ino index 25c01cf..ba27151 100644 --- a/examples/Modulino_Buzzer/Simple_melody/Simple_melody.ino +++ b/examples/Modulino_Buzzer/Simple_melody/Simple_melody.ino @@ -1,19 +1,32 @@ +/* + * Modulino Buzzer - Simple melody + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include +// Create a ModulinoBuzzer object ModulinoBuzzer buzzer; +// Define melody notes in Hz (C4, G3, G3, A3, G3, rest, B3, C4) int melody[] = { 262, 196, 196, 220, 196, 0, 247, 262 }; void setup() { + // Initialize Modulino I2C communication Modulino.begin(); + // Detect and connect to buzzer module buzzer.begin(); } void loop() { - + // Play each note in the melody for (int i = 0; i < 8; i++) { + // Get current note frequency int note = melody[i]; - + // Play the note for 250ms buzzer.tone(note, 250); delay(250); diff --git a/examples/Modulino_Buzzer/Theremin/Theremin.ino b/examples/Modulino_Buzzer/Theremin/Theremin.ino new file mode 100644 index 0000000..fd79184 --- /dev/null +++ b/examples/Modulino_Buzzer/Theremin/Theremin.ino @@ -0,0 +1,32 @@ +#include "Modulino.h" + +ModulinoBuzzer buzzer; +ModulinoDistance distance; +ModulinoKnob encoder; + + +void setup() { + + Modulino.begin(); + encoder.begin(); + distance.begin(); + buzzer.begin(); +} + +int pitch = 0; +int noteIndex = 0; + +//Notes from C to B with # +int note[] = {262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494}; + +void loop() { + pitch = distance.get(); + noteIndex = encoder.get(); + + noteIndex = noteIndex % 11; + if (noteIndex < 0){ + noteIndex = 0; + } + + buzzer.tone(note[noteIndex] + pitch, 1000); +} \ No newline at end of file diff --git a/examples/Modulino_Distance/Basic/Basic.ino b/examples/Modulino_Distance/Basic/Basic.ino deleted file mode 100644 index 6d4d3e1..0000000 --- a/examples/Modulino_Distance/Basic/Basic.ino +++ /dev/null @@ -1,15 +0,0 @@ -#include "Modulino.h" - -ModulinoDistance distance; - -void setup() { - Serial.begin(9600); - Modulino.begin(); - distance.begin(); -} - -void loop() { - int measure = distance.get(); - Serial.println(measure); - delay(10); -} \ No newline at end of file diff --git a/examples/Modulino_Distance/Distance_Basic/Distance_Basic.ino b/examples/Modulino_Distance/Distance_Basic/Distance_Basic.ino new file mode 100644 index 0000000..08e298e --- /dev/null +++ b/examples/Modulino_Distance/Distance_Basic/Distance_Basic.ino @@ -0,0 +1,30 @@ +/* + * Modulino Distance - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Modulino.h" + +// Create a ModulinoDistance object +ModulinoDistance distance; + +void setup() { + Serial.begin(9600); + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to distance sensor module + distance.begin(); +} + +void loop() { + // Check if new distance measurement is available + if (distance.available()) { + // Get the latest distance measurement in millimeters + int measure = distance.get(); + Serial.println(measure); + } + delay(10); +} \ No newline at end of file diff --git a/examples/Modulino_Knob/Basic/Basic.ino b/examples/Modulino_Knob/Basic/Basic.ino deleted file mode 100644 index 879c940..0000000 --- a/examples/Modulino_Knob/Basic/Basic.ino +++ /dev/null @@ -1,22 +0,0 @@ -#include - -ModulinoKnob knob; - -void setup() { - Serial.begin(9600); - Modulino.begin(); - knob.begin(); -} - -void loop(){ - int position = knob.get(); - bool click = knob.isPressed(); - - Serial.print("Current position is: "); - Serial.println(position); - - if(click){ - Serial.println("Clicked!"); - } - -} \ No newline at end of file diff --git a/examples/Modulino_Knob/EncoderSetter/EncoderSetter.ino b/examples/Modulino_Knob/EncoderSetter/EncoderSetter.ino deleted file mode 100644 index f130a63..0000000 --- a/examples/Modulino_Knob/EncoderSetter/EncoderSetter.ino +++ /dev/null @@ -1,30 +0,0 @@ -#include "Modulino.h" - -ModulinoKnob encoder; -ModulinoPixels leds; -ModulinoButtons buttons; - -void setup() { - // put your setup code here, to run once: - Serial.begin(115200); - Modulino.begin(); - encoder.begin(); - leds.begin(); - buttons.begin(); -} - -void loop() { - int value = encoder.get(); - //Reset the position of the encoder with the set function - if (value > 100 || value < 0) { - encoder.set(0); - } - value = encoder.get(); - Serial.println(value); - leds.set(1, RED, value); - leds.set(2, GREEN, value); - leds.set(3, BLUE, value); - leds.show(); - buttons.update(); - buttons.setLeds(buttons.isPressed(0), buttons.isPressed(1), buttons.isPressed(2)); -} diff --git a/examples/Modulino_Knob/Encoder_Setter/Encoder_Setter.ino b/examples/Modulino_Knob/Encoder_Setter/Encoder_Setter.ino new file mode 100644 index 0000000..9f91112 --- /dev/null +++ b/examples/Modulino_Knob/Encoder_Setter/Encoder_Setter.ino @@ -0,0 +1,50 @@ +/* + * Modulino Knob - Encoder Setter + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Modulino.h" + +// Create objects for the modules +ModulinoKnob encoder; +ModulinoPixels leds; +ModulinoButtons buttons; + +void setup() { + Serial.begin(115200); + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to modules + encoder.begin(); + leds.begin(); + buttons.begin(); +} + +void loop() { + // Get current encoder position value + int value = encoder.get(); + // Reset encoder position if out of range (0-100) + if (value > 100 || value < 0) { + encoder.set(0); + } + + // Get updated encoder value after possible reset + value = encoder.get(); + + Serial.println(value); + + // Set LED brightness based on encoder value (0-100) + // Available colors: RED, BLUE, GREEN, VIOLET, WHITE + leds.set(1, RED, value); + leds.set(2, GREEN, value); + leds.set(3, BLUE, value); + // Update LEDs with new settings + leds.show(); + // Check button states + buttons.update(); + // Set button LEDs to match button press states + buttons.setLeds(buttons.isPressed(0), buttons.isPressed(1), buttons.isPressed(2)); +} diff --git a/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino new file mode 100644 index 0000000..60dc248 --- /dev/null +++ b/examples/Modulino_Knob/Knob_Basic/Knob_Basic.ino @@ -0,0 +1,44 @@ +/* + * Modulino Knob - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +// Create a ModulinoKnob object +ModulinoKnob knob; + +void setup() { + Serial.begin(9600); + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to knob module + knob.begin(); +} + +void loop(){ + // Get the current position value of the knob + 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){ + Serial.println("Clicked!"); + } + + 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/examples/Modulino_Movement/Basic/Basic.ino b/examples/Modulino_Movement/Basic/Basic.ino deleted file mode 100644 index 956ae54..0000000 --- a/examples/Modulino_Movement/Basic/Basic.ino +++ /dev/null @@ -1,29 +0,0 @@ -#include "Modulino.h" - -ModulinoMovement movement; - -float x; -float y; -float z; - -void setup() { - Serial.begin(9600); - Modulino.begin(); - movement.begin(); -} - -void loop() { - movement.update(); - - x = movement.getX(); - y = movement.getY(); - z = movement.getZ(); - - Serial.print("Movement data: "); - Serial.print("x "); - Serial.print(x, 3); - Serial.print(" y "); - Serial.print(y, 3); - Serial.print(" z "); - Serial.println(z, 3); -} \ No newline at end of file diff --git a/examples/Modulino_Movement/Movement_Basic/Movement_Basic.ino b/examples/Modulino_Movement/Movement_Basic/Movement_Basic.ino new file mode 100644 index 0000000..4868dca --- /dev/null +++ b/examples/Modulino_Movement/Movement_Basic/Movement_Basic.ino @@ -0,0 +1,58 @@ +/* + * Modulino Movement - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include "Modulino.h" + +// Create a ModulinoMovement +ModulinoMovement movement; + + +float x, y, z; +float roll, pitch, yaw; + + +void setup() { + Serial.begin(9600); + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to movement sensor module + movement.begin(); +} + +void loop() { + // Read new movement data from the sensor + movement.update(); + + // Get acceleration and gyroscope values + x = movement.getX(); + y = movement.getY(); + z = movement.getZ(); + roll = movement.getRoll(); + pitch = movement.getPitch(); + yaw = movement.getYaw(); + + // Print acceleration values + Serial.print("A: "); + Serial.print(x, 3); + Serial.print(", "); + Serial.print(y, 3); + Serial.print(", "); + Serial.print(z, 3); + + // Print divider between acceleration and gyroscope + Serial.print(" | G: "); + + // Print gyroscope values + Serial.print(roll, 1); + Serial.print(", "); + Serial.print(pitch, 1); + Serial.print(", "); + Serial.println(yaw, 1); + + delay(200); +} \ No newline at end of file diff --git a/examples/Modulino_Pixels/Basic/Basic.ino b/examples/Modulino_Pixels/Basic/Basic.ino deleted file mode 100644 index 88099a5..0000000 --- a/examples/Modulino_Pixels/Basic/Basic.ino +++ /dev/null @@ -1,18 +0,0 @@ -#include - -ModulinoPixels leds; - -int brightness = 25; - -void setup(){ - Modulino.begin(); - leds.begin(); -} - -void loop(){ - //Set all LEDs blue - for (int i = 0; i < 8; i++) { - leds.set(i, BLUE, brightness); - leds.show(); - } -} \ No newline at end of file diff --git a/examples/Modulino_Pixels/Pixels_Basic/Pixels_Basic.ino b/examples/Modulino_Pixels/Pixels_Basic/Pixels_Basic.ino new file mode 100644 index 0000000..69be734 --- /dev/null +++ b/examples/Modulino_Pixels/Pixels_Basic/Pixels_Basic.ino @@ -0,0 +1,32 @@ +/* + * Modulino Pixels - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +// Create a ModulinoPixels object +ModulinoPixels leds; + +int brightness = 25; + +void setup(){ + // Initialize Modulino I2C communication + Modulino.begin(); + // Detect and connect to pixels module + leds.begin(); +} + +void loop(){ + // Set all 8 LEDs to blue color + for (int i = 0; i < 8; i++) { + // Set each LED (index, color, brightness) + // Available colors: RED, BLUE, GREEN, VIOLET, WHITE + leds.set(i, BLUE, brightness); + // Update the physical LEDs with new settings + leds.show(); + } +} \ No newline at end of file diff --git a/examples/Modulino_Pixels/Simple_Animation/Simple_Animation.ino b/examples/Modulino_Pixels/Simple_Animation/Simple_Animation.ino index addec14..40c1c26 100644 --- a/examples/Modulino_Pixels/Simple_Animation/Simple_Animation.ino +++ b/examples/Modulino_Pixels/Simple_Animation/Simple_Animation.ino @@ -1,18 +1,31 @@ +/* + * Modulino Pixels - Simple Animation + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include +// Create a ModulinoPixels object for the LED array ModulinoPixels leds; +// Define a custom color for turning off LEDs ModulinoColor OFF(0, 0, 0); int brightness = 25; void setup() { + // Initialize Modulino I2C communication Modulino.begin(); + // Detect and connect to pixels module leds.begin(); } void loop() { - + // Light up LEDs in different colors + // Available colors: RED, BLUE, GREEN, VIOLET, WHITE for (int i = 0; i < 8; i++) { if (i == 0 || i == 1) { setPixel(i, RED); @@ -29,7 +42,8 @@ void loop() { delay(25); } - + + // Turn off all LEDs one by one for (int i = 0; i < 8; i++) { setPixel(i, OFF); delay(25); diff --git a/examples/Modulino_Thermo/TemperatureHumidityMatrix/TemperatureHumidityMatrix.ino b/examples/Modulino_Thermo/Temperature_Humidity_Matrix/Temperature_Humidity_Matrix.ino similarity index 74% rename from examples/Modulino_Thermo/TemperatureHumidityMatrix/TemperatureHumidityMatrix.ino rename to examples/Modulino_Thermo/Temperature_Humidity_Matrix/Temperature_Humidity_Matrix.ino index 20335f3..57de8de 100644 --- a/examples/Modulino_Thermo/TemperatureHumidityMatrix/TemperatureHumidityMatrix.ino +++ b/examples/Modulino_Thermo/Temperature_Humidity_Matrix/Temperature_Humidity_Matrix.ino @@ -1,8 +1,18 @@ +/* + * Modulino Thermo - Temperature Humidity Matrix + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include "Modulino.h" #include "ArduinoGraphics.h" #include "Arduino_LED_Matrix.h" +// Create a ModulinoThermo object ModulinoThermo thermo; +// Create an object to control the LED matrix on UNO R4 WiFi ArduinoLEDMatrix matrix; float temperature = -273.15; @@ -11,9 +21,12 @@ float humidity = 0.0; void setup() { Serial.begin(9600); + // Initialize Modulino I2C communication Modulino.begin(); + // Detect and connect to temperature/humidity sensor module thermo.begin(); + // Initialize the LED matrix matrix.begin(); delay(100); } diff --git a/examples/Modulino_Thermo/Basic/Basic.ino b/examples/Modulino_Thermo/Thermo_Basic/Thermo_Basic.ino similarity index 56% rename from examples/Modulino_Thermo/Basic/Basic.ino rename to examples/Modulino_Thermo/Thermo_Basic/Thermo_Basic.ino index 74894c2..d219fce 100644 --- a/examples/Modulino_Thermo/Basic/Basic.ino +++ b/examples/Modulino_Thermo/Thermo_Basic/Thermo_Basic.ino @@ -1,3 +1,11 @@ +/* + * Modulino Thermo - Basic + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include // Create object instance @@ -6,17 +14,20 @@ ModulinoThermo thermo; void setup(){ Serial.begin(9600); - // Call all necessary .begin() function + // Initialize Modulino I2C communication Modulino.begin(); + // Detect and connect to temperature/humidity sensor module thermo.begin(); } void loop(){ - + // Read temperature in Celsius from the sensor float celsius = thermo.getTemperature(); + // Convert Celsius to Fahrenheit float fahrenheit = (celsius * 9 / 5) + 32; + // Read humidity percentage from the sensor float humidity = thermo.getHumidity(); Serial.print("Temperature (C) is: "); diff --git a/examples/Utilities/AddressChanger/AddressChanger.ino b/examples/Utilities/AddressChanger/AddressChanger.ino index 3081be1..abe4181 100644 --- a/examples/Utilities/AddressChanger/AddressChanger.ino +++ b/examples/Utilities/AddressChanger/AddressChanger.ino @@ -1,3 +1,11 @@ +/* + * Modulino - Address Changer + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include "Wire.h" // Setting new_address to 0 means that the module will get back its original address diff --git a/examples/Utilities/FirmwareUpdater/FirmwareUpdater.ino b/examples/Utilities/FirmwareUpdater/FirmwareUpdater.ino index 166d44b..3d6068a 100644 --- a/examples/Utilities/FirmwareUpdater/FirmwareUpdater.ino +++ b/examples/Utilities/FirmwareUpdater/FirmwareUpdater.ino @@ -1,5 +1,15 @@ +/* + * Modulino - Firmware Updater + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + +#if defined(ARDUINO_UNOWIFIR4) #include "ArduinoGraphics.h" #include "Arduino_LED_Matrix.h" +#endif #include "Modulino.h" #include "Wire.h" @@ -20,11 +30,14 @@ void setup() { } auto result = flash(node_base_bin, node_base_bin_len); + + #if defined(ARDUINO_UNOWIFIR4) if (result) { matrixInitAndDraw("PASS"); } else { matrixInitAndDraw("FAIL"); } + #endif } void loop() { @@ -53,6 +66,7 @@ class SerialVerbose { bool _verbose; }; +#if defined(ARDUINO_UNOWIFIR4) ArduinoLEDMatrix matrix; void matrixInitAndDraw(char* text) { @@ -67,6 +81,7 @@ void matrixInitAndDraw(char* text) { matrix.endDraw(); } +#endif bool flash(const uint8_t* binary, size_t lenght, bool verbose) { diff --git a/examples/Utilities/Modulino_PlugNPlay/Modulino_PlugNPlay.ino b/examples/Utilities/Modulino_PlugNPlay/Modulino_PlugNPlay.ino index 792c170..5fcc7cf 100644 --- a/examples/Utilities/Modulino_PlugNPlay/Modulino_PlugNPlay.ino +++ b/examples/Utilities/Modulino_PlugNPlay/Modulino_PlugNPlay.ino @@ -1,5 +1,14 @@ +/* + * Modulino - Plug and Play + * + * This example code is in the public domain. + * Copyright (c) 2025 Arduino + * SPDX-License-Identifier: MPL-2.0 + */ + #include "Modulino.h" +// Create objects for all Modulino modules ModulinoButtons buttons; ModulinoBuzzer buzzer; ModulinoPixels leds; @@ -11,15 +20,14 @@ ModulinoThermo thermo; void setup() { Serial.begin(115200); + // Initialize Modulino I2C communication Modulino.begin(); - + // Detect and connect to all modules distance.begin(); - buttons.begin(); encoder.begin(); buzzer.begin(); leds.begin(); - imu.begin(); thermo.begin(); } @@ -35,14 +43,17 @@ void loop() { float x; float y; float z; - + // Cycle through LED patterns when encoder is pressed if (encoder.isPressed()) { skip = (skip + 1) % 5; } - pitch = encoder.get() + distance.get(); + // Calculate pitch by combining encoder position and distance sensor value + pitch = encoder.get() + (distance.available() ? distance.get() : 0); + // When 's' is received over serial, report sensor data if (Serial.available() && Serial.read() == 's') { + // Update and report accelerometer values imu.update(); Serial.print("IMU: x "); Serial.print(imu.getX(), 3); @@ -51,29 +62,35 @@ void loop() { Serial.print("\tz "); Serial.println(imu.getZ(), 3); + // Report temperature and humidity values Serial.print("Humidity: " + String(thermo.getHumidity())); Serial.println("\tTemperature: " + String(thermo.getTemperature())); } + // Check for button presses if (buttons.update()) { + // Button A: Red LED and 440Hz tone if (buttons.isPressed(0)) { leds.set(1 + skip, RED, 100); buzzer.tone(440 + pitch, 1000); } else { leds.clear(1 + skip); } + // Button B: Blue LED and 880Hz tone if (buttons.isPressed(1)) { leds.set(2 + skip, BLUE, 100); buzzer.tone(880 + pitch, 1000); } else { leds.clear(2 + skip); } + // Button C: Green LED and 1240Hz tone if (buttons.isPressed(2)) { leds.set(3 + skip, GREEN, 100); buzzer.tone(1240 + pitch, 1000); } else { leds.clear(3 + skip); } + // Update the LEDs leds.show(); } } diff --git a/library.properties b/library.properties index d0cfb87..8989efb 100644 --- a/library.properties +++ b/library.properties @@ -1,11 +1,11 @@ name=Modulino -version=0.3.0 +version=0.5.0 author=Arduino maintainer=Arduino sentence=Arduino Library for Modulinos -paragraph= +paragraph=The Arduino Modulino® Library simplifies the integration of Modulino®, compact devices that connect via Qwiic and communicate over I2C. It provides an easy-to-use interface for working with sensors, actuators, and other modules on Arduino boards. category=Communication url=https://github.com/arduino-libraries/Modulino architectures=* includes=Modulino.h -depends=STM32duino VL53L4CD,Arduino_LSM6DSOX,Arduino_LPS22HB,Arduino_HS300x +depends=STM32duino VL53L4CD,STM32duino VL53L4ED,Arduino_LSM6DSOX,Arduino_LPS22HB,Arduino_HS300x,ArduinoGraphics diff --git a/src/Modulino.cpp b/src/Modulino.cpp index fc74b38..9c3ef2c 100644 --- a/src/Modulino.cpp +++ b/src/Modulino.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2024 Arduino SA +// Copyright (c) 2025 Arduino SA // SPDX-License-Identifier: MPL-2.0 #include "Modulino.h" @@ -11,4 +11,19 @@ ModulinoColor RED(255, 0, 0); ModulinoColor BLUE(0, 0, 255); ModulinoColor GREEN(0, 255, 0); ModulinoColor VIOLET(255, 0, 255); -ModulinoColor WHITE(255, 255, 255); \ No newline at end of file +ModulinoColor WHITE(255, 255, 255); + +#if __has_include("Arduino_LED_Matrix.h") +void __increaseI2CPriority() { + for (int i = 0; i < 96; i++) { + if (R_ICU->IELSR[i] == BSP_PRV_IELS_ENUM(EVENT_IIC0_TXI)) { + NVIC_SetPriority(IRQn_Type(i), 6); + NVIC_SetPriority(IRQn_Type(i+1), 6); + NVIC_SetPriority(IRQn_Type(i+2), 6); + NVIC_SetPriority(IRQn_Type(i+3), 6); + } + } +} +#else +void __increaseI2CPriority() {} +#endif \ No newline at end of file diff --git a/src/Modulino.h b/src/Modulino.h index 95a406e..a79d4b5 100644 --- a/src/Modulino.h +++ b/src/Modulino.h @@ -1,9 +1,17 @@ -// Copyright (c) 2024 Arduino SA +// Copyright (c) 2025 Arduino SA // SPDX-License-Identifier: MPL-2.0 +#ifndef ARDUINO_LIBRARIES_MODULINO_H +#define ARDUINO_LIBRARIES_MODULINO_H + +#if defined(ESP32) && defined(BOARD_HAS_PIN_REMAP) && defined(tone) + #error "The current configuration is unsupported, switch Pin Numbering to "By GPIO number" or #undef tone and #undef noTone in the beginning of your sketch." + #error "Learn more at: https://support.arduino.cc/hc/en-us/articles/10483225565980-Select-pin-numbering-for-Nano-ESP32-in-Arduino-IDE" +#endif + #include "Wire.h" -#include #include // from stm32duino +#include // from stm32duino #include "Arduino_LSM6DSOX.h" #include #include @@ -14,6 +22,8 @@ #define HardwareI2C TwoWire #endif +void __increaseI2CPriority(); + class ModulinoClass { public: #ifdef ARDUINO_UNOR4_WIFI @@ -33,6 +43,7 @@ class ModulinoClass { _wire = &wire; _wire->begin(); _wire->setClock(100000); + __increaseI2CPriority(); } friend class Module; protected: @@ -43,10 +54,11 @@ extern ModulinoClass Modulino; class Module : public Printable { public: - Module(uint8_t address = 0xFF, char* name = "") - : address(address), name(name) {} + Module(uint8_t address = 0xFF, const char* name = "") + : address(address), name((char *)name) {} + virtual ~Module() {} bool begin() { - if (address == 0xFF) { + if (address >= 0x7F) { address = discover() / 2; // divide by 2 to match address in fw main.c } return (address < 0x7F); @@ -120,6 +132,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); @@ -138,7 +161,7 @@ class ModulinoButtons : public Module { return; } virtual uint8_t discover() { - for (int i = 0; i < match.size(); i++) { + for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { if (scan(match[i])) { return match[i]; } @@ -147,8 +170,16 @@ 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: - std::vector match = { 0x7C }; // same as fw main.c + uint8_t match[1] = { 0x7C }; // same as fw main.c }; class ModulinoBuzzer : public Module { @@ -167,7 +198,7 @@ class ModulinoBuzzer : public Module { write(buf, 8); } virtual uint8_t discover() { - for (int i = 0; i < match.size(); i++) { + for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { if (scan(match[i])) { return match[i]; } @@ -175,7 +206,7 @@ class ModulinoBuzzer : public Module { return 0xFF; } protected: - std::vector match = { 0x3C }; // same as fw main.c + uint8_t match[1] = { 0x3C }; // same as fw main.c }; class ModulinoColor { @@ -214,7 +245,7 @@ class ModulinoPixels : public Module { write((uint8_t*)data, NUMLEDS * 4); } virtual uint8_t discover() { - for (int i = 0; i < match.size(); i++) { + for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { if (scan(match[i])) { return match[i]; } @@ -225,7 +256,7 @@ class ModulinoPixels : public Module { static const int NUMLEDS = 8; uint32_t data[NUMLEDS]; protected: - std::vector match = { 0x6C }; + uint8_t match[1] = { 0x6C }; }; @@ -236,8 +267,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; @@ -270,8 +302,26 @@ 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 (int i = 0; i < match.size(); i++) { + for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) { if (scan(match[i])) { return match[i]; } @@ -281,8 +331,11 @@ 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: - std::vector match = { 0x74, 0x76 }; + uint8_t match[2] = { 0x74, 0x76 }; }; extern ModulinoColor RED; @@ -298,6 +351,7 @@ class ModulinoMovement : public Module { _imu = new LSM6DSOXClass(*((TwoWire*)getWire()), 0x6A); } initialized = _imu->begin(); + __increaseI2CPriority(); return initialized != 0; } operator bool() { @@ -305,7 +359,15 @@ class ModulinoMovement : public Module { } int update() { if (initialized) { - return _imu->readAcceleration(x, y, z); + int accel = _imu->readAcceleration(x, y, z); + int gyro = _imu->readGyroscope(roll, pitch, yaw); + return accel && gyro; + } + return 0; + } + int available() { + if (initialized) { + return _imu->accelerationAvailable() && _imu->gyroscopeAvailable(); } return 0; } @@ -318,9 +380,19 @@ class ModulinoMovement : public Module { float getZ() { return z; } + float getRoll() { + return roll; + } + float getPitch() { + return pitch; + } + float getYaw() { + return yaw; + } private: LSM6DSOXClass* _imu = nullptr; float x,y,z; + float roll,pitch,yaw; //gx, gy, gz int initialized = 0; }; @@ -331,6 +403,7 @@ class ModulinoThermo: public Module { _sensor = new HS300xClass(*((TwoWire*)getWire())); } initialized = _sensor->begin(); + __increaseI2CPriority(); return initialized; } operator bool() { @@ -364,6 +437,7 @@ class ModulinoPressure : public Module { // unfortunately LPS22HBClass calles Wire.end() on failure, restart it getWire()->begin(); } + __increaseI2CPriority(); return initialized != 0; } operator bool() { @@ -390,6 +464,52 @@ class ModulinoLight : public Module { }; +class _distance_api { +public: + _distance_api(VL53L4CD* sensor) : sensor(sensor) { + isVL53L4CD = true; + }; + _distance_api(VL53L4ED* sensor) : sensor(sensor) {}; + uint8_t setRangeTiming(uint32_t timing_budget_ms, uint32_t inter_measurement_ms) { + if (isVL53L4CD) { + return ((VL53L4CD*)sensor)->VL53L4CD_SetRangeTiming(timing_budget_ms, inter_measurement_ms); + } else { + return ((VL53L4ED*)sensor)->VL53L4ED_SetRangeTiming(timing_budget_ms, inter_measurement_ms); + } + } + uint8_t startRanging() { + if (isVL53L4CD) { + return ((VL53L4CD*)sensor)->VL53L4CD_StartRanging(); + } else { + return ((VL53L4ED*)sensor)->VL53L4ED_StartRanging(); + } + } + uint8_t checkForDataReady(uint8_t* p_is_data_ready) { + if (isVL53L4CD) { + return ((VL53L4CD*)sensor)->VL53L4CD_CheckForDataReady(p_is_data_ready); + } else { + return ((VL53L4ED*)sensor)->VL53L4ED_CheckForDataReady(p_is_data_ready); + } + } + uint8_t clearInterrupt() { + if (isVL53L4CD) { + return ((VL53L4CD*)sensor)->VL53L4CD_ClearInterrupt(); + } else { + return ((VL53L4ED*)sensor)->VL53L4ED_ClearInterrupt(); + } + } + uint8_t getResult(void* result) { + if (isVL53L4CD) { + return ((VL53L4CD*)sensor)->VL53L4CD_GetResult((VL53L4CD_Result_t*)result); + } else { + return ((VL53L4ED*)sensor)->VL53L4ED_GetResult((VL53L4ED_ResultsData_t*)result); + } + } +private: + void* sensor; + bool isVL53L4CD = false; +}; + class ModulinoDistance : public Module { public: bool begin() { @@ -400,38 +520,58 @@ class ModulinoDistance : public Module { } tof_sensor = new VL53L4CD((TwoWire*)getWire(), -1); auto ret = tof_sensor->InitSensor(); - if (ret == VL53L4CD_ERROR_NONE) { - tof_sensor->VL53L4CD_SetRangeTiming(20, 0); - tof_sensor->VL53L4CD_StartRanging(); - return true; - } else { + if (ret != VL53L4CD_ERROR_NONE) { + delete tof_sensor; tof_sensor = nullptr; - return false; + tof_sensor_alt = new VL53L4ED((TwoWire*)getWire(), -1); + ret = tof_sensor_alt->InitSensor(); + if (ret == VL53L4ED_ERROR_NONE) { + api = new _distance_api(tof_sensor_alt); + } else { + delete tof_sensor_alt; + tof_sensor_alt = nullptr; + return false; + } + } else { + api = new _distance_api(tof_sensor); } + + __increaseI2CPriority(); + api->setRangeTiming(20, 0); + api->startRanging(); + return true; } operator bool() { - return (tof_sensor != nullptr); + return (api != nullptr); } - float get() { - if (tof_sensor == nullptr) { - return NAN; + bool available() { + if (api == nullptr) { + return false; } + uint8_t NewDataReady = 0; - tof_sensor->VL53L4CD_CheckForDataReady(&NewDataReady); + api->checkForDataReady(&NewDataReady); if (NewDataReady) { - tof_sensor->VL53L4CD_ClearInterrupt(); - tof_sensor->VL53L4CD_GetResult(&results); + api->clearInterrupt(); + api->getResult(&results); } if (results.range_status == 0) { - return results.distance_mm; + internal = results.distance_mm; } else { - return NAN; + internal = NAN; } + return !isnan(internal); } - bool isValid(float distance) { - return !isnan(distance); + float get() { + return internal; } private: VL53L4CD* tof_sensor = nullptr; + VL53L4ED* tof_sensor_alt = nullptr; VL53L4CD_Result_t results; -}; \ No newline at end of file + //VL53L4ED_ResultsData_t results; + float internal = NAN; + _distance_api* api = nullptr; +}; + +#endif