diff --git a/examples/breakout_encoder_wheel/CMakeLists.txt b/examples/breakout_encoder_wheel/CMakeLists.txt index 680046f7..d258674e 100644 --- a/examples/breakout_encoder_wheel/CMakeLists.txt +++ b/examples/breakout_encoder_wheel/CMakeLists.txt @@ -4,5 +4,6 @@ add_subdirectory(clock) add_subdirectory(colour_picker) add_subdirectory(encoder) add_subdirectory(gpio_pwm) +add_subdirectory(interrupt) add_subdirectory(led_rainbow) add_subdirectory(stop_watch) \ No newline at end of file diff --git a/examples/breakout_encoder_wheel/README.md b/examples/breakout_encoder_wheel/README.md index 18c5be99..d8f30a85 100644 --- a/examples/breakout_encoder_wheel/README.md +++ b/examples/breakout_encoder_wheel/README.md @@ -3,6 +3,7 @@ - [Function Examples](#function-examples) - [Buttons](#buttons) - [Encoder](#encoder) + - [Interrupt](#interrupt) - [LED Examples](#led-examples) - [LED Rainbow](#led-rainbow) - [Clock](#clock) @@ -28,6 +29,12 @@ A demonstration of reading the 5 buttons on Encoder Wheel. A demonstration of reading the rotary dial of the Encoder Wheel breakout. +### Interrupt +[interrupt/interrupt.cpp](interrupt/interrupt.cpp) + +How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs. + + ## LED Examples ### LED Rainbow diff --git a/examples/breakout_encoder_wheel/interrupt/CMakeLists.txt b/examples/breakout_encoder_wheel/interrupt/CMakeLists.txt new file mode 100644 index 00000000..a10f054c --- /dev/null +++ b/examples/breakout_encoder_wheel/interrupt/CMakeLists.txt @@ -0,0 +1,13 @@ +set(OUTPUT_NAME encoderwheel_interrupt) +add_executable(${OUTPUT_NAME} interrupt.cpp) + +# Pull in pico libraries that we need +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + breakout_encoder_wheel +) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/breakout_encoder_wheel/interrupt/interrupt.cpp b/examples/breakout_encoder_wheel/interrupt/interrupt.cpp new file mode 100644 index 00000000..6d822ffd --- /dev/null +++ b/examples/breakout_encoder_wheel/interrupt/interrupt.cpp @@ -0,0 +1,84 @@ +#include +#include +#include "pimoroni_i2c.hpp" +#include "breakout_encoder_wheel.hpp" +#include "time.h" + +using namespace pimoroni; +using namespace encoderwheel; + +/* +How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs. +*/ + +// Constants +const std::string BUTTON_NAMES[] = {"Up", "Down", "Left", "Right", "Centre"}; + +// Create a new BreakoutEncoderWheel +I2C i2c(BOARD::BREAKOUT_GARDEN); +BreakoutEncoderWheel wheel(&i2c, + BreakoutEncoderWheel::DEFAULT_IOE_I2C_ADDRESS, + BreakoutEncoderWheel::DEFAULT_LED_I2C_ADDRESS, + 3); // 3 for BG_BASE, 22 for EXPLORER_BASE, or 19 for some RP2040 boards +// If wiring the breakout via the qw/st connector, use the below line instead +// BreakoutEncoderWheel wheel(&i2c); + +// Variables +bool last_pressed[NUM_BUTTONS] = {false, false, false, false, false}; +bool pressed[NUM_BUTTONS] = {false, false, false, false, false}; +int position = 0; +float hue = 0.0f; + + +int main() { + stdio_init_all(); + + // Attempt to initialise the encoder wheel + if(wheel.init()) { + + // Set the first LED + wheel.clear(); + wheel.set_hsv(position, hue, 1.0f, 1.0f); + wheel.show(); + + // Clear any left over interrupt from previous code + wheel.clear_interrupt_flag(); + + // Loop forever + while(true) { + + // Check if the interrupt has fired + if(wheel.get_interrupt_flag()) { + wheel.clear_interrupt_flag(); + + // Read all of the encoder wheel's buttons + for(int b = 0 ; b < NUM_BUTTONS; b++) { + pressed[b] = wheel.pressed(b); + if(pressed[b] != last_pressed[b]) { + printf("%s %s\n", BUTTON_NAMES[b].c_str(), pressed[b] ? "Pressed" : "Released"); + } + last_pressed[b] = pressed[b]; + } + + // The interrupt may have come from several sources, + // so check if it was a position change + int new_position = wheel.step(); + if(new_position != position) { + // Record the new position (from 0 to 23) + position = new_position; + printf("Position = %d\n", position); + + // Record a colour hue from 0.0 to 1.0 + hue = fmodf(wheel.revolutions(), 1.0f); + + // Set the LED at the new position to the new hue + wheel.clear(); + wheel.set_hsv(position, hue, 1.0f, 1.0f); + wheel.show(); + } + } + } + } + + return 0; +} \ No newline at end of file diff --git a/libraries/breakout_encoder_wheel/breakout_encoder_wheel.cpp b/libraries/breakout_encoder_wheel/breakout_encoder_wheel.cpp index 2fe9a1c4..61d6431d 100644 --- a/libraries/breakout_encoder_wheel/breakout_encoder_wheel.cpp +++ b/libraries/breakout_encoder_wheel/breakout_encoder_wheel.cpp @@ -17,6 +17,12 @@ namespace encoderwheel { ioe.set_mode(SW_RIGHT, IOExpander::PIN_IN_PU); ioe.set_mode(SW_CENTRE, IOExpander::PIN_IN_PU); + ioe.set_pin_interrupt(SW_UP, true); + ioe.set_pin_interrupt(SW_DOWN, true); + ioe.set_pin_interrupt(SW_LEFT, true); + ioe.set_pin_interrupt(SW_RIGHT, true); + ioe.set_pin_interrupt(SW_CENTRE, true); + led_ring.enable({ 0b00000000, 0b10111111, 0b00111110, 0b00111110, diff --git a/micropython/examples/breakout_encoder_wheel/README.md b/micropython/examples/breakout_encoder_wheel/README.md index c633ec2a..7adda3f7 100644 --- a/micropython/examples/breakout_encoder_wheel/README.md +++ b/micropython/examples/breakout_encoder_wheel/README.md @@ -3,6 +3,7 @@ - [Function Examples](#function-examples) - [Buttons](#buttons) - [Encoder](#encoder) + - [Interrupt](#interrupt) - [LED Examples](#led-examples) - [LED Rainbow](#led-rainbow) - [Clock](#clock) @@ -28,6 +29,12 @@ A demonstration of reading the 5 buttons on Encoder Wheel. A demonstration of reading the rotary dial of the Encoder Wheel breakout. +### Interrupt +[interrupt.py](interrupt.py) + +How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs. + + ## LED Examples ### LED Rainbow diff --git a/micropython/examples/breakout_encoder_wheel/encoder.py b/micropython/examples/breakout_encoder_wheel/encoder.py index b35b59ab..8d3783cc 100644 --- a/micropython/examples/breakout_encoder_wheel/encoder.py +++ b/micropython/examples/breakout_encoder_wheel/encoder.py @@ -8,9 +8,6 @@ A demonstration of reading the rotary dial of the Encoder Wheel breakout. Press Ctrl+C to stop the program. """ -PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} -PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} - # Create a new BreakoutEncoderWheel i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS) wheel = BreakoutEncoderWheel(i2c) diff --git a/micropython/examples/breakout_encoder_wheel/interrupt.py b/micropython/examples/breakout_encoder_wheel/interrupt.py new file mode 100644 index 00000000..f0b839a0 --- /dev/null +++ b/micropython/examples/breakout_encoder_wheel/interrupt.py @@ -0,0 +1,62 @@ +from pimoroni_i2c import PimoroniI2C +from pimoroni import BREAKOUT_GARDEN_I2C_PINS # or PICO_EXPLORER_I2C_PINS or HEADER_I2C_PINS +from breakout_encoder_wheel import BreakoutEncoderWheel, NUM_BUTTONS + +""" +How to read the buttons and rotary dial of the Encoder Wheel breakout, only when an interrupt occurs. + +Press Ctrl+C to stop the program. +""" + +# Constants +BUTTON_NAMES = ["Up", "Down", "Left", "Right", "Centre"] + +# Create a new BreakoutEncoderWheel with a pin on the Pico specified as an interrupt +i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS) +wheel = BreakoutEncoderWheel(i2c, interrupt=3) # 3 for BG_BASE, 22 for EXPLORER_BASE, or 19 for some RP2040 boards +# If wiring the breakout via the qw/st connector, use the below line instead +# wheel = BreakoutEncoderWheel(i2c) + +# Variables +last_pressed = [False] * NUM_BUTTONS +pressed = [False] * NUM_BUTTONS +position = 0 +hue = 0.0 + +# Set the first LED +wheel.clear() +wheel.set_hsv(position, hue, 1.0, 1.0) +wheel.show() + +# Clear any left over interrupt from previous code +wheel.clear_interrupt_flag() + +# Loop forever +while True: + + # Check if the interrupt has fired + if wheel.get_interrupt_flag(): + wheel.clear_interrupt_flag() + + # Read all of the encoder wheel's buttons + for b in range(NUM_BUTTONS): + pressed[b] = wheel.pressed(b) + if pressed[b] != last_pressed[b]: + print(BUTTON_NAMES[b], "Pressed" if pressed[b] else "Released") + last_pressed[b] = pressed[b] + + # The interrupt may have come from several sources, + # so check if it was a position change + new_position = wheel.step() + if new_position != position: + # Record the new position (from 0 to 23) + position = new_position + print("Position = ", position) + + # Record a colour hue from 0.0 to 1.0 + hue = wheel.revolutions() % 1.0 + + # Set the LED at the new position to the new hue + wheel.clear() + wheel.set_hsv(position, hue, 1.0, 1.0) + wheel.show() diff --git a/micropython/modules/breakout_encoder_wheel/README.md b/micropython/modules/breakout_encoder_wheel/README.md index 20440459..365fa566 100644 --- a/micropython/modules/breakout_encoder_wheel/README.md +++ b/micropython/modules/breakout_encoder_wheel/README.md @@ -262,6 +262,8 @@ Here is the complete list of functions available on the `BreakoutEncoderWheel` c ```python BreakoutEncoderWheel(ioe_address=0x13, led_address=0x77, interrupt=PIN_UNUSED) set_ioe_address(address) +get_interrupt_flag() +clear_interrupt_flag() pressed(button) count() delta() @@ -280,7 +282,7 @@ show() gpio_pin_mode(gpio) gpio_pin_mode(gpio, mode) gpio_pin_value(gpio) -gpio_pin_value(gpio, value) +gpio_pin_value(gpio, value, load=True, wait_for_load=False) gpio_pwm_load(wait_for_load=True) gpio_pwm_frequency(frequency, load=True, wait_for_load=True) ```