From 41225090efb442ac9803a0a20f166d1536adafb6 Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Mon, 17 Oct 2022 16:15:02 +0100 Subject: [PATCH] Added some C specific examples for Plasma Stick --- common/pimoroni_common.hpp | 4 +- common/pimoroni_i2c.hpp | 6 ++ examples/CMakeLists.txt | 1 + examples/plasma_stick/CMakeLists.txt | 5 + .../plasma_stick_alternating_blinkies.cmake | 12 +++ .../plasma_stick_alternating_blinkies.cpp | 54 +++++++++++ .../plasma_stick/plasma_stick_encoder.cmake | 14 +++ .../plasma_stick/plasma_stick_encoder.cpp | 92 +++++++++++++++++++ examples/plasma_stick/plasma_stick_fire.cmake | 12 +++ examples/plasma_stick/plasma_stick_fire.cpp | 38 ++++++++ .../plasma_stick/plasma_stick_rainbows.cmake | 12 +++ .../plasma_stick/plasma_stick_rainbows.cpp | 45 +++++++++ .../plasma_stick_temperature_bme280.cmake | 14 +++ .../plasma_stick_temperature_bme280.cpp | 64 +++++++++++++ libraries/CMakeLists.txt | 1 + libraries/plasma_stick/CMakeLists.txt | 1 + libraries/plasma_stick/plasma_stick.cmake | 6 ++ libraries/plasma_stick/plasma_stick.hpp | 10 ++ 18 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 examples/plasma_stick/CMakeLists.txt create mode 100644 examples/plasma_stick/plasma_stick_alternating_blinkies.cmake create mode 100644 examples/plasma_stick/plasma_stick_alternating_blinkies.cpp create mode 100644 examples/plasma_stick/plasma_stick_encoder.cmake create mode 100644 examples/plasma_stick/plasma_stick_encoder.cpp create mode 100644 examples/plasma_stick/plasma_stick_fire.cmake create mode 100644 examples/plasma_stick/plasma_stick_fire.cpp create mode 100644 examples/plasma_stick/plasma_stick_rainbows.cmake create mode 100644 examples/plasma_stick/plasma_stick_rainbows.cpp create mode 100644 examples/plasma_stick/plasma_stick_temperature_bme280.cmake create mode 100644 examples/plasma_stick/plasma_stick_temperature_bme280.cpp create mode 100644 libraries/plasma_stick/CMakeLists.txt create mode 100644 libraries/plasma_stick/plasma_stick.cmake create mode 100644 libraries/plasma_stick/plasma_stick.hpp diff --git a/common/pimoroni_common.hpp b/common/pimoroni_common.hpp index 3ee36022..1f61712a 100644 --- a/common/pimoroni_common.hpp +++ b/common/pimoroni_common.hpp @@ -50,9 +50,11 @@ namespace pimoroni { enum BOARD { BREAKOUT_GARDEN, PICO_EXPLORER, + PLASMA_STICK, PLASMA_2040, INTERSTATE_75, - SERVO_2040 + SERVO_2040, + MOTOR_2040 }; enum Rotation { diff --git a/common/pimoroni_i2c.hpp b/common/pimoroni_i2c.hpp index ea43be40..3c0ceb19 100644 --- a/common/pimoroni_i2c.hpp +++ b/common/pimoroni_i2c.hpp @@ -29,9 +29,15 @@ namespace pimoroni { scl = I2C_DEFAULT_SCL; interrupt = I2C_DEFAULT_INT; break; + case PLASMA_STICK: + sda = I2C_BG_SDA; + scl = I2C_BG_SCL; + interrupt = PIN_UNUSED; + break; case PLASMA_2040: case INTERSTATE_75: case SERVO_2040: + case MOTOR_2040: sda = I2C_HEADER_SDA; scl = I2C_HEADER_SCL; interrupt = I2C_HEADER_INT; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c7de23d1..01a422ba 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -47,6 +47,7 @@ add_subdirectory(inky_pack) add_subdirectory(inky_frame) add_subdirectory(automation2040w) +add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) add_subdirectory(tufty2040) diff --git a/examples/plasma_stick/CMakeLists.txt b/examples/plasma_stick/CMakeLists.txt new file mode 100644 index 00000000..32b43d0e --- /dev/null +++ b/examples/plasma_stick/CMakeLists.txt @@ -0,0 +1,5 @@ +include(plasma_stick_alternating_blinkies.cmake) +include(plasma_stick_encoder.cmake) +include(plasma_stick_fire.cmake) +include(plasma_stick_rainbows.cmake) +include(plasma_stick_temperature_bme280.cmake) \ No newline at end of file diff --git a/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake b/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake new file mode 100644 index 00000000..e84779c9 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_alternating_blinkies.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_alternating_blinkies) +add_executable(${OUTPUT_NAME} plasma_stick_alternating_blinkies.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp b/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp new file mode 100644 index 00000000..f239cb14 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_alternating_blinkies.cpp @@ -0,0 +1,54 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +This super simple example sets up two alternating colours, great for festive lights! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Pick two hues from the colour wheel (from 0-360°, try https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ ) +constexpr float HUE_1 = 40.0f; +constexpr float HUE_2 = 285.0f; + +// Set up brightness (between 0 and 1) +constexpr float BRIGHTNESS = 0.5f; + +// Set up speed (wait time between colour changes, in seconds) +constexpr float SPEED = 1.0f; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(); + + while(true) { + + for(auto i = 0u; i < NUM_LEDS; i++) { + // the if statements below use a modulo operation to identify the even and odd numbered LEDs + if((i % 2) == 0) + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS); + else + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS); + } + sleep_ms(SPEED * 1000.0f); + + for(auto i = 0u; i < NUM_LEDS; i++) { + if((i % 2) == 0) + led_strip.set_hsv(i, HUE_2 / 360, 1.0, BRIGHTNESS); + else + led_strip.set_hsv(i, HUE_1 / 360, 1.0, BRIGHTNESS); + } + sleep_ms(SPEED * 1000.0f); + } +} diff --git a/examples/plasma_stick/plasma_stick_encoder.cmake b/examples/plasma_stick/plasma_stick_encoder.cmake new file mode 100644 index 00000000..ba4ed048 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_encoder.cmake @@ -0,0 +1,14 @@ +set(OUTPUT_NAME plasma_stick_encoder) +add_executable(${OUTPUT_NAME} plasma_stick_encoder.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + breakout_encoder + pimoroni_i2c + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_encoder.cpp b/examples/plasma_stick/plasma_stick_encoder.cpp new file mode 100644 index 00000000..eebdcd3d --- /dev/null +++ b/examples/plasma_stick/plasma_stick_encoder.cpp @@ -0,0 +1,92 @@ +#include +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" +#include "breakout_encoder.hpp" + +/* +Change the colour of your LEDs easily by hooking up an RGB Encoder Breakout! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Make this number bigger for more precise colour adjustments +const uint STEPS_PER_REV = 24; + +// WS28X-style LEDs with a single signal line. AKA NeoPixel +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +I2C i2c(BOARD::PLASMA_STICK); +BreakoutEncoder enc(&i2c); + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +void count_changed(int16_t count) { + printf("Count: %d\n", count); + float h = (count % STEPS_PER_REV) / (float)STEPS_PER_REV; + uint8_t r = 0, g = 0, b = 0; + from_hsv(h, 1.0f, 1.0f, r, g, b); + + // set the encoder LED colour + enc.set_led(r, g, b); + + for(auto i = 0u; i < NUM_LEDS; i++) { + led_strip.set_rgb(i, r, g, b); + } +} + +int main() { + stdio_init_all(); + + led_strip.start(); + + if(enc.init()) { + printf("Encoder found...\n"); + + enc.set_brightness(1.0f); + //enc.set_direction(BreakoutEncoder::DIRECTION_CCW); // Uncomment this to flip the direction + + count_changed(0); + enc.clear_interrupt_flag(); + + while(true) { + if(enc.get_interrupt_flag()) { + int16_t count = enc.read(); + enc.clear_interrupt_flag(); + + while(count < 0) { + count += STEPS_PER_REV; + } + + count_changed(count); + } + } + } + else { + printf("Encoder not found :'(\n"); + } + + return 0; +} diff --git a/examples/plasma_stick/plasma_stick_fire.cmake b/examples/plasma_stick/plasma_stick_fire.cmake new file mode 100644 index 00000000..90c70e67 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_fire.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_fire) +add_executable(${OUTPUT_NAME} plasma_stick_fire.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_fire.cpp b/examples/plasma_stick/plasma_stick_fire.cpp new file mode 100644 index 00000000..d965e9ab --- /dev/null +++ b/examples/plasma_stick/plasma_stick_fire.cpp @@ -0,0 +1,38 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +A basic fire effect. +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +// Maps a value from one range to another +float map(float x, float in_min, float in_max, float out_min, float out_max) { + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(); + + while(true) { + // fire effect! Random red/orange hue, full saturation, random brightness + for(auto i = 0u; i < NUM_LEDS; ++i) { + float hue = map((float)rand(), 0.0f, (float)RAND_MAX, 0.0, 50.0f / 360.0f); + float brightness = map((float)rand(), 0.0f, (float)RAND_MAX, 0.0, 1.0f); + led_strip.set_hsv(i, hue, 1.0, brightness); + } + sleep_ms(100); + } +} diff --git a/examples/plasma_stick/plasma_stick_rainbows.cmake b/examples/plasma_stick/plasma_stick_rainbows.cmake new file mode 100644 index 00000000..e463b924 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_rainbows.cmake @@ -0,0 +1,12 @@ +set(OUTPUT_NAME plasma_stick_rainbows) +add_executable(${OUTPUT_NAME} plasma_stick_rainbows.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_rainbows.cpp b/examples/plasma_stick/plasma_stick_rainbows.cpp new file mode 100644 index 00000000..41abcf62 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_rainbows.cpp @@ -0,0 +1,45 @@ +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" + +/* +Make some rainbows! +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// The SPEED that the LEDs cycle at (1 - 255) +const uint SPEED = 20; + +// How many times the LEDs will be updated per second +const uint UPDATES = 60; + +// WS2812 / NeoPixel™ LEDs +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + + +int main() { + stdio_init_all(); + + // Start updating the LED strip + led_strip.start(UPDATES); + + float offset = 0.0f; + + // Make rainbows + while(true) { + + offset += float(SPEED) / 2000.0f; + + for(auto i = 0u; i < NUM_LEDS; ++i) { + float hue = float(i) / NUM_LEDS; + led_strip.set_hsv(i, hue + offset, 1.0f, 1.0f); + } + + sleep_ms(1000 / UPDATES); + } +} diff --git a/examples/plasma_stick/plasma_stick_temperature_bme280.cmake b/examples/plasma_stick/plasma_stick_temperature_bme280.cmake new file mode 100644 index 00000000..8bec6c2e --- /dev/null +++ b/examples/plasma_stick/plasma_stick_temperature_bme280.cmake @@ -0,0 +1,14 @@ +set(OUTPUT_NAME plasma_stick_temperature_bme280) +add_executable(${OUTPUT_NAME} plasma_stick_temperature_bme280.cpp) + +target_link_libraries(${OUTPUT_NAME} + pico_stdlib + plasma_stick + bme280 + pimoroni_i2c + ) + +# enable usb output +pico_enable_stdio_usb(${OUTPUT_NAME} 1) + +pico_add_extra_outputs(${OUTPUT_NAME}) diff --git a/examples/plasma_stick/plasma_stick_temperature_bme280.cpp b/examples/plasma_stick/plasma_stick_temperature_bme280.cpp new file mode 100644 index 00000000..a6316800 --- /dev/null +++ b/examples/plasma_stick/plasma_stick_temperature_bme280.cpp @@ -0,0 +1,64 @@ +#include +#include "pico/stdlib.h" +#include "plasma_stick.hpp" +#include "common/pimoroni_common.hpp" +#include "bme280.hpp" + +/* +Reads the temperature from a BME280 breakout... +...and changes the LED strip an appropriate colour. +https://shop.pimoroni.com/products/bme280-breakout +*/ + +using namespace pimoroni; +using namespace plasma; + +// Set how many LEDs you have +const uint NUM_LEDS = 50; + +// Set up brightness (between 0 and 1) +constexpr float BRIGHTNESS = 1.0f; + +// The range of readings that we want to map to colours +const uint MIN = 10; +const uint MAX = 30; + +// Pick what bits of the colour wheel to use (from 0-360°) +// https://www.cssscript.com/demo/hsv-hsl-color-wheel-picker-reinvented/ +const uint HUE_START = 230; // blue +const uint HUE_END = 359; // red + +// WS28X-style LEDs with a single signal line. AKA NeoPixel +WS2812 led_strip(NUM_LEDS, pio0, 0, plasma_stick::DAT); + +I2C i2c(BOARD::PLASMA_STICK); +BME280 bme(&i2c); + + +int main() { + stdio_init_all(); + + led_strip.start(); + + if(bme.init()) { + printf("BME280 found...\n"); + + while(true) { + BME280::bme280_reading result = bme.read_forced(); + printf("%s %0.2lf deg C, %0.2lf hPa, %0.2lf%%\n", result.status == BME280_OK ? "OK" : "ER", result.temperature, result.pressure, result.humidity); + + // calculates a colour + float hue = HUE_START + ((float)(result.temperature - MIN) * (float)(HUE_END - HUE_START) / (float)(MAX - MIN)); + + // set the leds + for(auto i = 0u; i < NUM_LEDS; i++) { + led_strip.set_hsv(i, hue / 360.0f, 1.0, BRIGHTNESS); + } + } + } + else { + printf("BME280 not found :'(\n"); + } + + return 0; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index b7fa264f..8c192f00 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -26,6 +26,7 @@ add_subdirectory(pico_motor_shim) add_subdirectory(pico_rgb_keypad) add_subdirectory(pico_wireless) add_subdirectory(automation2040w) +add_subdirectory(plasma_stick) add_subdirectory(plasma2040) add_subdirectory(badger2040) add_subdirectory(tufty2040) diff --git a/libraries/plasma_stick/CMakeLists.txt b/libraries/plasma_stick/CMakeLists.txt new file mode 100644 index 00000000..18b91ca9 --- /dev/null +++ b/libraries/plasma_stick/CMakeLists.txt @@ -0,0 +1 @@ +include(plasma_stick.cmake) \ No newline at end of file diff --git a/libraries/plasma_stick/plasma_stick.cmake b/libraries/plasma_stick/plasma_stick.cmake new file mode 100644 index 00000000..dbf1900f --- /dev/null +++ b/libraries/plasma_stick/plasma_stick.cmake @@ -0,0 +1,6 @@ +add_library(plasma_stick INTERFACE) + +target_include_directories(plasma_stick INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(plasma_stick INTERFACE pico_stdlib plasma) \ No newline at end of file diff --git a/libraries/plasma_stick/plasma_stick.hpp b/libraries/plasma_stick/plasma_stick.hpp new file mode 100644 index 00000000..edf5b8e8 --- /dev/null +++ b/libraries/plasma_stick/plasma_stick.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "pico/stdlib.h" + +#include "ws2812.hpp" + +namespace plasma { + namespace plasma_stick { + const uint DAT = 15; // Used for WS2812 + } +} \ No newline at end of file