SBK_BarDrive Library 2.1.0
LED bar meter control and queued animations for Arduino
Loading...
Searching...
No Matches
animationQueueDemo.ino
Go to the documentation of this file.
1/**
2 * @file animationQueueDemo.ino
3 * @brief Demonstrates queued animations, live logic inversion, and wait().
4 *
5 * This example demonstrates:
6 * - Capturing four animations in a fixed-storage queue
7 * - Inspecting the active queue index
8 * - Modifying a running animation without losing its block positions
9 * - Stopping block emission and allowing active blocks to flow out
10 * - Adding a non-blocking pause with wait()
11 *
12 * Requirements:
13 * - Supported driver with compatible library (SBK_MAX72xx or SBK_HT16K33)
14 * - Bar meter display or LED array wired to the selected driver
15 *
16 * @author
17 * Samuel Barabé (Smart Builds & Kits)
18 *
19 * @version 2.1.0
20 * @license MIT
21 */
22
23#include <Arduino.h>
24
25// -----------------------------------------------------------------------------
26// SBK BarDrive Configuration Flags
27// -----------------------------------------------------------------------------
28#define SBK_BARDRIVE_WITH_ANIM // Enable preset animations and queue controls.
29
30// This example uses four entries. The library default is already four.
31// If you change the global queue capacity, keep it at four or greater here.
32// #define SBK_BARDRIVE_QUEUE_CAPACITY 4
33
34// -----------------------------------------------------------------------------
35// SELECT YOUR DRIVER SETUP
36// Enable one driver configuration and comment out the other two.
37// -----------------------------------------------------------------------------
38
39/* === [A] MAX7219/MAX7221 via SOFTWARE SPI (any 3 digital pins) === */
40#define DIN_PIN A4 // Software SPI Data In
41#define CLK_PIN A5 // Software SPI Clock
42#define CS_PIN A3 // Chip Select / LOAD
43#include <SBK_MAX72xxSoft.h>
44SBK_MAX72xxSoft driver(DIN_PIN, CLK_PIN, CS_PIN, 1);
45#include <SBK_BarDrive.h>
46SBK_BarDrive<SBK_MAX72xxSoft> bar(
47 &driver, 0, MatrixPreset::SBK_BarMeter_SK28);
48
49/* === [B] MAX7219/MAX7221 via HARDWARE SPI (dedicated MCU SPI pins) === */
50// #define CS_PIN A3 // Chip Select / LOAD
51// #include <SBK_MAX72xxHard.h>
52// SBK_MAX72xxHard driver(CS_PIN, 1);
53// #include <SBK_BarDrive.h>
54// SBK_BarDrive<SBK_MAX72xxHard> bar(
55// &driver, 0, MatrixPreset::SBK_BarMeter_SK28);
56
57/* === [C] HT16K33 via I2C === */
58// #include <SBK_HT16K33.h>
59// const uint8_t NUM_DEV = 1;
60// const uint8_t DEV0_IDX = 0;
61// const uint8_t DEV0_ADD = 0x70;
62// const uint8_t DEV0_NUM_ROWS = 8; // 20-SOP = 8, 24-SOP = 12, 28-SOP = 16
63// SBK_HT16K33 driver(NUM_DEV);
64// #include <SBK_BarDrive.h>
65// SBK_BarDrive<SBK_HT16K33> bar(
66// &driver, 0, MatrixPreset::SBK_BarMeter_SK28);
67
68/*
69 * The default setup uses the SBK BarMeter SK28 28-segment preset.
70 * Change the MatrixPreset or constructor to match your display and wiring.
71 */
72
73uint8_t previousQueueIndex = 0xFF; // Same value as NO_QUEUE_INDEX.
74uint32_t queueStepStartedAt = 0;
75bool blockLogicInverted = false;
76
77void startAnimationQueue()
78{
79 /*
80 * enqueue() captures the animation and its modifiers in the next queue slot.
81 * The captured animations do not start until startQueue() is called.
82 *
83 * Queue index 0: fill the display.
84 * Queue index 1: empty the display.
85 * Queue index 2: emit colliding blocks indefinitely (numBlocks defaults to 0).
86 * Queue index 3: preserve the empty display for 1000 ms without blocking.
87 *
88 * wait() is different from Arduino delay(): loop() and animations.update()
89 * continue to run, so the rest of the application remains responsive.
90 */
91 bar.animations().stop()
92 .fillUpIntv(35).noLoop().enqueue()
93 .emptyDownIntv(35).noLoop().enqueue()
94 .collidingBlocks(45, 4, 2).enqueue()
95 .wait(1000).enqueue()
96 .startQueue();
97}
98
99void setup()
100{
101#ifdef SBK_HT16K33_IS_DEFINED
102 // HT16K33 setup is required only when configuration [C] is enabled.
103 driver.setAddress(DEV0_IDX, DEV0_ADD);
104 driver.setDriverRows(DEV0_IDX, DEV0_NUM_ROWS);
105#endif
106
107 driver.begin();
108 driver.setBrightness(0, 10);
109 bar.setDirection(BarDirection::FORWARD);
110 startAnimationQueue();
111}
112
113void loop()
114{
115 // update() advances timing and queue transitions; show() sends pixels to the driver.
116 bar.animations().update();
117 bar.show();
118
119 /*
120 * Detect entry into a new queue slot so each timed action is measured from
121 * the start of that animation, rather than from the start of the sketch.
122 */
123 const uint8_t currentQueueIndex = bar.animations().currentQueueIndex();
124 if (currentQueueIndex != previousQueueIndex)
125 {
126 previousQueueIndex = currentQueueIndex;
127 queueStepStartedAt = millis();
128 blockLogicInverted = false;
129 }
130
131 const uint32_t queueStepElapsed = millis() - queueStepStartedAt;
132
133 /*
134 * invertLogic() is intentionally called outside the queue. Loading another
135 * queued animation would reinitialize the animation and lose all current
136 * block positions. Modifying the active index-2 animation in place keeps
137 * the same blocks moving while changing how they are rendered.
138 *
139 * The boolean prevents invertLogic() from being called on every loop pass.
140 */
141 if (bar.animations().isQueueIndexPlaying(2) &&
142 queueStepElapsed >= 3000 &&
143 !blockLogicInverted)
144 {
145 bar.animations().invertLogic();
146 blockLogicInverted = true;
147 }
148
149 /*
150 * After three more seconds, stop creating blocks. Active blocks continue
151 * moving until they leave the display. The animation then completes
152 * naturally and the queue advances to wait(1000).
153 */
154 if (bar.animations().isQueueIndexPlaying(2) &&
155 queueStepElapsed >= 6000 &&
156 bar.animations().isBlockEmissionEnabled())
157 {
158 bar.animations().stopBlockEmission();
159 }
160
161 // After the final wait entry completes, rebuild and replay the demonstration.
162 if (!bar.animations().isRunning())
163 startAnimationQueue();
164}