diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f729f45..f43e737 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -25,14 +25,26 @@ jobs:
strategy:
fail-fast: false
matrix:
- environment: [uno, esp32dev, pico]
+ board:
+ - fqbn: arduino:avr:uno
+ name: uno
+ - fqbn: esp32:esp32:esp32
+ name: esp32dev
+ - fqbn: rp2040:rp2040:rpipico
+ name: pico
+ platform: |
+ - name: rp2040:rp2040
+ source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
+ name: compile (${{ matrix.board.name }})
steps:
- uses: actions/checkout@v7
- - uses: actions/setup-python@v7
+ - uses: arduino/compile-sketches@v1
with:
- python-version: "3.14"
- - run: python -m pip install "platformio==6.1.18"
- - run: pio run -e ${{ matrix.environment }}
+ fqbn: ${{ matrix.board.fqbn }}
+ platforms: ${{ matrix.board.platform || '' }}
+ sketch-paths: |
+ - examples
+ enable-warnings-report: true
package:
runs-on: ubuntu-latest
@@ -41,8 +53,9 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: "3.14"
+ - run: python tools/validate_metadata.py
- run: python tools/build_release.py
- uses: actions/upload-artifact@v7
with:
name: ArduinoPatterns
- path: dist/ArduinoPatterns-*.zip
+ path: dist/ArduinoPatterns-*.zip
\ No newline at end of file
diff --git a/.zenodo.json b/.zenodo.json
index fd3d058..0a47b6e 100644
--- a/.zenodo.json
+++ b/.zenodo.json
@@ -1,21 +1,18 @@
{
- "creators": [{"name": "devkyato", "affiliation": "MATA Company"}],
+ "creators": [{"name": "@dev.mako (devkyato)", "affiliation": "MATA Company"}],
"contributors": [{"name": "Cursor Agent", "type": "Other"}],
"title": "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino",
- "description": "ArduinoPatterns is a small teaching library for coordinating LEDs and other digital outputs without delay(). It provides rollover-safe millis()-based patterns, output banks, and periodic outputs with no heap allocation or board-specific API. Usage: install the library in Arduino IDE or PlatformIO, include ArduinoPatterns.h, and update patterns from loop(). Applications include Arduino lessons, traffic-light demonstrations, ESP32 and RP2040 sketches, responsive user interfaces, and embedded output control.",
- "version": "1.0.1",
- "keywords": ["Arduino", "LED", "non-blocking", "millis", "library", "education", "ESP32", "RP2040"],
+ "description": "
Overview
ArduinoPatterns is a compact teaching and prototyping library for coordinating LEDs and other digital outputs without blocking the main loop.
Capabilities
- LedBank maps up to 32 pins to a bit mask.
- LedAnimator plays rollover-safe timed sequences with
millis(). - PeriodicOutput toggles independent outputs at separate rates.
- The implementation uses no heap allocation, interrupts, third-party dependencies, or board-specific APIs.
Installation
Download the release ZIP and use Arduino IDE Sketch > Include Library > Add .ZIP Library, or add https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2 to PlatformIO lib_deps.
Quick start
#include <ArduinoPatterns.h>\nconst uint8_t pins[] = {6, 7, 8};\nconst PatternStep steps[] = {{0b001, 5000}, {0b010, 2000}, {0b100, 5000}};\nLedBank lights(pins, 3);\nLedAnimator traffic(lights, steps, 3);\nvoid setup() { lights.begin(); traffic.start(millis()); }\nvoid loop() { traffic.update(millis()); }
Applications
- Traffic lights, scanners, counters, status indicators, and active-low modules.
- Lessons on bit masks, elapsed-time scheduling, and cooperative state machines.
- Responsive sketches that continue reading sensors, buttons, serial, or network input.
Compatibility, safety, and limitations
The API uses standard Arduino digital I/O and unsigned millisecond arithmetic. CI compile coverage is not hardware validation. GPIO current and voltage limits still apply; use resistors and appropriate drivers for loads. A bank is limited to 32 outputs, callers retain ownership of pin and step arrays, and a zero interval disables periodic toggling.
Documentation
Related software
Arduino Programs Guide is the companion course and introduces the progression that this library generalizes from Exercise B onward.
Citation
@dev.mako (devkyato). (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.2). Zenodo. https://doi.org/10.5281/zenodo.21853284
",
+ "version": "1.0.2",
+ "keywords": ["Arduino", "LED", "digital output", "non-blocking", "millis", "state machine", "library", "education", "ESP32", "RP2040"],
"license": "mit",
"upload_type": "software",
"access_right": "open",
"language": "eng",
"related_identifiers": [
{"identifier": "https://github.com/devkyato/Custom-Arduino-Libraries", "relation": "isSupplementTo", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/Datary", "relation": "references", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/OpenNet", "relation": "references", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/TapAuth", "relation": "references", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/Lowpack", "relation": "references", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/Relay", "relation": "references", "resource_type": "software"},
- {"identifier": "https://github.com/devkyato/Arduino-Programs-Guide", "relation": "references", "resource_type": "software"}
+ {"identifier": "10.5281/zenodo.21853284", "relation": "isVersionOf", "scheme": "doi"},
+ {"identifier": "https://github.com/devkyato/Arduino-Programs-Guide", "relation": "isSupplementTo", "resource_type": "software"},
+ {"identifier": "https://docs.arduino.cc/language-reference/en/functions/time/millis/", "relation": "references", "resource_type": "publication"}
]
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 741b03a..3ec2f21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,24 @@
All notable changes to ArduinoPatterns are documented here. The project follows
[Semantic Versioning](https://semver.org/).
+## [1.0.2] - 2026-08-09
+
+### Changed
+
+- Overhaul the README and Zenodo presentation with installation, real code,
+ applications, limitations, documentation, companion-course links, and an
+ example-to-concept gallery.
+- Expand Citation File Format metadata and align release metadata and attribution
+ on `@dev.mako (devkyato)`.
+- Package API, citation, release-note, and governance documents in the Arduino
+ IDE ZIP.
+- Compile every example across Uno, ESP32, and RP2040 CI targets and validate
+ release metadata without additional dependencies.
+
+### Fixed
+
+- Update the bug-report template's stale example version.
+
## [1.0.1] - 2026-08-09
### Changed
@@ -23,3 +41,4 @@ All notable changes to ArduinoPatterns are documented here. The project follows
[1.0.0]: https://github.com/devkyato/Custom-Arduino-Libraries/releases/tag/v1.0.0
[1.0.1]: https://github.com/devkyato/Custom-Arduino-Libraries/compare/v1.0.0...v1.0.1
+[1.0.2]: https://github.com/devkyato/Custom-Arduino-Libraries/compare/v1.0.1...v1.0.2
diff --git a/CITATION.cff b/CITATION.cff
index 5f97877..91ac2dc 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -2,18 +2,42 @@ cff-version: 1.2.0
message: "If you use this software, please cite it using the metadata from this file."
title: "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino"
authors:
- - family-names: devkyato
+ - name: "@dev.mako (devkyato)"
affiliation: "MATA Company"
-version: 1.0.1
+version: 1.0.2
+date-released: 2026-08-09
license: MIT
repository-code: "https://github.com/devkyato/Custom-Arduino-Libraries"
url: "https://github.com/devkyato/Custom-Arduino-Libraries"
-abstract: "Non-blocking LED and digital-output patterns for Arduino."
-keywords: [Arduino, LED, non-blocking, millis, library, education, ESP32, RP2040]
+doi: 10.5281/zenodo.21853284
+identifiers:
+ - type: doi
+ value: 10.5281/zenodo.21853284
+abstract: >-
+ ArduinoPatterns is a small Arduino library for reusable, non-blocking LED and
+ digital-output behavior. It provides bit-mask output banks, rollover-safe
+ millis()-driven animation, and independent periodic outputs without dynamic
+ allocation, interrupts, external dependencies, or board-specific APIs. Six
+ examples support teaching and prototyping across Arduino Uno, ESP32, and
+ RP2040 compile targets.
+keywords:
+ - Arduino
+ - LED
+ - digital output
+ - non-blocking
+ - millis
+ - state machine
+ - embedded systems education
+ - ESP32
+ - RP2040
preferred-citation:
type: software
title: "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino"
authors:
- - family-names: devkyato
+ - name: "@dev.mako (devkyato)"
affiliation: "MATA Company"
- version: 1.0.1
+ version: 1.0.2
+ date-released: 2026-08-09
+ repository-code: "https://github.com/devkyato/Custom-Arduino-Libraries"
+ doi: 10.5281/zenodo.21853284
+ license: MIT
diff --git a/README.md b/README.md
index 645c29a..2d9679f 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,37 @@
# ArduinoPatterns
[](https://github.com/devkyato/Custom-Arduino-Libraries/actions/workflows/ci.yml)
+[](https://doi.org/10.5281/zenodo.21853284)
[](LICENSE)
-ArduinoPatterns is a small teaching library for coordinating LEDs and other digital
-outputs without `delay()`. It turns the original laboratory sketches in this
-repository into reusable components that can run alongside buttons, sensors,
-displays, networking, and serial communication.
+ArduinoPatterns 1.0.2 is a focused Arduino library for coordinating LEDs and
+other digital outputs without blocking `loop()`. It packages common teaching
+patterns into reusable components that can run alongside buttons, sensors,
+serial communication, displays, or networking.
-## Features
+## Why ArduinoPatterns
- `LedBank`: treat up to 32 output pins as a bit mask.
- `LedAnimator`: play timed mask sequences using rollover-safe `millis()` logic.
- `PeriodicOutput`: blink independent outputs at different rates.
- No heap allocation, third-party dependencies, interrupts, or board-specific API.
-- Arduino IDE and PlatformIO examples for traffic lights, scanning, counting,
- alternating patterns, and independent blinkers.
+- Six compile-checked examples spanning traffic lights, scanners, counters,
+ alternating masks, and independent blinkers.
-## Install
+## Installation
Download the latest release ZIP and choose **Sketch > Include Library > Add .ZIP
Library** in Arduino IDE. In PlatformIO:
```ini
lib_deps =
- https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.1
+ https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2
```
-## Quick example
+To work from source, clone the repository into the Arduino `libraries` folder or
+add its root as a local PlatformIO library.
+
+## Quick start
```cpp
#include
@@ -53,37 +57,69 @@ void loop() {
}
```
-Open **File > Examples > ArduinoPatterns** for complete sketches. The examples map
-the original student work into reusable patterns; the original commits remain in
-the repository history.
+`update()` never waits for a phase to finish, so other application work remains
+responsive.
+
+## Examples gallery
+
+| Example | Demonstrates | Companion-course connection |
+| --- | --- | --- |
+| [TrafficLight](examples/TrafficLight/TrafficLight.ino) | timed phases and a three-output mask | elapsed-time scheduling foundation |
+| [ScanningLight](examples/ScanningLight/ScanningLight.ino) | forward/reverse animation | [Exercise B](https://github.com/devkyato/Arduino-Programs-Guide/blob/main/docs/lessons/exercise-b.md) and Exercise E |
+| [AlternatingPatterns](examples/AlternatingPatterns/AlternatingPatterns.ino) | reusable multi-step mask sequences | Exercise B pattern design |
+| [BinaryCounter](examples/BinaryCounter/BinaryCounter.ino) | direct `LedBank` masks and rollover-safe timing | arrays, bit masks, and output mapping |
+| [CountUpDown](examples/CountUpDown/CountUpDown.ino) | longer repeating animation tables | progression toward state-machine lessons |
+| [IndependentBlink](examples/IndependentBlink/IndependentBlink.ino) | two concurrent periodic outputs | cooperative scheduling used throughout Exercises C–F |
-See the [API reference](docs/API.md) for lifecycle, ownership, rollover, and
-active-low behavior.
+These examples are maintained adaptations of concepts present in the repository's
+earlier laboratory sketches; they are not claimed as unchanged originals. Git
+history preserves provenance. The companion
+[Arduino Programs Guide](https://github.com/devkyato/Arduino-Programs-Guide)
+provides a structured course progression and introduces the library as an
+optional abstraction from Exercise B onward.
+
+## Applications
-## Compatibility
+- Non-blocking traffic lights, scanners, counters, and status indicators.
+- Arduino timing, bit-mask, and cooperative state-machine instruction.
+- Responsive output patterns alongside sensors, serial, or network activity.
+- Active-low LED or relay modules through logical output inversion.
+
+## Compatibility, safety, and limitations
The public API uses only `pinMode`, `digitalWrite`, and unsigned millisecond
-arithmetic. CI compiles for Arduino AVR Uno, ESP32, and RP2040. Other Arduino
-architectures are expected to work but should be reported as verified only after an
-actual compile or hardware test.
+arithmetic. CI compiles every example for Arduino AVR Uno, ESP32, and RP2040;
+this is source compatibility evidence, not hardware validation. Other Arduino
+architectures may work but are unverified.
+
+- Respect each board's GPIO voltage and current ratings; use a series resistor
+ for every LED and a suitable driver for relays, motors, or other loads.
+- `LedBank` supports 1–32 outputs. The caller must keep pin and pattern arrays
+ alive for the lifetime of the objects that reference them.
+- `millis()` scheduling is rollover-safe, but updates only occur when `update()`
+ is called; long blocking work elsewhere still delays transitions.
+- A zero `PeriodicOutput` interval disables automatic toggling.
+
+## Documentation index
+
+- [API reference](docs/API.md) — ownership, lifecycle, active-low behavior, and
+ rollover semantics.
+- [Examples gallery](#examples-gallery) — working sketches mapped to concepts.
+- [Contributing guide](CONTRIBUTING.md) — development and test expectations.
+- [Security policy](SECURITY.md) — supported release and reporting process.
+- [Changelog](CHANGELOG.md) and [1.0.2 release notes](RELEASE_NOTES.md).
## Citation
-If you use this software in research or teaching, please cite the Zenodo archive / this repository:
+If you use this software in research or teaching, cite the archived release when
+available, or use:
```text
-devkyato. (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.1).
+@dev.mako (devkyato). (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.2). Zenodo. https://doi.org/10.5281/zenodo.21853284
```
See [CITATION.cff](CITATION.cff) for machine-readable metadata.
-## Applications
-
-- Non-blocking LED and traffic-light demonstrations.
-- Arduino timing and state-machine lessons.
-- Responsive ESP32 and RP2040 digital-output sketches.
-- Reusable output patterns alongside sensors and serial communication.
-
## Contributing
Student-friendly issues are labeled `good first issue`. Changes should remain
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
new file mode 100644
index 0000000..47dabbd
--- /dev/null
+++ b/RELEASE_NOTES.md
@@ -0,0 +1,31 @@
+# ArduinoPatterns 1.0.2
+
+Publication and documentation quality release for Zenodo archival presentation.
+
+## Highlights
+
+- Expand README installation, applications, limitations, documentation index, and citation guidance.
+- Add an examples gallery that maps each sketch to concepts and the companion Arduino Programs Guide.
+- Package `docs/API.md`, `CITATION.cff`, release notes, and governance files in the Arduino IDE ZIP.
+- Align metadata attribution on `@dev.mako (devkyato)` and validate release metadata before packaging.
+- Compile every example across Uno, ESP32, and RP2040 CI targets.
+
+## Install
+
+Arduino IDE: download `ArduinoPatterns-1.0.2.zip` and choose **Sketch > Include Library > Add .ZIP Library**.
+
+PlatformIO:
+
+```ini
+lib_deps =
+ https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2
+```
+
+## Citation
+
+Concept DOI: https://doi.org/10.5281/zenodo.21853284
+
+See `CITATION.cff` for machine-readable citation metadata.
+
+Published by @dev.mako (devkyato). Cursor Agent is acknowledged as a non-author contributor.
+
diff --git a/library.json b/library.json
index 5018208..262ef6e 100644
--- a/library.json
+++ b/library.json
@@ -1,13 +1,13 @@
{
"name": "ArduinoPatterns",
- "version": "1.0.1",
- "description": "Non-blocking LED and digital-output patterns for Arduino.",
- "keywords": ["arduino", "led", "non-blocking", "millis", "education"],
+ "version": "1.0.2",
+ "description": "Rollover-safe, non-blocking LED and digital-output patterns for Arduino without interrupts or heap allocation.",
+ "keywords": ["arduino", "led", "digital-output", "non-blocking", "millis", "state-machine", "education"],
"repository": {
"type": "git",
"url": "https://github.com/devkyato/Custom-Arduino-Libraries.git"
},
- "authors": [{"name": "devkyato", "maintainer": true}],
+ "authors": [{"name": "@dev.mako (devkyato)", "maintainer": true}],
"license": "MIT",
"frameworks": ["arduino"],
"platforms": "*",
diff --git a/library.properties b/library.properties
index e6c489b..0ebee26 100644
--- a/library.properties
+++ b/library.properties
@@ -1,9 +1,9 @@
name=ArduinoPatterns
-version=1.0.1
-author=devkyato and contributors
-maintainer=devkyato
+version=1.0.2
+author=@dev.mako (devkyato) and contributors
+maintainer=@dev.mako (devkyato)
sentence=Non-blocking LED and digital-output patterns for Arduino.
-paragraph=Coordinate timed LED sequences, bit-mask output banks, and independent periodic outputs without delay() or heap allocation.
+paragraph=Coordinate rollover-safe timed LED sequences, bit-mask output banks, and independent periodic outputs without delay(), interrupts, or heap allocation.
category=Signal Input/Output
url=https://github.com/devkyato/Custom-Arduino-Libraries
architectures=*
diff --git a/tools/build_release.py b/tools/build_release.py
index 6d201ab..3f4cb2e 100644
--- a/tools/build_release.py
+++ b/tools/build_release.py
@@ -11,8 +11,14 @@
INCLUDED = (
"src",
"examples",
+ "docs",
"README.md",
"CHANGELOG.md",
+ "RELEASE_NOTES.md",
+ "CITATION.cff",
+ "CONTRIBUTING.md",
+ "CODE_OF_CONDUCT.md",
+ "SECURITY.md",
"LICENSE",
"library.properties",
"library.json",
@@ -54,6 +60,8 @@ def main() -> None:
with zipfile.ZipFile(output) as archive:
required = {
+ "ArduinoPatterns/CITATION.cff",
+ "ArduinoPatterns/docs/API.md",
"ArduinoPatterns/library.properties",
"ArduinoPatterns/src/ArduinoPatterns.h",
}
diff --git a/tools/validate_metadata.py b/tools/validate_metadata.py
new file mode 100644
index 0000000..3559ee7
--- /dev/null
+++ b/tools/validate_metadata.py
@@ -0,0 +1,94 @@
+"""Validate release versions and Zenodo's restricted HTML description."""
+
+from __future__ import annotations
+
+import json
+import re
+from html.parser import HTMLParser
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parents[1]
+ALLOWED_TAGS = {"p", "h2", "ul", "li", "pre", "code", "a", "strong"}
+REQUIRED_SECTIONS = {
+ "Overview",
+ "Capabilities",
+ "Installation",
+ "Quick start",
+ "Applications",
+ "Compatibility, safety, and limitations",
+ "Documentation",
+ "Related software",
+ "Citation",
+}
+
+
+class DescriptionValidator(HTMLParser):
+ def __init__(self) -> None:
+ super().__init__(convert_charrefs=True)
+ self.errors: list[str] = []
+ self.headings: list[str] = []
+ self._in_h2 = False
+
+ def handle_starttag(
+ self, tag: str, attrs: list[tuple[str, str | None]]
+ ) -> None:
+ if tag not in ALLOWED_TAGS:
+ self.errors.append(f"disallowed HTML tag: {tag}")
+ if tag == "a":
+ if {name for name, _ in attrs} - {"href"}:
+ self.errors.append("links may only use the href attribute")
+ elif attrs:
+ self.errors.append(f"attributes are not allowed on {tag}")
+ self._in_h2 = tag == "h2"
+
+ def handle_endtag(self, tag: str) -> None:
+ if tag not in ALLOWED_TAGS:
+ self.errors.append(f"disallowed closing tag: {tag}")
+ if tag == "h2":
+ self._in_h2 = False
+
+ def handle_data(self, data: str) -> None:
+ if self._in_h2:
+ self.headings.append(data.strip())
+
+
+def property_version() -> str:
+ text = (ROOT / "library.properties").read_text(encoding="utf-8")
+ match = re.search(r"^version=(.+)$", text, re.MULTILINE)
+ if not match:
+ raise ValueError("library.properties has no version")
+ return match.group(1)
+
+
+def main() -> None:
+ version = property_version()
+ zenodo = json.loads((ROOT / ".zenodo.json").read_text(encoding="utf-8"))
+ library_json = json.loads((ROOT / "library.json").read_text(encoding="utf-8"))
+ cff = (ROOT / "CITATION.cff").read_text(encoding="utf-8")
+ readme = (ROOT / "README.md").read_text(encoding="utf-8")
+
+ assert version == "1.0.2"
+ assert zenodo["version"] == version
+ assert library_json["version"] == version
+ assert re.search(rf"^version: {re.escape(version)}$", cff, re.MULTILINE)
+ assert f"ArduinoPatterns {version}" in readme
+ assert zenodo["creators"] == [
+ {"name": "@dev.mako (devkyato)", "affiliation": "MATA Company"}
+ ]
+ assert {"name": "Cursor Agent", "type": "Other"} in zenodo["contributors"]
+
+ parser = DescriptionValidator()
+ parser.feed(zenodo["description"])
+ parser.close()
+ missing = REQUIRED_SECTIONS.difference(parser.headings)
+ if parser.errors or missing:
+ raise ValueError(
+ f"invalid Zenodo description: errors={parser.errors}, "
+ f"missing sections={sorted(missing)}"
+ )
+
+ print(f"metadata valid for ArduinoPatterns {version}")
+
+
+if __name__ == "__main__":
+ main()