Compare commits

...

No commits in common. "main" and "folder-images" have entirely different histories.

8854 changed files with 1740 additions and 7693485 deletions

View file

@ -1,46 +0,0 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View file

@ -1,26 +0,0 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

View file

@ -1,134 +0,0 @@
name: Arduino Library CI
on:
workflow_dispatch:
pull_request:
push:
jobs:
check-if-needed:
runs-on: ubuntu-latest
outputs:
answer: ${{ steps.is-needed.outputs.answer }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Check if run by adabot
id: check-cron
run: |
iscron=false
[[ "${{ github.event_name }}" == "push" && "${{ github.actor }}" == "adafruit-adabot" ]] && iscron=true
echo "status=$iscron" >> "$GITHUB_OUTPUT"
- name: Check if dispatched
id: check-dispatch
run: |
isdispatch=false
[[ "${{ github.event_name }}" == "workflow_dispatch" ]] && isdispatch=true
echo "status=$isdispatch" >> "$GITHUB_OUTPUT"
- name: Check for Arduino file updates
id: check-updated
if: ${{ steps.check-cron.outputs.status }} == false && ${{ steps.check-dispatch.outputs.status }} == false
run: |
changedfiles=$(git diff --name-only -r HEAD^1 HEAD)
ischanged=false
for changedfile in ${changedfiles[*]}; do
echo $changedfile
if [[ $changedfile == *.c ]] ||
[[ $changedfile == *.cpp ]] ||
[[ $changedfile == *.h ]] ||
[[ $changedfile == *.hpp ]] ||
[[ $changedfile == *.ino ]] ||
[[ $changedfile == *.yml ]]; then
ischanged=true
break
fi
done
echo "status=$ischanged" >> "$GITHUB_OUTPUT"
- name: Output Arduino needed
id: is-needed
run: |
isneeded=false
if [[ ${{ steps.check-cron.outputs.status }} == true ]] ||
[[ ${{ steps.check-dispatch.outputs.status }} == true ]] ||
[[ ${{ steps.check-updated.outputs.status }} == true ]]; then
isneeded=true
fi
echo "answer=$isneeded" >> "$GITHUB_OUTPUT"
arduino:
strategy:
fail-fast: false
matrix:
arduino-platform: ["cpb", "cpc", "cpx_ada", "esp32", "esp8266", "feather32u4", "feather_esp32c6", "feather_m0_express", "feather_m4_express", "feather_rp2040", "feather_rp2040_adalogger", "feather_rp2350", "flora", "fruit_jam_tinyusb", "funhouse", "gemma", "gemma_m0", "hallowing_m0", "hallowing_m4_tinyusb", "ledglasses_nrf52840", "magtag", "metro_m0", "metro_m0_tinyusb", "metro_m4", "metro_m4_tinyusb", "monster_m4sk", "monster_m4sk_tinyusb", "metro_rp2350", "neokeytrinkey_m0", "neotrellis_m4", "nrf52832", "nrf52840", "pixeltrinkey_m0", "protrinket_5v", "proxlighttrinkey_m0", "pybadge", "pycamera_s3", "pygamer", "pyportal", "qualia_s3_rgb666", "qt2040_trinkey", "qtpy_m0", "qtpy_esp32s2", "rotarytrinkey_m0", "sht4xtrinkey_m0", "slidetrinkey_m0", "trinket_5v", "trinket_m0", "uno"]
runs-on: ubuntu-latest
if: needs.check-if-needed.outputs.answer == 'true'
needs: check-if-needed
steps:
- uses: actions/setup-python@v5
with:
python-version: "3.x"
# Checkout the learn repo itself
- uses: actions/checkout@v4
# Checkout the CI scripts
- uses: actions/checkout@v4
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
# manually install some libraries
- name: extra libraries
run: |
git clone --quiet https://github.com/adafruit/Cryptosuite.git /home/runner/Arduino/libraries/Cryptosuite
git clone --quiet https://github.com/adafruit/WiFiNINA.git /home/runner/Arduino/libraries/WiFiNINA
git clone --quiet https://github.com/adafruit/Adafruit_LSM303.git /home/runner/Arduino/libraries/Adafruit_LSM303
git clone --quiet https://github.com/moderndevice/CapSense.git /home/runner/Arduino/libraries/CapSense
git clone --quiet https://github.com/PaintYourDragon/ffft.git /home/runner/Arduino/libraries/ffft
git clone --quiet https://github.com/adafruit/RadioHead.git /home/runner/Arduino/libraries/RadioHead
git clone --quiet https://github.com/me-no-dev/ESPAsyncTCP /home/runner/Arduino/libraries/ESPAsyncTCP
git clone --quiet https://github.com/adafruit/Talkie /home/runner/Arduino/libraries/Talkie
git clone --quiet https://github.com/Infineon/arduino-optiga-trust-m /home/runner/Arduino/libraries/arduinoOptigaTrustM
git clone --quiet https://github.com/adafruit/HID /home/runner/Arduino/libraries/HID_Project
rm -rf /home/runner/Arduino/libraries/ArduinoHttpClient
git clone --quiet https://github.com/arduino-libraries/ArduinoHttpClient.git /home/runner/Arduino/libraries/ArduinoHttpClient
git clone --quiet https://github.com/pschatzmann/ESP32-A2DP /home/runner/Arduino/libraries/ESP32-A2DP
git clone --quiet https://github.com/pschatzmann/arduino-audio-tools /home/runner/Arduino/libraries/arduino-audio-tools
- name: test platforms
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.repository.name }}.${{ github.sha }}
path: |
build/*.hex
build/*.bin
build/*.uf2
- name: Zip release files
if: startsWith(github.ref, 'refs/tags/')
run: |
if [ -d build ]; then
(
echo "Built from Adafruit Learning System Guides `git describe --tags` for ${{ matrix.arduino-platform }}"
echo "Source code: https://github.com/adafruit/"
echo "Adafruit Learning System: https://learn.adafruit.com/"
) > build/README.txt
cd build && zip -9 -o ${{ matrix.arduino-platform }}.zip *.hex *.bin *.uf2 *.txt
fi
- name: Create release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
files: build/${{ matrix.arduino-platform }}.zip
fail_on_unmatched_files: false
body: "Select the zip file corresponding to your board from the list below."

View file

@ -1,35 +0,0 @@
name: SPDX and Pylint
on: [pull_request, push, repository_dispatch]
jobs:
spdx:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Checkout Current Repo
uses: actions/checkout@v4
- name: check SPDX licensing
run: python ./SPDX.py
pylint:
runs-on: ubuntu-latest
steps:
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Versions
run: |
python3 --version
- name: Pip install pylint
run: |
pip install --force-reinstall pylint==2.7.1
- name: Checkout Current Repo
uses: actions/checkout@v4
- name: lint
run: ./pylint_check.sh

View file

@ -1,52 +0,0 @@
name: Generate folder images
on:
schedule:
- cron: '0 10 * * *'
workflow_dispatch:
push:
branches: [main]
concurrency:
group: folder-images-concurrency # https://github.com/adafruit/Adafruit_Learning_System_Guides/issues/2327
cancel-in-progress: true
jobs:
update-images:
if: github.repository_owner == 'adafruit'
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v4
- name: Set up Python 3.x
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Checkout screenshot maker
run: git clone --depth=1 https://github.com/circuitpython/CircuitPython_Library_Screenshot_Maker
- name: Install dependencies
run: pip install -r CircuitPython_Library_Screenshot_Maker/requirements.txt
- name: Generate images
run: |
cd CircuitPython_Library_Screenshot_Maker
env LEARN_GUIDE_REPO=../ python3 ./create_requirement_images.py
- name: Commit updates
run: |
cd CircuitPython_Library_Screenshot_Maker/generated_images
git config --global user.name "${GITHUB_ACTOR} (github actions cron)"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git config --global init.defaultBranch main
git init
for i in *.png; do echo "<a href=\"$i\">$i</a><br>"; done > index.html
git add *.png index.html
git remote add origin https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
if git commit -m"update images"; then git push -f origin HEAD:folder-images; fi

8
.gitignore vendored
View file

@ -1,8 +0,0 @@
*~
Hue_Controller/secrets.h
.idea
*.DS_Store
CircuitPython_Logger/secrets\.py
.python-version
__pycache__
*.swp

View file

@ -1 +0,0 @@
Anne Barela <mydigitalhome@gmail.com>

433
.pylintrc
View file

@ -1,433 +0,0 @@
[MASTER]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint.
# jobs=1
jobs=2
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Specify a configuration file.
#rcfile=
# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=too-many-instance-attributes,len-as-condition,too-few-public-methods,anomalous-backslash-in-string,no-else-return,simplifiable-if-statement,too-many-arguments,duplicate-code,no-name-in-module,no-member,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,missing-docstring,invalid-name,bad-whitespace,consider-using-enumerate,unexpected-keyword-arg,consider-using-f-string,unspecified-encoding
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=
[REPORTS]
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
msg-template='{path}:{line}: {msg} ({symbol})'
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
[LOGGING]
# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging
[SPELLING]
# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
# notes=FIXME,XXX,TODO
notes=FIXME,XXX
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,_cb
# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,future.builtins
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
# expected-line-ending-format=
expected-line-ending-format=LF
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module
max-module-lines=1000
# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[BASIC]
# Naming hint for argument names
argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct argument names
argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for attribute names
attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct attribute names
attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Naming hint for class attribute names
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Naming hint for class names
# class-name-hint=[A-Z_][a-zA-Z0-9]+$
class-name-hint=[A-Z_][a-zA-Z0-9_]+$
# Regular expression matching correct class names
# class-rgx=[A-Z_][a-zA-Z0-9]+$
class-rgx=[A-Z_][a-zA-Z0-9_]+$
# Naming hint for constant names
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
# Naming hint for function names
function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct function names
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Good variable names which should always be accepted, separated by a comma
# good-names=i,j,k,ex,Run,_
good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
# Naming hint for inline iteration names
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for method names
method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct method names
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
property-classes=abc.abstractproperty
# Naming hint for variable names
variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct variable names
variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
[IMPORTS]
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
[CLASSES]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Maximum number of attributes for a class (see R0902).
# max-attributes=7
max-attributes=11
# Maximum number of boolean expressions in a if statement
max-bool-expr=5
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of statements in function / method body
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=1
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

View file

@ -1,622 +0,0 @@
// SPDX-FileCopyrightText: 2023 Phil B. for Adafruit Industries
// SPDX-License-Identifier: MIT
// Basic full-color PicoDVI test. Provides a 16-bit color video framebuffer to
// which Adafruit_GFX calls can be made. It's based on the EYESPI_Test.ino sketch.
#include <PicoDVI.h> // Core display & graphics library
#include <Fonts/FreeSansBold18pt7b.h> // A custom font
// Here's how a 320x240 16-bit color framebuffer is declared. Double-buffering
// is not an option in 16-bit color mode, just not enough RAM; all drawing
// operations are shown as they occur. Second argument is a hardware
// configuration -- examples are written for Adafruit Feather RP2040 DVI, but
// that's easily switched out for boards like the Pimoroni Pico DV (use
// 'pimoroni_demo_hdmi_cfg') or Pico DVI Sock ('pico_sock_cfg').
DVIGFX16 display(DVI_RES_320x240p60, adafruit_dvibell_cfg);
// A 400x240 mode is possible but pushes overclocking even higher than
// 320x240 mode. SOME BOARDS MIGHT SIMPLY NOT BE COMPATIBLE WITH THIS.
// May require selecting QSPI div4 clock (Tools menu) to slow down flash
// accesses, may require further over-volting the CPU to 1.25 or 1.3 V.
//DVIGFX16 display(DVI_RES_400x240p60, adafruit_feather_dvi_cfg);
void setup() { // Runs once on startup
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
}
#define PAUSE 2000 // Delay (milliseconds) between examples
uint8_t rotate = 0; // Current screen orientation (0-3)
#define CORNER_RADIUS 0
void loop() {
// Each of these functions demonstrates a different Adafruit_GFX concept:
show_shapes();
show_charts();
show_basic_text();
show_char_map();
show_custom_text();
show_bitmap();
show_canvas();
if (++rotate > 3) rotate = 0; // Cycle through screen rotations 0-3
display.setRotation(rotate); // Takes effect on next drawing command
}
// BASIC SHAPES EXAMPLE ----------------------------------------------------
void show_shapes() {
// Draw outlined and filled shapes. This demonstrates:
// - Enclosed shapes supported by GFX (points & lines are shown later).
// - Adapting to different-sized displays, and to rounded corners.
const int16_t cx = display.width() / 2; // Center of screen =
const int16_t cy = display.height() / 2; // half of width, height
int16_t minor = min(cx, cy); // Lesser of half width or height
// Shapes will be drawn in a square region centered on the screen. But one
// particular screen -- rounded 240x280 ST7789 -- has VERY rounded corners
// that would clip a couple of shapes if drawn full size. If using that
// screen type, reduce area by a few pixels to avoid drawing in corners.
if (CORNER_RADIUS > 40) minor -= 4;
const uint8_t pad = 5; // Space between shapes is 2X this
const int16_t size = minor - pad; // Shapes are this width & height
const int16_t half = size / 2; // 1/2 of shape size
display.fillScreen(0); // Start by clearing the screen; color 0 = black
// Draw outline version of basic shapes: rectangle, triangle, circle and
// rounded rectangle in different colors. Rather than hardcoded numbers
// for position and size, some arithmetic helps adapt to screen dimensions.
display.drawRect(cx - minor, cy - minor, size, size, 0xF800);
display.drawTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
cx + minor - 1, cy - pad, 0x07E0);
display.drawCircle(cx - pad - half, cy + pad + half, half, 0x001F);
display.drawRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
delay(PAUSE);
// Draw same shapes, same positions, but filled this time.
display.fillRect(cx - minor, cy - minor, size, size, 0xF800);
display.fillTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
cx + minor - 1, cy - pad, 0x07E0);
display.fillCircle(cx - pad - half, cy + pad + half, half, 0x001F);
display.fillRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
delay(PAUSE);
} // END SHAPE EXAMPLE
// CHART EXAMPLES ----------------------------------------------------------
void show_charts() {
// Draw some graphs and charts. GFX library doesn't handle these as native
// object types, but it only takes a little code to build them from simple
// shapes. This demonstrates:
// - Drawing points and horizontal, vertical and arbitrary lines.
// - Adapting to different-sized displays.
// - Graphics being clipped off edge.
// - Use of negative values to draw shapes "backward" from an anchor point.
// - C technique for finding array size at runtime (vs hardcoding).
display.fillScreen(0); // Clear screen
const int16_t cx = display.width() / 2; // Center of screen =
const int16_t cy = display.height() / 2; // half of width, height
const int16_t minor = min(cx, cy); // Lesser of half width or height
const int16_t major = max(cx, cy); // Greater of half width or height
// Let's start with a relatively simple sine wave graph with axes.
// Draw graph axes centered on screen. drawFastHLine() and drawFastVLine()
// need fewer arguments than normal 2-point line drawing shown later.
display.drawFastHLine(0, cy, display.width(), 0x0210); // Dark blue
display.drawFastVLine(cx, 0, display.height(), 0x0210);
// Then draw some tick marks along the axes. To keep this code simple,
// these aren't to any particular scale, but a real program may want that.
// The loop here draws them from the center outward and pays no mind
// whether the screen is rectangular; any ticks that go off-screen will
// be clipped by the library.
for (uint8_t i=1; i<=10; i++) {
// The Arduino map() function scales an input value (e.g. "i") from an
// input range (0-10 here) to an output range (0 to major-1 here).
// Very handy for making graphics adjust to different screens!
int16_t n = map(i, 0, 10, 0, major - 1); // Tick offset relative to center point
display.drawFastVLine(cx - n, cy - 5, 11, 0x210);
display.drawFastVLine(cx + n, cy - 5, 11, 0x210);
display.drawFastHLine(cx - 5, cy - n, 11, 0x210);
display.drawFastHLine(cx - 5, cy + n, 11, 0x210);
}
// Then draw sine wave over this using GFX drawPixel() function.
for (int16_t x=0; x<display.width(); x++) { // Each column of screen...
// Note the inverted Y axis here (cy-value rather than cy+value)
// because GFX, like most graphics libraries, has +Y heading down,
// vs. classic Cartesian coords which have +Y heading up.
int16_t y = cy - (int16_t)(sin((x - cx) * 0.05) * (float)minor * 0.5);
display.drawPixel(x, y, 0xFFFF);
}
delay(PAUSE);
// Next, let's draw some charts...
// NOTE: some other examples in this code take extra steps to avoid placing
// anything off in the rounded corners of certain displays. The charts do
// not. It's *possible* but would introduce a lot of complexity into code
// that's trying to show the basics. We'll leave the clipped charts here as
// a teachable moment: not all content suits all displays.
// A list of data to plot. These are Y values only; X assumed equidistant.
const uint8_t data[] = { 31, 42, 36, 58, 67, 88 }; // Percentages, 0-100
const uint8_t num_points = sizeof data / sizeof data[0]; // Length of data[] list
display.fillScreen(0); // Clear screen
display.setFont(); // Use default (built-in) font
display.setTextSize(2); // and 2X size for chart label
// Chart label is centered manually; 144 is the width in pixels of
// "Widget Sales" at 2X scale (12 chars * 6 px * 2 = 144). A later example
// shows automated centering based on string.
display.setCursor((display.width() - 144) / 2, 0);
display.print(F("Widget Sales")); // F("string") is in program memory, not RAM
// The chart-drawing code is then written to skip the top 20 rows where
// this label is located.
// First, a line chart, connecting the values point-to-point:
// Draw a grid of lines to provide scale & an interesting background.
for (uint8_t i=0; i<11; i++) {
int16_t x = map(i, 0, 10, 0, display.width() - 1); // Scale grid X to screen
display.drawFastVLine(x, 20, display.height(), 0x001F);
int16_t y = map(i, 0, 10, 20, display.height() - 1); // Scale grid Y to screen
display.drawFastHLine(0, y, display.width(), 0x001F);
}
// And then draw lines connecting data points. Load up the first point...
int16_t prev_x = 0;
int16_t prev_y = map(data[0], 0, 100, display.height() - 1, 20);
// Then connect lines to each subsequent point...
for (uint8_t i=1; i<num_points; i++) {
int16_t new_x = map(i, 0, num_points - 1, 0, display.width() - 1);
int16_t new_y = map(data[i], 0, 100, display.height() - 1, 20);
display.drawLine(prev_x, prev_y, new_x, new_y, 0x07FF);
prev_x = new_x;
prev_y = new_y;
}
// For visual interest, let's add a circle around each data point. This is
// done in a second pass so the circles are always drawn "on top" of lines.
for (uint8_t i=0; i<num_points; i++) {
int16_t x = map(i, 0, num_points - 1, 0, display.width() - 1);
int16_t y = map(data[i], 0, 100, display.height() - 1, 20);
display.drawCircle(x, y, 5, 0xFFFF);
}
delay(PAUSE);
// Then a bar chart of the same data...
// Erase the old chart but keep the label at top.
display.fillRect(0, 20, display.width(), display.height() - 20, 0);
// Just draw the Y axis lines; bar chart doesn't really need X lines.
for (uint8_t i=0; i<11; i++) {
int16_t y = map(i, 0, 10, 20, display.height() - 1);
display.drawFastHLine(0, y, display.width(), 0x001F);
}
int bar_width = display.width() / num_points - 4; // 2px pad to either side
for (uint8_t i=0; i<num_points; i++) {
int16_t x = map(i, 0, num_points, 0, display.width()) + 2; // Left edge of bar
int16_t height = map(data[i], 0, 100, 0, display.height() - 20);
// Some GFX functions (rects, H/V lines and similar) can accept negative
// width/height values. What this does is anchor the shape at the right or
// bottom coordinate (rather than the usual left/top) and draw back from
// there, hence the -height here (bar is anchored at bottom of screen):
display.fillRect(x, display.height() - 1, bar_width, -height, 0xFFE0);
}
delay(PAUSE);
} // END CHART EXAMPLES
// TEXT ALIGN FUNCTIONS ----------------------------------------------------
// Adafruit_GFX only handles left-aligned text. This is normal and by design;
// it's a rare need that would further strain AVR by incurring a ton of extra
// code to properly handle, and some details would confuse. If needed, these
// functions give a fair approximation, with the "gotchas" that multi-line
// input won't work, and this operates only as a println(), not print()
// (though, unlike println(), cursor X does not reset to column 0, instead
// returning to initial column and downward by font's line spacing). If you
// can work with those constraints, it's a modest amount of code to copy
// into a project. Or, if your project only needs one or two aligned strings,
// simply use getTextBounds() for a bounding box and work from there.
// DO NOT ATTEMPT TO MAKE THIS A GFX-NATIVE FEATURE, EVERYTHING WILL BREAK.
typedef enum { // Alignment options passed to functions below
GFX_ALIGN_LEFT,
GFX_ALIGN_CENTER,
GFX_ALIGN_RIGHT
} GFXalign;
// Draw text aligned relative to current cursor position. Arguments:
// gfx : An Adafruit_GFX-derived type (e.g. display or canvas object).
// str : String to print (as a char *).
// align : One of the GFXalign values declared above.
// GFX_ALIGN_LEFT is normal left-aligned println() behavior.
// GFX_ALIGN_CENTER prints centered on cursor pos.
// GFX_ALIGN_RIGHT prints right-aligned to cursor pos.
// Cursor advances down one line a la println(). Column is unchanged.
void print_aligned(Adafruit_GFX &gfx, const char *str,
GFXalign align = GFX_ALIGN_LEFT) {
uint16_t w, h;
int16_t x, y, cursor_x, cursor_x_save;
cursor_x = cursor_x_save = gfx.getCursorX();
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
gfx.println(str);
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
}
// Equivalent function for strings in flash memory (e.g. F("Foo")). Body
// appears identical to above function, but with C++ overloading it it works
// from flash instead of RAM. Any changes should be made in both places.
void print_aligned(Adafruit_GFX &gfx, const __FlashStringHelper *str,
GFXalign align = GFX_ALIGN_LEFT) {
uint16_t w, h;
int16_t x, y, cursor_x, cursor_x_save;
cursor_x = cursor_x_save = gfx.getCursorX();
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
gfx.println(str);
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
}
// Equivalent function for Arduino Strings; converts to C string (char *)
// and calls corresponding print_aligned() implementation.
void print_aligned(Adafruit_GFX &gfx, const String &str,
GFXalign align = GFX_ALIGN_LEFT) {
print_aligned(gfx, const_cast<char *>(str.c_str()));
}
// TEXT EXAMPLES -----------------------------------------------------------
// This section demonstrates:
// - Using the default 5x7 built-in font, including scaling in each axis.
// - How to access all characters of this font, including symbols.
// - Using a custom font, including alignment techniques that aren't a normal
// part of the GFX library (uses functions above).
void show_basic_text() {
// Show text scaling with built-in font.
display.fillScreen(0);
display.setFont(); // Use default font
display.setCursor(0, CORNER_RADIUS); // Initial cursor position
display.setTextSize(1); // Default size
display.println(F("Standard built-in font"));
display.setTextSize(2);
display.println(F("BIG TEXT"));
display.setTextSize(3);
// "BIGGER TEXT" won't fit on narrow screens, so abbreviate there.
display.println((display.width() >= 200) ? F("BIGGER TEXT") : F("BIGGER"));
display.setTextSize(2, 4);
display.println(F("TALL and"));
display.setTextSize(4, 2);
display.println(F("WIDE"));
delay(PAUSE);
} // END BASIC TEXT EXAMPLE
void show_char_map() {
// "Code Page 437" is a name given to the original IBM PC character set.
// Despite age and limited language support, still seen in small embedded
// settings as it has some useful symbols and accented characters. The
// default 5x7 pixel font of Adafruit_GFX is modeled after CP437. This
// function draws a table of all the characters & explains some issues.
// There are 256 characters in all. Draw table as 16 rows of 16 columns,
// plus hexadecimal row & column labels. How big can each cell be drawn?
const int cell_size = min(display.width(), display.height()) / 17;
if (cell_size < 8) return; // Screen is too small for table, skip example.
const int total_size = cell_size * 17; // 16 cells + 1 row or column label
// Set up for default 5x7 font at 1:1 scale. Custom fonts are NOT used
// here as most are only 128 characters to save space (the "7b" at the
// end of many GFX font names means "7 bits," i.e. 128 characters).
display.setFont();
display.setTextSize(1);
// Early Adafruit_GFX was missing one symbol, throwing off some indices!
// But fixing the library would break MANY existing sketches that relied
// on the degrees symbol and others. The default behavior is thus "broken"
// to keep older code working. New code can access the CORRECT full CP437
// table by calling this function like so:
display.cp437(true);
display.fillScreen(0);
const int16_t x = (display.width() - total_size) / 2; // Upper left corner of
int16_t y = (display.height() - total_size) / 2; // table centered on screen
if (y >= 4) { // If there's a little extra space above & below, scoot table
y += 4; // down a few pixels and show a message centered at top.
display.setCursor((display.width() - 114) / 2, 0); // 114 = pixel width
display.print(F("CP437 Character Map")); // of this message
}
const int16_t inset_x = (cell_size - 5) / 2; // To center each character within cell,
const int16_t inset_y = (cell_size - 8) / 2; // compute X & Y offset from corner.
for (uint8_t row=0; row<16; row++) { // 16 down...
// Draw row and columm headings as hexadecimal single digits. To get the
// hex value for a specific character, combine the left & top labels,
// e.g. Pi symbol is row E, column 3, thus: display.print((char)0xE3);
display.setCursor(x + (row + 1) * cell_size + inset_x, y + inset_y);
display.print(row, HEX); // This actually draws column labels
display.setCursor(x + inset_x, y + (row + 1) * cell_size + inset_y);
display.print(row, HEX); // and THIS is the row labels
for (uint8_t col=0; col<16; col++) { // 16 across...
if ((row + col) & 1) { // Fill alternating cells w/gray
display.fillRect(x + (col + 1) * cell_size, y + (row + 1) * cell_size,
cell_size, cell_size, 0x630C);
}
// drawChar() bypasses usual cursor positioning to go direct to an X/Y
// location. If foreground & background match, it's drawn transparent.
display.drawChar(x + (col + 1) * cell_size + inset_x,
y + (row + 1) * cell_size + inset_y, row * 16 + col,
0xFFFF, 0xFFFF, 1);
}
}
delay(PAUSE * 2);
} // END CHAR MAP EXAMPLE
void show_custom_text() {
// Show use of custom fonts, plus how to do center or right alignment
// using some additional functions provided earlier.
display.fillScreen(0);
display.setFont(&FreeSansBold18pt7b);
display.setTextSize(1);
display.setTextWrap(false); // Allow text off edges
// Get "M height" of custom font and move initial base line there:
uint16_t w, h;
int16_t x, y;
display.getTextBounds("M", 0, 0, &x, &y, &w, &h);
// On rounded 240x280 display in tall orientation, "Custom Font" gets
// clipped by top corners. Scoot text down a few pixels in that one case.
if (CORNER_RADIUS && (display.height() == 280)) h += 20;
display.setCursor(display.width() / 2, h);
if (display.width() >= 200) {
print_aligned(display, F("Custom Font"), GFX_ALIGN_CENTER);
display.setCursor(0, display.getCursorY() + 10);
print_aligned(display, F("Align Left"), GFX_ALIGN_LEFT);
display.setCursor(display.width() / 2, display.getCursorY());
print_aligned(display, F("Centered"), GFX_ALIGN_CENTER);
// Small rounded screen, when oriented the wide way, "Right" gets
// clipped by bottom right corner. Scoot left to compensate.
int16_t x_offset = (CORNER_RADIUS && (display.height() < 200)) ? 15 : 0;
display.setCursor(display.width() - x_offset, display.getCursorY());
print_aligned(display, F("Align Right"), GFX_ALIGN_RIGHT);
} else {
// On narrow screens, use abbreviated messages
print_aligned(display, F("Font &"), GFX_ALIGN_CENTER);
print_aligned(display, F("Align"), GFX_ALIGN_CENTER);
display.setCursor(0, display.getCursorY() + 10);
print_aligned(display, F("Left"), GFX_ALIGN_LEFT);
display.setCursor(display.width() / 2, display.getCursorY());
print_aligned(display, F("Center"), GFX_ALIGN_CENTER);
display.setCursor(display.width(), display.getCursorY());
print_aligned(display, F("Right"), GFX_ALIGN_RIGHT);
}
delay(PAUSE);
} // END CUSTOM FONT EXAMPLE
// BITMAP EXAMPLE ----------------------------------------------------------
// This section demonstrates:
// - Embedding a small bitmap in the code (flash memory).
// - Drawing that bitmap in various colors, and transparently (only '1' bits
// are drawn; '0' bits are skipped, leaving screen contents in place).
// - Use of the color565() function to decimate 24-bit RGB to 16 bits.
#define HEX_WIDTH 16 // Bitmap width in pixels
#define HEX_HEIGHT 16 // Bitmap height in pixels
// Bitmap data. PROGMEM ensures it's in flash memory (not RAM). And while
// it would be valid to leave the brackets empty here (i.e. hex_bitmap[]),
// having dimensions with a little math makes the compiler verify the
// correct number of bytes are present in the list.
PROGMEM const uint8_t hex_bitmap[(HEX_WIDTH + 7) / 8 * HEX_HEIGHT] = {
0b00000001, 0b10000000,
0b00000111, 0b11100000,
0b00011111, 0b11111000,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b01111111, 0b11111110,
0b00011111, 0b11111000,
0b00000111, 0b11100000,
0b00000001, 0b10000000,
};
#define Y_SPACING (HEX_HEIGHT - 2) // Used by code below for positioning
void show_bitmap() {
display.fillScreen(0);
// Not screen center, but UL coordinates of center hexagon bitmap
const int16_t center_x = (display.width() - HEX_WIDTH) / 2;
const int16_t center_y = (display.height() - HEX_HEIGHT) / 2;
const uint8_t steps = min((display.height() - HEX_HEIGHT) / Y_SPACING,
display.width() / HEX_WIDTH - 1) / 2;
display.drawBitmap(center_x, center_y, hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
0xFFFF); // Draw center hexagon in white
// Tile the hexagon bitmap repeatedly in a range of hues. Don't mind the
// bit of repetition in the math, the optimizer easily picks this up.
// Also, if math looks odd, keep in mind "PEMDAS" operator precedence;
// multiplication and division occur before addition and subtraction.
for (uint8_t a=0; a<=steps; a++) {
for (uint8_t b=1; b<=steps; b++) {
display.drawBitmap( // Right section centered red: a = green, b = blue
center_x + (a + b) * HEX_WIDTH / 2,
center_y + (a - b) * Y_SPACING,
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
display.color565(255, 255 - 255 * a / steps, 255 - 255 * b / steps));
display.drawBitmap( // UL section centered green: a = blue, b = red
center_x - b * HEX_WIDTH + a * HEX_WIDTH / 2,
center_y - a * Y_SPACING,
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
display.color565(255 - 255 * b / steps, 255, 255 - 255 * a / steps));
display.drawBitmap( // LL section centered blue: a = red, b = green
center_x - a * HEX_WIDTH + b * HEX_WIDTH / 2,
center_y + b * Y_SPACING,
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
display.color565(255 - 255 * a / steps, 255 - 255 * b / steps, 255));
}
}
delay(PAUSE);
} // END BITMAP EXAMPLE
// CANVAS EXAMPLE ----------------------------------------------------------
// This section demonstrates:
// - How to refresh changing values onscreen without erase/redraw flicker.
// - Using an offscreen canvas. It's similar to a bitmap above, but rather
// than a fixed pattern in flash memory, it's drawable like the screen.
// - More tips on text alignment, and adapting to different screen sizes.
#define PADDING 6 // Pixels between axis label and value
void show_canvas() {
// For this example, let's suppose we want to display live readings from a
// sensor such as a three-axis accelerometer, something like:
// X: (number)
// Y: (number)
// Z: (number)
// To look extra classy, we want a custom font, and the labels for each
// axis are right-aligned so the ':' characters line up...
display.setFont(&FreeSansBold18pt7b); // Use a custom font
display.setTextSize(1); // and reset to 1:1 scale
char *label[] = { "X:", "Y:", "Z:" }; // Labels for each axis
const uint16_t color[] = { 0xF800, 0x07E0, 0x001F }; // Colors for each value
// To get the labels right-aligned, one option would be simple trial and
// error to find a column that looks good and doesn't clip anything off.
// Let's do this dynamically though, so it adapts to any font or labels!
// Start by finding the widest of the label strings:
uint16_t w, h, max_w = 0;
int16_t x, y;
for (uint8_t i=0; i<3; i++) { // For each label...
display.getTextBounds(label[i], 0, 0, &x, &y, &w, &h);
if (w > max_w) max_w = w; // Keep track of widest label
}
// Rounded corners throwing us a curve again. If needed, scoot everything
// to the right a bit on wide displays, down a bit on tall ones.
int16_t y_offset = 0;
if (display.width() > display.height()) max_w += CORNER_RADIUS;
else y_offset = CORNER_RADIUS;
// Now we have max_w for right-aligning the labels. Before we draw them
// though...in order to perform flicker-free updates, the numbers we show
// will be rendered in either a GFXcanvas1 or GFXcanvas16 object; a 1-bit
// or 16-bit offscreen bitmap, RAM permitting. The correct size for this
// canvas could also be trial-and-errored, but again let's make this adapt
// automatically. The width of the canvas will span from max_w (plus a few
// pixels for padding) to the right edge. But the height? Looking at an
// uppercase 'M' can work in many situations, but some fonts have ascenders
// and descenders on digits, and in some locales a comma (extending below
// the baseline) is the decimal separator. Feed ALL the numeric chars into
// getTextBounds() for a cumulative height:
display.setTextWrap(false); // Keep on one line
display.getTextBounds(F("0123456789.,-"), 0, 0, &x, &y, &w, &h);
// Now declare a GFXcanvas16 object based on the computed width & height:
GFXcanvas16 canvas16(display.width() - max_w - PADDING, h);
// Small devices (e.g. ATmega328p) will almost certainly lack enough RAM
// for the canvas. Check if canvas buffer exists. If not, fall back on
// using a 1-bit (rather than 16-bit) canvas. Much more RAM friendly, but
// not as fast to draw. If a project doesn't require super interactive
// updates, consider just going straight for the more compact Canvas1.
if (canvas16.getBuffer()) {
// If here, 16-bit canvas allocated successfully! Point of interest,
// only one canvas is needed for this example, we can reuse it for all
// three numbers because the regions are the same size.
// display and canvas are independent drawable objects; must explicitly
// set the same custom font to use on the canvas now:
canvas16.setFont(&FreeSansBold18pt7b);
// Clear display and print labels. Once drawn, these remain untouched.
display.fillScreen(0);
display.setCursor(max_w, -y + y_offset); // Set baseline for first row
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
// Last part now is to print numbers on the canvas and copy the canvas to
// the display, repeating for several seconds...
uint32_t elapsed, startTime = millis();
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
for (uint8_t i=0; i<3; i++) { // For each label...
canvas16.fillScreen(0); // fillScreen() in this case clears canvas
canvas16.setCursor(0, -y); // Reset baseline for custom font
canvas16.setTextColor(color[i]);
// These aren't real accelerometer readings, just cool-looking numbers.
// Notice we print to the canvas, NOT the display:
canvas16.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
// And HERE is the secret sauce to flicker-free updates. Canvas details
// can be passed to the drawRGBBitmap() function, which fully overwrites
// prior screen contents in that area. yAdvance is font line spacing.
display.drawRGBBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
y_offset, canvas16.getBuffer(), canvas16.width(),
canvas16.height());
}
}
} else {
// Insufficient RAM for Canvas16. Try declaring a 1-bit canvas instead...
GFXcanvas1 canvas1(display.width() - max_w - PADDING, h);
// If even this smaller object fails, can't proceed, cancel this example.
if (!canvas1.getBuffer()) return;
// Remainder here is nearly identical to the code above, simply using a
// different canvas type. It's stripped of most comments for brevity.
canvas1.setFont(&FreeSansBold18pt7b);
display.fillScreen(0);
display.setCursor(max_w, -y + y_offset);
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
uint32_t elapsed, startTime = millis();
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
for (uint8_t i=0; i<3; i++) {
canvas1.fillScreen(0);
canvas1.setCursor(0, -y);
canvas1.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
// Here's the secret sauce to flicker-free updates with GFXcanvas1.
// Canvas details can be passed to the drawBitmap() function, and by
// specifying both a foreground AND BACKGROUND color (0), this will fully
// overwrite/erase prior screen contents in that area (vs transparent).
display.drawBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
y_offset, canvas1.getBuffer(), canvas1.width(),
canvas1.height(), color[i], 0);
}
}
}
// Because canvas object was declared locally to this function, it's freed
// automatically when the function returns; no explicit delete needed.
} // END CANVAS EXAMPLE

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2020[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x1f, 0xf0, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xf8,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x7c, 0x7c, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0x7c, 0x3c,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0xf8, 0x3e,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0xf8, 0x3e, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0xf8, 0x3e, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0xf8, 0x3e,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc0, 0xf8, 0x3e, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x80, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x00, 0x78, 0x7c, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x7c, 0x7c,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x3f, 0xf8, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x3f, 0xf0,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,205 +0,0 @@
// SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <Adafruit_LIS3DH.h> // For accelerometer
#include <Adafruit_PixelDust.h> // For simulation
#include <Adafruit_Protomatter.h> // For LED matrix
#include "2020.h" // 2020 bitmap data
#include "2021.h" // 2021 bitmap data
#include "2022.h" // etc.
#include "2023.h"
#include "2024.h"
#include "2025.h"
#include "2026.h"
#define BITMAP_WIDTH 64 // All the year bitmaps are a fixed size
#define BITMAP_HEIGHT 32
#define THIS_YEAR_BITMAP bitmap_2021 // Name of current/next year bitmap
#define NEXT_YEAR_BITMAP bitmap_2022 // arrays in header files
bool show_new_year = true;
#define SHAKE_ACCEL_G 2.9 // Force (in Gs) to trigger shake
#define SHAKE_ACCEL_MS2 (SHAKE_ACCEL_G * 9.8) // Convert to m/s^2
#define SHAKE_ACCEL_SQ (SHAKE_ACCEL_MS2 * SHAKE_ACCEL_MS2) // Avoid sqrt() in accel check
#define SHAKE_EVENTS 30 // Number of accel readings to trigger sand
#define SHAKE_PERIOD 2000 // Period (in ms) when SHAKE_EVENTS must happen
#define SAND_TIME 6000 // Time (in ms) to run simulation before restarting
#if defined(_VARIANT_MATRIXPORTAL_M4_) // MatrixPortal M4
uint8_t rgbPins[] = {7, 8, 9, 10, 11, 12};
uint8_t addrPins[] = {17, 18, 19, 20, 21};
uint8_t clockPin = 14;
uint8_t latchPin = 15;
uint8_t oePin = 16;
#else // MatrixPortal ESP32-S3
uint8_t rgbPins[] = {42, 41, 40, 38, 39, 37};
uint8_t addrPins[] = {35, 36, 48, 45, 21};
uint8_t clockPin = 2;
uint8_t latchPin = 47;
uint8_t oePin = 14;
#endif
// 64x32 pixel matrix, 6-bit depth
Adafruit_Protomatter matrix(
64, 6, 1, rgbPins, 4, addrPins, clockPin, latchPin, oePin, true);
Adafruit_LIS3DH accel = Adafruit_LIS3DH(); // Accelerometer
#define MAX_FPS 60 // Maximum redraw rate, frames/second
uint32_t prevTime = 0; // For frames-per-second throttle
uint16_t n_grains = 0; // Number of sand grains (counted on startup)
Adafruit_PixelDust *sand; // Sand object (allocated in setup())
// Error handler used by setup()
void err(int x) {
uint8_t i;
pinMode(LED_BUILTIN, OUTPUT); // Using onboard LED
for(i=1;;i++) { // Loop forever...
digitalWrite(LED_BUILTIN, i & 1); // LED on/off blink to alert user
delay(x);
}
}
// SETUP - RUNS ONCE AT PROGRAM START --------------------------------------
void setup(void) {
uint8_t i, j, bytes;
Serial.begin(115200);
//while (!Serial);
ProtomatterStatus status = matrix.begin();
Serial.printf("Protomatter begin() status: %d\n", status);
// Count number of 'on' pixels (sand grains) in THIS_YEAR_BITMAP
for (int i=0; i<sizeof(THIS_YEAR_BITMAP); i++) {
for (int b=0; b<8; b++) {
if (THIS_YEAR_BITMAP[i] & (1 << b)) {
n_grains++;
}
}
}
Serial.printf("Bitmap has %d grains\n", n_grains);
// Allocate sand object based on matrix size and bitmap 'on' pixels
sand = new Adafruit_PixelDust(matrix.width(), matrix.height(), n_grains, 1);
if (!sand->begin()) {
Serial.println("Couldn't start sand");
err(1000); // Slow blink = malloc error
}
if (!accel.begin(0x19)) {
Serial.println("Couldn't find accelerometer");
err(250); // Fast bink = I2C error
}
Serial.println("Accelerometer OK");
accel.setRange(LIS3DH_RANGE_8_G);
}
void loop() {
Serial.print("Tick");
uint16_t sandColor = show_new_year ? 0xF800 : 0xFFFF; // Red or white
// Set initial sand pixel positions and draw initial matrix state
sand->clear();
matrix.fillScreen(0);
int grain = 0, pixel = 0; // Sand grain and pixel indices
for (int i=0; i<sizeof(THIS_YEAR_BITMAP); i++) {
for (int b=0; b<8; b++, pixel++) {
if (THIS_YEAR_BITMAP[i] & (1 << (7-b))) {
int x = pixel % BITMAP_WIDTH;
int y = pixel / BITMAP_WIDTH;
//Serial.printf("Set pixel %d @ (%d, %d)\n", grain, x, y);
sand->setPosition(grain++, x, y);
matrix.drawPixel(x, y, sandColor);
}
}
}
matrix.show();
// Wait for shake
uint32_t first_event_time = millis() - SHAKE_PERIOD * 2, last_event_time = first_event_time;
uint8_t num_events = 0;
sensors_event_t event;
for (;;) {
uint32_t t = millis(); // Current time
accel.getEvent(&event);
float mag2 = event.acceleration.x * event.acceleration.x +
event.acceleration.y * event.acceleration.y +
event.acceleration.z * event.acceleration.z;
if (mag2 >= SHAKE_ACCEL_SQ) { // Accel exceeds shake threshold
if ((t - last_event_time) > SHAKE_PERIOD) { // Long time since last event?
first_event_time = t; // Start of new count
num_events = 1;
} else if ((t - first_event_time) < SHAKE_PERIOD) { // Still in shake interval?
if (++num_events >= SHAKE_EVENTS) { // Enough events?
break;
}
}
last_event_time = t;
}
}
// Run sand simulation for a few seconds
uint32_t elapsed, sandStartTime = millis();
while((elapsed = (millis() - sandStartTime)) < SAND_TIME) {
// Limit the animation frame rate to MAX_FPS.
uint32_t t;
while(((t = micros()) - prevTime) < (1000000L / MAX_FPS));
prevTime = t;
// Read accelerometer...
sensors_event_t event;
accel.getEvent(&event);
// Run one frame of the simulation
sand->iterate(event.acceleration.x * 1024, event.acceleration.y * 1024, event.acceleration.z * 1024);
if (elapsed > SAND_TIME * 3 / 4) {
float scale = 1.0 - (float)(elapsed - (SAND_TIME * 3 / 4)) / (float)(SAND_TIME / 4);
if (scale < 0.0) scale = 0.0;
else if (scale > 1.0) scale = 1.0;
scale = pow(scale, 2.6);
uint16_t rb = (int)(31.0 * scale + 0.5);
uint16_t g = (int)(63.0 * scale + 0.5);
if (show_new_year)
sandColor = (rb * 0b100000000000); // Just show red
else
sandColor = (rb * 0b100000000001) + (g << 5);
}
// Update pixel data in LED driver
matrix.fillScreen(0);
dimension_t x, y;
for(int i=0; i<n_grains ; i++) {
sand->getPosition(i, &x, &y);
matrix.drawPixel(x, y, sandColor);
}
matrix.show();
}
// If the show_new_year flag is set, don't return to shake detect,
// instead switch to sparkly display forever (reset to start over)
if (show_new_year) {
uint16_t frame = 0;
matrix.fillScreen(0);
for(;;) {
int pixel = 0;
for (int i=0; i<sizeof(NEXT_YEAR_BITMAP); i++) {
for (int b=0; b<8; b++, pixel++) {
if (NEXT_YEAR_BITMAP[i] & (1 << (7-b))) {
int x = pixel % BITMAP_WIDTH;
int y = pixel / BITMAP_WIDTH;
matrix.drawPixel(x, y, (random() & 1) ? ((((x - y + frame) / 8) & 1) ? 0xFFFF : 0x001F) : 0);
}
}
}
matrix.show();
delay(18);
frame++;
}
}
}

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2021[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xfc, 0x01, 0xfc, 0x01, 0xfc, 0x00, 0x78, 0x03, 0xff, 0x03, 0xfe,
0x03, 0xff, 0x00, 0x78, 0x07, 0xff, 0x87, 0xff, 0x07, 0xff, 0x80, 0xf8,
0x0f, 0xff, 0x8f, 0xff, 0x8f, 0xff, 0x81, 0xf8, 0x0f, 0x8f, 0xcf, 0x8f,
0x8f, 0x8f, 0xdf, 0xf8, 0x1f, 0x07, 0xcf, 0x87, 0x9f, 0x07, 0xdf, 0xf8,
0x1f, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xdf, 0xf8, 0x1f, 0x07, 0xdf, 0x07,
0xdf, 0x07, 0xdf, 0xf8, 0x1f, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xc0, 0xf8,
0x00, 0x07, 0xdf, 0x07, 0xc0, 0x07, 0xc0, 0xf8, 0x00, 0x0f, 0x9f, 0x07,
0xc0, 0x0f, 0x80, 0xf8, 0x00, 0x0f, 0x9f, 0x07, 0xc0, 0x0f, 0x80, 0xf8,
0x00, 0x3f, 0x1f, 0x07, 0xc0, 0x3f, 0x00, 0xf8, 0x00, 0x7e, 0x1f, 0x07,
0xc0, 0x7e, 0x00, 0xf8, 0x00, 0xfc, 0x1f, 0x07, 0xc0, 0xfc, 0x00, 0xf8,
0x01, 0xf8, 0x1f, 0x07, 0xc1, 0xf8, 0x00, 0xf8, 0x03, 0xf0, 0x1f, 0x07,
0xc3, 0xf0, 0x00, 0xf8, 0x03, 0xe0, 0x1f, 0x07, 0xc3, 0xe0, 0x00, 0xf8,
0x07, 0xc0, 0x1f, 0x07, 0xc7, 0xc0, 0x00, 0xf8, 0x0f, 0x80, 0x0f, 0x0f,
0x8f, 0x80, 0x00, 0xf8, 0x0f, 0x80, 0x0f, 0x8f, 0x8f, 0x80, 0x00, 0xf8,
0x1f, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0xc0, 0xf8, 0x1f, 0xff, 0xc7, 0xff,
0x1f, 0xff, 0xc0, 0xf8, 0x1f, 0xff, 0xc7, 0xfe, 0x1f, 0xff, 0xc0, 0xf8,
0x1f, 0xff, 0xc1, 0xfc, 0x1f, 0xff, 0xc0, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2022[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x7c, 0x7e, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0x00, 0x7c,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0x01, 0xf8, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0x03, 0xf0, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0x07, 0xe0,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc0, 0x0f, 0xc0, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x80, 0x1f, 0x80, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x00, 0x1f, 0x00,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x00, 0x3e, 0x00, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x7c, 0x00,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0xff, 0xfe,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2023[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xc0, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x3f, 0xf0, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xf8,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x7c, 0xfc, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0xf8, 0x7c,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x7c, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0xf8, 0x7c, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x00, 0x7c,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0x00, 0xf8, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0x0f, 0xf8, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0x0f, 0xe0,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0x0f, 0xf8, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0x0f, 0xfc, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0x00, 0xfc,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc0, 0x00, 0x7e, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x80, 0x00, 0x3e, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x7c, 0x7e,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x3f, 0xfc, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x1f, 0xf8,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2024[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x01, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x01, 0xf8, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x03, 0xf8,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x03, 0xf8, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x07, 0xf8, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0x07, 0xf8,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x0f, 0xf8, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0x1e, 0xf8, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x1e, 0xf8,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0x3c, 0xf8, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0x3c, 0xf8, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0x78, 0xf8,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0x78, 0xf8, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0xf0, 0xf8, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0xf0, 0xf8,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc1, 0xe0, 0xf8, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x81, 0xff, 0xfe, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x01, 0xff, 0xfe,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x01, 0xff, 0xfe, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x01, 0xff, 0xfe, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0xf8,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x00, 0xf8, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x00, 0xf8, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x00, 0xf8,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2025[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x7f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfc,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x7f, 0xfc, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0x78, 0x00,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x78, 0x00, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0x78, 0x00, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0x79, 0xf0,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0x7f, 0xf8, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0x7f, 0xfc, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0x7f, 0xfc,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0x7c, 0x7e, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0x78, 0x3e, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0x00, 0x3e,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc0, 0x00, 0x3e, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x80, 0x00, 0x3e, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0xfc, 0x7c,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x7f, 0xf8, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const uint8_t PROGMEM bitmap_2026[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xe0, 0x0f, 0xe0, 0x0f, 0xe0, 0x07, 0xe0, 0x1f, 0xf8, 0x1f, 0xf0,
0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc,
0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, 0x7c, 0x7e, 0x7c, 0x7c,
0x7c, 0x7e, 0x7c, 0x3e, 0xf8, 0x3e, 0x7c, 0x3c, 0xf8, 0x3e, 0x7c, 0x3e,
0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x00, 0xf8, 0x3e, 0xf8, 0x3e,
0xf8, 0x3e, 0xf8, 0x00, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x3e, 0xf8, 0x00,
0x00, 0x3e, 0xf8, 0x3e, 0x00, 0x3e, 0xf9, 0xf0, 0x00, 0x7c, 0xf8, 0x3e,
0x00, 0x7c, 0xfb, 0xf8, 0x00, 0x7c, 0xf8, 0x3e, 0x00, 0x7c, 0xff, 0xfc,
0x01, 0xf8, 0xf8, 0x3e, 0x01, 0xf8, 0xff, 0xfc, 0x03, 0xf0, 0xf8, 0x3e,
0x03, 0xf0, 0xfc, 0x7e, 0x07, 0xe0, 0xf8, 0x3e, 0x07, 0xe0, 0xf8, 0x3e,
0x0f, 0xc0, 0xf8, 0x3e, 0x0f, 0xc0, 0xf8, 0x3e, 0x1f, 0x80, 0xf8, 0x3e,
0x1f, 0x80, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e, 0x1f, 0x00, 0xf8, 0x3e,
0x3e, 0x00, 0xf8, 0x3e, 0x3e, 0x00, 0xf8, 0x3e, 0x7c, 0x00, 0x78, 0x7c,
0x7c, 0x00, 0x78, 0x3e, 0x7c, 0x00, 0x7c, 0x7c, 0x7c, 0x00, 0x7c, 0x7c,
0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x7f, 0xfc, 0xff, 0xfe, 0x3f, 0xf8,
0xff, 0xfe, 0x3f, 0xf8, 0xff, 0xfe, 0x3f, 0xf0, 0xff, 0xfe, 0x1f, 0xf8,
0xff, 0xfe, 0x0f, 0xe0, 0xff, 0xfe, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

BIN
3D_Printed_Bionic_Eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,76 +0,0 @@
// SPDX-FileCopyrightText: 2018 Bill Earl and Mikey Sklar for Adafruit Industries
//
// SPDX-License-Identifier: MIT
/*******************************************************************
Bionic Eye sketch for Adafruit Trinket.
by Bill Earl
for Adafruit Industries
Required library is the Adafruit_SoftServo library
available at https://github.com/adafruit/Adafruit_SoftServo
The standard Arduino IDE servo library will not work with 8 bit
AVR microcontrollers like Trinket and Gemma due to differences
in available timer hardware and programming. We simply refresh
by piggy-backing on the timer0 millis() counter
Trinket: Bat+ Gnd Pin #0 Pin #1
Connection: Servo+ Servo- Tilt Rotate
(Red) (Brown) Servo Servo
(Orange)(Orange)
*******************************************************************/
#include <Adafruit_SoftServo.h> // SoftwareServo (works on non PWM pins)
#define TILTSERVOPIN 0 // Servo control line (orange) on Trinket Pin #0
#define ROTATESERVOPIN 1 // Servo control line (orange) on Trinket Pin #1
Adafruit_SoftServo TiltServo, RotateServo; //create TWO servo objects
void setup()
{
// Set up the interrupt that will refresh the servo for us automagically
OCR0A = 0xAF; // any number is OK
TIMSK |= _BV(OCIE0A); // Turn on the compare interrupt (below!)
TiltServo.attach(TILTSERVOPIN); // Attach the servo to pin 0 on Trinket
RotateServo.attach(ROTATESERVOPIN); // Attach the servo to pin 1 on Trinket
delay(15); // Wait 15ms for the servo to reach the position
}
void loop()
{
delay(100);
TiltServo.detach(); // release the servo
RotateServo.detach(); // release the servo
if(random(100) > 80) // on average, move once every 500ms
{
TiltServo.attach(TILTSERVOPIN); // Attach the servo to pin 0 on Trinket
TiltServo.write(random(120, 180)); // Tell servo to go to position
}
if(random(100) > 90) // on average, move once every 500ms
{
RotateServo.attach(ROTATESERVOPIN); // Attach the servo to pin 1 on Trinket
RotateServo.write(random(0, 180)); // Tell servo to go to position
}
}
// We'll take advantage of the built in millis() timer that goes off
// to keep track of time, and refresh the servo every 20 milliseconds
// The SIGNAL(TIMER0_COMPA_vect) function is the interrupt that will be
// Called by the microcontroller every 2 milliseconds
volatile uint8_t counter = 0;
SIGNAL(TIMER0_COMPA_vect)
{
// this gets called every 2 milliseconds
counter += 2;
// every 20 milliseconds, refresh the servos!
if (counter >= 20)
{
counter = 0;
TiltServo.refresh();
RotateServo.refresh();
}
}

View file

@ -1,4 +0,0 @@
# 3D_Printed_Bionic_Eye
Code to accompany this Adafruit tutorial:
https://learn.adafruit.com/3d-printed-bionic-eye

View file

@ -1,54 +0,0 @@
# SPDX-FileCopyrightText: 2018 Bill Earl and Mikey Sklar for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#
# Bionic Eye sketch for Adafruit Trinket.
#
# written by Bill Earl for Arduino
# ported to CircuitPython by Mikey Sklar
# for Adafruit Industries
#
# Required library is the Adafruit_SoftServo library
# available at https://github.com/adafruit/Adafruit_SoftServo
# The standard Arduino IDE servo library will not work with 8 bit
# AVR microcontrollers like Trinket and Gemma due to differences
# in available timer hardware and programming. We simply refresh
# by piggy-backing on the timer0 millis() counter
#
# Trinket: Bat+ Gnd Pin #0 Pin #2
# Connection: Servo+ Servo- Tilt Rotate
# (Red) (Black) Servo Servo
# (Orange)(Orange)
import time
import random
import board
import pwmio
from adafruit_motor import servo
# we are intentionally avoiding Trinket Pin #1 (board.A0)
# as it does not have PWM capability
tilt_servo_pin = board.A2 # servo control line (orange) Trinket Pin #0
rotate_servo_pin = board.A1 # servo control line (orange) Trinket Pin #2
# servo object setup for the M0 boards:
tilt_pwm = pwmio.PWMOut(tilt_servo_pin, duty_cycle=2 ** 15, frequency=50)
rotate_pwm = pwmio.PWMOut(rotate_servo_pin, duty_cycle=2 ** 15, frequency=50)
tilt_servo = servo.Servo(tilt_pwm)
rotate_servo = servo.Servo(rotate_pwm)
# servo timing and angle range
tilt_min = 120 # lower limit to tilt rotation range
max_rotate = 180 # rotation range limited to half circle
while True:
# servo tilt - on average move every 500ms
if random.randint(0,100) > 80:
tilt_servo.angle = random.randint(tilt_min, max_rotate)
time.sleep(.25)
# servo rotate - on average move every 500ms
if random.randint(0,100) > 90:
rotate_servo.angle = random.randint(0, max_rotate)
time.sleep(.25)

View file

@ -1,132 +0,0 @@
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
// Fiery demon horns (rawr!) for Adafruit Trinket/Gemma.
// Adafruit invests time and resources providing this open source code,
// please support Adafruit and open-source hardware by purchasing
// products from Adafruit!
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#define N_HORNS 1
#define N_LEDS 30 // Per horn
#define PIN 0
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_HORNS * N_LEDS, PIN);
// /\ -> Fire-like effect is the sum of multiple triangle
// ____/ \____ waves in motion, with a 'warm' color map applied.
#define N_WAVES 6 // Number of simultaneous waves (per horn)
// Coordinate space for waves is 16x the pixel spacing,
// allowing fixed-point math to be used instead of floats.
struct {
int16_t lower; // Lower bound of wave
int16_t upper; // Upper bound of wave
int16_t mid; // Midpoint (peak) ((lower+upper)/2)
uint8_t vlower; // Velocity of lower bound
uint8_t vupper; // Velocity of upper bound
uint16_t intensity; // Brightness at peak
} wave[N_HORNS][N_WAVES];
long fade; // Decreases brightness as wave moves
// Gamma correction improves appearance of midrange colors
const uint8_t gamma[] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
static void random_wave(uint8_t h,uint8_t w) { // Randomize one wave struct
wave[h][w].upper = -1; // Always start just below head of strip
wave[h][w].lower = -16 * (3 + random(4)); // Lower end starts ~3-7 pixels back
wave[h][w].mid = (wave[h][w].lower + wave[h][w].upper) / 2;
wave[h][w].vlower = 3 + random(4); // Lower end moves at ~1/8 to 1/4 pixel/frame
wave[h][w].vupper = wave[h][w].vlower + random(4); // Upper end moves a bit faster, spreading wave
wave[h][w].intensity = 300 + random(600);
}
void setup() {
uint8_t h, w;
randomSeed(analogRead(1));
pixels.begin();
for(h=0; h<N_HORNS; h++) {
for(w=0; w<N_WAVES; w++) random_wave(h, w);
}
fade = 234 + N_LEDS / 2;
if(fade > 255) fade = 255;
// A ~100 Hz timer interrupt on Timer/Counter1 makes everything run
// at regular intervals, regardless of current amount of motion.
#if F_CPU == 16000000L
clock_prescale_set(clock_div_1);
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS11) | _BV(CS10); // 1:1024 prescale
OCR1C = F_CPU / 1024 / 100 - 1;
#else
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS11); // 1:512 prescale
OCR1C = F_CPU / 512 / 100 - 1;
#endif
GTCCR = 0; // No PWM out
TIMSK |= _BV(TOIE1); // Enable overflow interrupt
}
void loop() { } // Not used -- everything's in interrupt below
ISR(TIMER1_OVF_vect) {
uint8_t h, w, i, r, g, b;
int16_t x;
uint16_t sum;
for(h=0; h<N_HORNS; h++) { // For each horn...
for(x=7, i=0; i<N_LEDS; i++, x+=16) { // For each LED along horn...
for(sum=w=0; w<N_WAVES; w++) { // For each wave of horn...
if((x < wave[h][w].lower) || (x > wave[h][w].upper)) continue; // Out of range
if(x <= wave[h][w].mid) { // Lower half of wave (ramping up to peak brightness)
sum += wave[h][w].intensity * (x - wave[h][w].lower) / (wave[h][w].mid - wave[h][w].lower);
} else { // Upper half of wave (ramping down from peak)
sum += wave[h][w].intensity * (wave[h][w].upper - x) / (wave[h][w].upper - wave[h][w].mid);
}
}
// Now the magnitude (sum) is remapped to color for the LEDs.
// A blackbody palette is used - fades white-yellow-red-black.
if(sum < 255) { // 0-254 = black to red-1
r = pgm_read_byte(&gamma[sum]);
g = b = 0;
} else if(sum < 510) { // 255-509 = red to yellow-1
r = 255;
g = pgm_read_byte(&gamma[sum - 255]);
b = 0;
} else if(sum < 765) { // 510-764 = yellow to white-1
r = g = 255;
b = pgm_read_byte(&gamma[sum - 510]);
} else { // 765+ = white
r = g = b = 255;
}
pixels.setPixelColor(h * N_LEDS + i, r, g, b);
}
for(w=0; w<N_WAVES; w++) { // Update wave positions for each horn
wave[h][w].lower += wave[h][w].vlower; // Advance lower position
if(wave[h][w].lower >= (N_LEDS * 16)) { // Off end of strip?
random_wave(h, w); // Yes, 'reboot' wave
} else { // No, adjust other values...
wave[h][w].upper += wave[h][w].vupper;
wave[h][w].mid = (wave[h][w].lower + wave[h][w].upper) / 2;
wave[h][w].intensity = (wave[h][w].intensity * fade) / 256; // Dimmer
}
}
}
pixels.show();
}

View file

@ -1,151 +0,0 @@
# SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Fiery demon horns (rawr!) for Adafruit Trinket/Gemma.
# Adafruit invests time and resources providing this open source code,
# please support Adafruit and open-source hardware by purchasing
# products from Adafruit!
import board
import neopixel
from analogio import AnalogIn
# pylint: disable=global-statement
try:
import urandom as random
except ImportError:
import random
# /\ -> Fire-like effect is the sum_total of multiple triangle
# ____/ \____ waves in motion, with a 'warm' color map applied.
n_horns = 1 # number of horns
led_pin = board.D0 # which pin your pixels are connected to
n_leds = 30 # number of LEDs per horn
frames_per_second = 50 # animation frames per second
brightness = 0 # current wave height
fade = 0 # Decreases brightness as wave moves
pixels = neopixel.NeoPixel(led_pin, n_leds, brightness=1, auto_write=False)
offset = 0
# Coordinate space for waves is 16x the pixel spacing,
# allowing fixed-point math to be used instead of floats.
lower = 0 # lower bound of wave
upper = 1 # upper bound of wave
mid = 2 # midpoint (peak) ((lower+upper)/2)
vlower = 3 # velocity of lower bound
vupper = 4 # velocity of upper bound
intensity = 5 # brightness at peak
y = 0
brightness = 0
count = 0
# initialize 3D list
wave = [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6
# Number of simultaneous waves (per horn)
n_waves = len(wave)
# Gamma-correction table
gamma = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110,
112, 114, 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133,
135, 137, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
160, 162, 164, 167, 169, 171, 173, 175, 177, 180, 182, 184, 186,
189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, 215, 218,
220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252,
255
]
def random_wave(he, wi):
wave[he][wi][upper] = -1 # Always start below head of strip
wave[he][wi][lower] = -16 * (3 + random.randint(0,4)) # Lower end starts ~3-7 pixels back
wave[he][wi][mid] = (wave[he][wi][lower]+ wave[he][wi][upper]) / 2
wave[he][wi][vlower] = 3 + random.randint(0,4) # Lower end moves at ~1/8 to 1/pixels
wave[he][wi][vupper] = wave[he][wi][vlower]+ random.randint(0,4) # Upper end moves a bit faster
wave[he][wi][intensity] = 300 + random.randint(0,600)
def setup():
global fade
# Random number generator is seeded from an unused 'floating'
# analog input - this helps ensure the random color choices
# aren't always the same order.
pin = AnalogIn(board.A0)
random.seed(pin.value)
pin.deinit()
for he in range(n_horns):
for wi in range(n_waves):
random_wave(he, wi)
fade = 233 + n_leds / 2
if fade > 233:
fade = 233
setup()
while True:
h = w = i = r = g = b = 0
x = 0
for h in range(n_horns): # For each horn...
x = 7
sum_total = 0
for i in range(n_leds): # For each LED along horn...
x += 16
for w in range(n_waves): # For each wave of horn...
if (x < wave[h][w][lower]) or (x > wave[h][w][upper]):
continue # Out of range
if x <= wave[h][w][mid]: # Lower half of wave (ramping up peak brightness)
sum_top = wave[h][w][intensity] * (x - wave[h][w][lower])
sum_bottom = (wave[h][w][mid] - wave[h][w][lower])
sum_total += sum_top / sum_bottom
else: # Upper half of wave (ramping down from peak)
sum_top = wave[h][w][intensity] * (wave[h][w][upper] - x)
sum_bottom = (wave[h][w][upper] - wave[h][w][mid])
sum_total += sum_top / sum_bottom
sum_total = int(sum_total) # convert from decimal to whole number
# Now the magnitude (sum_total) is remapped to color for the LEDs.
# A blackbody palette is used - fades white-yellow-red-black.
if sum_total < 255: # 0-254 = black to red-1
r = gamma[sum_total]
g = b = 0
elif sum_total < 510: # 255-509 = red to yellow-1
r = 255
g = gamma[sum_total - 255]
b = 0
elif sum_total < 765: # 510-764 = yellow to white-1
r = g = 255
b = gamma[sum_total - 510]
else: # 765+ = white
r = g = b = 255
pixels[i] = (r, g, b)
for w in range(n_waves): # Update wave positions for each horn
wave[h][w][lower] += wave[h][w][vlower] # Advance lower position
if wave[h][w][lower] >= (n_leds * 16): # Off end of strip?
random_wave(h, w) # Yes, 'reboot' wave
else: # No, adjust other values...
wave[h][w][upper] += wave[h][w][vupper]
wave[h][w][mid] = (wave[h][w][lower] + wave[h][w][upper]) / 2
wave[h][w][intensity] = (wave[h][w][intensity] * fade) / 256 # Dimmer
pixels.show()

View file

@ -1,161 +0,0 @@
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// Adafruit Trinket+NeoPixel animation for Daft Punk-inspired helmet.
// Contains some ATtiny85-specific stuff; won't run as-is on Uno, etc.
// Operates in HSV (hue, saturation, value) colorspace rather than RGB.
// Animation is an interference pattern between two waves; one controls
// saturation, the other controls value (brightness). The wavelength,
// direction, speed and type (square vs triangle wave) for each is randomly
// selected every few seconds. Hue is always linear, but other parameters
// are similarly randomized.
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
// GLOBAL STUFF --------------------------------------------------------------
#define N_LEDS 29
#define PIN 0
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_LEDS, PIN);
volatile uint16_t count = 1; // Countdown to next animation change
extern const uint8_t gamma[]; // Big table at end of this code
volatile struct {
uint8_t type, // 0 = square wave, 1 = triangle wave
value[2]; // 0 = start-of-frame value, 1 = pixel-to-pixel value
int8_t inc[2]; // 0 = frame-to-frame increment, 1 = pixel-to-pixel inc
} wave[3]; // 0 = Hue, 1 = Saturation, 2 = Value (brightness)
#define WAVE_H 0 // Array indices for wave[]
#define WAVE_S 1
#define WAVE_V 2
#define FRAME 0 // Array indices for value[] and inc[]
#define PIXEL 1
// INITIALIZATION ------------------------------------------------------------
void setup() {
pixels.begin();
randomSeed(analogRead(0)); // Seed random() from a floating pin (D2)
// Timer/Counter 1 is used to generate a steady ~50 Hz frame rate.
#if F_CPU == 16000000L
clock_prescale_set(clock_div_1);
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS12); // 1:2048 prescale
OCR1C = F_CPU / 2048 / 50 - 1;
#else
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS11) | _BV(CS10); // 1:1024
OCR1C = F_CPU / 1024 / 50 - 1;
#endif
GTCCR = 0; // No PWM out
TIMSK |= _BV(TOIE1); // Enable overflow interrupt
}
void loop() { } // Not used here -- everything's in interrupt below
// 50 HZ LOOP ----------------------------------------------------------------
ISR(TIMER1_OVF_vect) {
uint8_t w, i, n, s, v, r, g, b;
uint16_t v1, s1;
if(!(--count)) { // Time for new animation?
count = 250 + random(250); // New effect will run for 5-10 sec.
for(w=0; w<3; w++) { // Three waves (H,S,V)...
wave[w].type = random(2); // Assign random type (square/triangle)
for(i=0; i<2; i++) { // For frame and pixel increments...
while(!(wave[w].inc[i] = random(15) - 7)); // Set non-zero random
// wave value is never initialized; it's allowed to carry over
}
wave[w].value[PIXEL] = wave[w].value[FRAME];
}
wave[WAVE_S].inc[PIXEL] *= 16; // Make saturation & value
wave[WAVE_V].inc[PIXEL] *= 16; // blinkier along strip
} else { // Continue current animation; update waves
for(w=0; w<3; w++) {
wave[w].value[FRAME] += wave[w].inc[FRAME]; // OK if this wraps!
wave[w].value[PIXEL] = wave[w].value[FRAME];
}
}
// Render current animation frame. COGNITIVE HAZARD: fixed point math.
for(i=0; i<N_LEDS; i++) { // For each LED along strip...
// Coarse (8-bit) HSV-to-RGB conversion, hue first:
n = (wave[WAVE_H].value[PIXEL] % 43) * 6; // Angle within sextant; 0-255
switch(wave[WAVE_H].value[PIXEL] / 43) { // Sextant number; 0-5
case 0 : r = 255 ; g = n ; b = 0 ; break; // R to Y
case 1 : r = 254 - n; g = 255 ; b = 0 ; break; // Y to G
case 2 : r = 0 ; g = 255 ; b = n ; break; // G to C
case 3 : r = 0 ; g = 254 - n; b = 255 ; break; // C to B
case 4 : r = n ; g = 0 ; b = 255 ; break; // B to M
default: r = 255 ; g = 0 ; b = 254 - n; break; // M to R
}
// Saturation = 1-256 to allow >>8 instead of /255
s = wave[WAVE_S].value[PIXEL];
if(wave[WAVE_S].type) { // Triangle wave?
if(s & 0x80) { // Downslope
s = (s & 0x7F) << 1;
s1 = 256 - s;
} else { // Upslope
s <<= 1;
s1 = 1 + s;
s = 255 - s;
}
} else { // Square wave
if(s & 0x80) { // 100% saturation
s1 = 256;
s = 0;
} else { // 0% saturation (white)
s1 = 1;
s = 255;
}
}
// Value (brightness) = 1-256 for similar reasons
v = wave[WAVE_V].value[PIXEL];
v1 = (wave[WAVE_V].type) ? // Triangle wave?
((v & 0x80) ? 64 - ((v & 0x7F) << 1) : // Downslope
1 + ( v << 1) ) : // Upslope
((v & 0x80) ? 256 : 1); // Square wave; on/off
pixels.setPixelColor(i,
pgm_read_byte(&gamma[((((r * s1) >> 8) + s) * v1) >> 8]),
pgm_read_byte(&gamma[((((g * s1) >> 8) + s) * v1) >> 8]),
pgm_read_byte(&gamma[((((b * s1) >> 8) + s) * v1) >> 8]));
// Update wave values along length of strip (values may wrap, is OK!)
for(w=0; w<3; w++) wave[w].value[PIXEL] += wave[w].inc[PIXEL];
}
pixels.show();
}
// Gamma correction improves appearance of midrange colors.
// This table is positioned down here because it's a big annoying
// distraction. The 'extern' near the top lets us reference it earlier.
const uint8_t gamma[] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };

View file

@ -1,193 +0,0 @@
# SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Adafruit Trinket+NeoPixel animation for Daft Punk-inspired helmet.
# Contains some ATtiny85-specific stuff; won't run as-is on Uno, etc.
# Operates in HSV (hue, saturation, value) colorspace rather than RGB.
# Animation is an interference pattern between two waves; one controls
# saturation, the other controls value (brightness). The wavelength,
# direction, speed and type (square vs triangle wave) for each is randomly
# selected every few seconds. Hue is always linear, but other parameters
# are similarly randomized.
import random
import board
import neopixel
from analogio import AnalogIn
n_leds = 29 # number of LEDs per horn
led_pin = board.D0 # which pin your pixels are connected to
# initialize neopixel strip
pixels = neopixel.NeoPixel(led_pin, n_leds, brightness=1, auto_write=False)
count = 1 # countdown to next animation change
# Gamma-correction table
gamma = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110,
112, 114, 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133,
135, 137, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
160, 162, 164, 167, 169, 171, 173, 175, 177, 180, 182, 184, 186,
189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, 215, 218,
220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252,
255
]
# initialize 3D list
wave = [0] * 5, [0] * 5, [0] * 5
wave_type = 0 # 0 = square wave, 1 = triangle wave
value_frame = 1 # start-of-frame value
value_pixel = 2 # pixel-to-pixel value
inc_frame = 3 # frame-to-frame increment
inc_pixel = 4 # pixel-to-pixel inc
wave_h = 0 # hue
wave_s = 1 # saturation
wave_v = 2 # brightness
# Random number generator is seeded from an unused 'floating'
# analog input - this helps ensure the random color choices
# aren't always the same order.
pin = AnalogIn(board.A0)
random.seed(pin.value)
pin.deinit()
# generate a non-zero random number for frame and pixel increments
def nz_random():
random_number = 0
while random_number <= 0:
random_number = random.randint(0,15) - 7
return random_number
while True:
w = i = n = s = v = r = g = b = v1 = s1 = 0
if count <= 0: # time for new animation
count = 250 + random.randint(0,250) # effect run for 5-10 sec.
for w in range(3): # three waves (H,S,V)
wave[w][wave_type] = random.randint(0,2)# square vs triangle
wave[w][inc_frame] = nz_random() # frame increment
wave[w][inc_pixel] = nz_random() # pixel increment
wave[w][value_pixel] = wave[w][value_frame]
wave[wave_s][inc_pixel] *= 16 # make saturation & value
wave[wave_v][inc_pixel] *= 16 # blinkier along strip
else: # continue animation
count -= 1
for w in range(3):
wave[w][value_frame] += wave[w][inc_frame]
wave[w][value_pixel] = wave[w][value_frame]
# Render current animation frame. COGNITIVE HAZARD: fixed point math.
for i in range(n_leds): # for each LED along strip...
# Coarse (8-bit) HSV-to-RGB conversion, hue first:
n = (wave[wave_h][value_pixel] % 43) * 6 # angle within sextant
sextant = wave[wave_h][value_pixel] / 43 # sextant number 0-5
# R to Y
if sextant == 0:
r = 255
g = n
b = 0
# Y to G
elif sextant == 1:
r = 254 - n
g = 255
b = 0
# G to C
elif sextant == 2:
r = 0
g = 255
b = n
# C to B
elif sextant == 3:
r = 0
g = 254 - n
b = 255
# B to M
elif sextant == 4:
r = n
g = 0
b = 255
# M to R
else:
r = 255
g = 0
b = 254 - n
# Saturation = 1-256 to allow >>8 instead of /255
s = wave[wave_s][value_pixel]
if wave[wave_s][wave_type]: # triangle wave?
if s & 0x80: # downslope
s = (s & 0x7F) << 1
s1 = 256 - s
else: # upslope
s = s<<1
s1 = 1 + s
s = 255 - s
else:
if s & 0x80: # square wave
s1 = 256 # 100% saturation
s = 0
else: # 0% saturation
s1 = 1
s = 255
# Value (brightness) = 1-256 for similar reasons
v = wave[wave_v][value_pixel]
# value (brightness) = 1-256 for similar reasons
if wave[wave_v][wave_type]: # triangle wave?
if v & 0x80: # downslope
v1 = 64 - ((v & 0x7F) << 1)
else: # upslope
v1 = 1 + (v << 1)
else:
if v & 0x80: # square wave; on/off
v1 = 256
else:
v1 = 1
# gamma rgb values
gr = ((((r * s1) >> 8) + s) * v1) >> 8
gg = ((((g * s1) >> 8) + s) * v1) >> 8
gb = ((((b * s1) >> 8) + s) * v1) >> 8
# gamma rgb indices range check
if -256 < gr < 256:
r = gamma[gr]
if -256 < gg < 256:
g = gamma[gg]
if -256 < gb < 256:
b = gamma[gb]
pixels[i] = (r, g, b)
# update wave values along length of strip (values may wrap, is OK!)
for w in range(3):
wave[w][value_pixel] += wave[w][inc_pixel]
pixels.show()

View file

@ -1,4 +0,0 @@
# 3D Printed Daft Punk Helmet
Code to accompany this tutorial:
https://learn.adafruit.com/3d-printed-daft-punk-helmet

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,59 +0,0 @@
// SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN 4
// Color Segments
#define APIXELS 14 // number of first orange pixels
#define BPIXELS 84 // number of blue pixels
#define CPIXELS 93 // second orange pixels
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(93, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 10; // delay for half a second
void setup() {
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// End of trinket special code
pixels.begin(); // This initializes the NeoPixel library.
}
void loop() {
// For the first 14 pixels, make them orange, starting from pixel number 0.
for(int i=0;i<APIXELS;i++){
pixels.setPixelColor(i, pixels.Color(255,50,0)); // Set Pixels to Orange Color
pixels.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}
// Fill up 84 pixels with blue, starting with pixel number 14.
for(int i=14;i<BPIXELS;i++){
pixels.setPixelColor(i, pixels.Color(0,250,200)); // Set Pixels to Blue Color
pixels.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}
// Fill up 9 pixels with orange, starting from pixel number 84.
for(int i=84;i<CPIXELS;i++){
pixels.setPixelColor(i, pixels.Color(250,50,0)); //Set Pixels to Orange Color
pixels.show(); // This sends the updated pixel color to the hardware.
delay(delayval); // Delay for a period of time (in milliseconds).
}
}

View file

@ -1,4 +0,0 @@
# 3D_Printed_Guardian_Sword
Code to accompany this tutorial:
https://learn.adafruit.com/breath-of-the-wild-guardian-sword-led-3d-printed

View file

@ -1,54 +0,0 @@
# SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# 3D_Printed_Guardian_Sword
# https://learn.adafruit.com/breath-of-the-wild-guardian-sword-led-3d-printed
import time
import board
import neopixel
pin = board.D4 # DIGITAL IO pin for NeoPixel OUTPUT from GEMMA
pixel_count = 93 # number of neopixels
delayval = .01 # 10 ms delay
APIXELS = 14 # number of first orange pixels
BPIXELS = 84 # number of blue pixels
CPIXELS = 93 # second orange pixels
# initialize neopixels
pixels = neopixel.NeoPixel(pin, pixel_count, brightness=1, auto_write=False)
while True:
# For the first 14 pixels, make them orange,
# starting from pixel number 0.
for i in range(0, APIXELS):
# Set Pixels to Orange Color
pixels[i] = (255, 50, 0)
# This sends the updated pixel color to the hardware.
pixels.write()
# Delay for a period of time (in milliseconds).
time.sleep(delayval)
# Fill up 84 pixels with blue,
# starting with pixel number 14.
for i in range(APIXELS, BPIXELS):
# Set Pixels to Orange Color
pixels[i] = (0, 250, 200)
# This sends the updated pixel color to the hardware.
pixels.write()
# Delay for a period of time (in milliseconds).
time.sleep(delayval)
# Fill up 9 pixels with orange,
# starting from pixel number 84.
for i in range(BPIXELS, CPIXELS):
# Set Pixels to Orange Color
pixels[i] = (250, 50, 0)
# This sends the updated pixel color to the hardware.
pixels.write()
# Delay for a period of time (in milliseconds).
time.sleep(delayval)

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -1,94 +0,0 @@
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
// Trinket/Gemma + LED matrix backpack jewelry. Plays animated
// sequence on LED matrix. Press reset button to display again,
// or add optional momentary button between pin #1 and +V.
// THERE IS NO ANIMATION DATA IN THIS SOURCE FILE, you should
// rarely need to change anything here. EDIT anim.h INSTEAD.
#define BRIGHTNESS 12 // 0=min, 15=max
#define I2C_ADDR 0x70 // Edit if backpack A0/A1 jumpers set
#include <TinyWireM.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include "bmo.h" // Animation data is located here
static const uint8_t PROGMEM reorder[] = { // Column-reordering table
0x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78,
0x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c,
0x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a,
0x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e,
0x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79,
0x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d,
0x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b,
0x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f,
0x80,0xc0,0xa0,0xe0,0x90,0xd0,0xb0,0xf0,0x88,0xc8,0xa8,0xe8,0x98,0xd8,0xb8,0xf8,
0x84,0xc4,0xa4,0xe4,0x94,0xd4,0xb4,0xf4,0x8c,0xcc,0xac,0xec,0x9c,0xdc,0xbc,0xfc,
0x82,0xc2,0xa2,0xe2,0x92,0xd2,0xb2,0xf2,0x8a,0xca,0xaa,0xea,0x9a,0xda,0xba,0xfa,
0x86,0xc6,0xa6,0xe6,0x96,0xd6,0xb6,0xf6,0x8e,0xce,0xae,0xee,0x9e,0xde,0xbe,0xfe,
0x81,0xc1,0xa1,0xe1,0x91,0xd1,0xb1,0xf1,0x89,0xc9,0xa9,0xe9,0x99,0xd9,0xb9,0xf9,
0x85,0xc5,0xa5,0xe5,0x95,0xd5,0xb5,0xf5,0x8d,0xcd,0xad,0xed,0x9d,0xdd,0xbd,0xfd,
0x83,0xc3,0xa3,0xe3,0x93,0xd3,0xb3,0xf3,0x8b,0xcb,0xab,0xeb,0x9b,0xdb,0xbb,0xfb,
0x87,0xc7,0xa7,0xe7,0x97,0xd7,0xb7,0xf7,0x8f,0xcf,0xaf,0xef,0x9f,0xdf,0xbf,0xff };
void ledCmd(uint8_t x) { // Issue command to LED backback driver
TinyWireM.beginTransmission(I2C_ADDR);
TinyWireM.write(x);
TinyWireM.endTransmission();
}
void clear(void) { // Clear display buffer
TinyWireM.beginTransmission(I2C_ADDR);
for(uint8_t i=0; i<17; i++) TinyWireM.write(0);
TinyWireM.endTransmission();
}
void setup() {
power_timer1_disable(); // Disable unused peripherals
power_adc_disable(); // to save power
PCMSK |= _BV(PCINT1); // Set change mask for pin 1
TinyWireM.begin(); // I2C init
clear(); // Blank display
ledCmd(0x21); // Turn on oscillator
ledCmd(0xE0 | BRIGHTNESS); // Set brightness
ledCmd(0x81); // Display on, no blink
}
uint8_t rep = REPS;
void loop() {
for(int i=0; i<sizeof(anim); i) { // For each frame...
TinyWireM.beginTransmission(I2C_ADDR);
TinyWireM.write(0); // Start address
for(uint8_t j=0; j<8; j++) { // 8 rows...
TinyWireM.write(pgm_read_byte(&reorder[pgm_read_byte(&anim[i++])]));
TinyWireM.write(0);
}
TinyWireM.endTransmission();
delay(pgm_read_byte(&anim[i++]) * 10);
}
if(!--rep) { // If last cycle...
ledCmd(0x20); // LED matrix in standby mode
GIMSK = _BV(PCIE); // Enable pin change interrupt
power_all_disable(); // All peripherals off
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei(); // Keep interrupts disabled
sleep_mode(); // Power down CPU (pin 1 will wake)
// Execution resumes here on wake.
GIMSK = 0; // Disable pin change interrupt
rep = REPS; // Reset animation counter
power_timer0_enable(); // Re-enable timer
power_usi_enable(); // Re-enable USI
TinyWireM.begin(); // Re-init I2C
clear(); // Blank display
ledCmd(0x21); // Re-enable matrix
}
}
ISR(PCINT0_vect) {} // Button tap

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View file

@ -1,4 +0,0 @@
# 3D Printed LED-Animation BMO
Code to accompany this Adafruit tutorial:
https://learn.adafruit.com/3d-printed-led-animation-bmo/overview

View file

@ -1,99 +0,0 @@
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
// Animation data for Trinket/Gemma + LED matrix backpack jewelry.
#define REPS 255 // Number of times to repeat the animation loop (1-255)
const uint8_t PROGMEM anim[] = {
B11111111, // 1 frame
B10011001,
B10011001,
B11111111,
B10000001,
B11000011,
B11100111,
B11111111,
25, // 0.25 second delay
B11111111, // 2 frame
B10011001,
B10011001,
B11111111,
B10111101,
B10111101,
B11000011,
B11111111,
25, // 0.25 second delay
B11111111, // 3 frame
B10011001,
B10011001,
B11111111,
B10000001,
B11000011,
B11100111,
B11111111,
25, // 0.25 second delay
B11111111, // 4 frame
B10011001,
B10011001,
B11111111,
B10111101,
B10111101,
B11000011,
B11111111,
25, // 0.25 second delay
B11111111, // 5 frame
B10011001,
B10011001,
B11111111,
B11111111,
B11111111,
B10000001,
B11111111,
25, // 0.25 second delay
B11111111, // 6 frame
B10011001,
B10011001,
B11111111,
B11100111,
B11011011,
B11100111,
B11111111,
25, // 0.25 second delay
B11111111, // 7 frame
B10111101,
B00011000,
B10111101,
B11100111,
B11011011,
B11100111,
B11111111,
25, // 0.25 second delay
B11111111, // 8 frame
B11111111,
B00011000,
B11111111,
B11100111,
B11011011,
B11100111,
B11111111,
25, // 0.25 second delay
B11111111, // 9 frame
B10111101,
B00011000,
B10111101,
B11100111,
B11011011,
B11100111,
B11111111,
25, // 0.25 second delay
};

View file

@ -1,122 +0,0 @@
# SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
# SPDX-FileCopyrightText: 2018 Phil Burgess for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#
# Trinket/Gemma + LED matrix backpack jewelry. Plays animated
# sequence on LED matrix. Press reset button to display again.
import time
import adafruit_ht16k33.matrix
import board
import busio as io
import touchio
touch = touchio.TouchIn(board.D1)
i2c = io.I2C(board.SCL, board.SDA)
matrix = adafruit_ht16k33.matrix.Matrix8x8(i2c)
# pixels initializers
x_pix = y_pix = 8
x = y = 0
matrix.fill(0)
matrix.show()
# seconds to pause between frames
frame_delay = [.25, .25, .25, .25, .25, .25, .25, .25, .25, .25]
# counter for animation frames
frame_count = 0
# repeat entire animation multiple times
reps = 255
rep_count = reps
# animation bitmaps
animation = [
# frame 1
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 2
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 3
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 4
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 1, 1, 1, 0, 1], [1, 0, 1, 1, 1, 1, 0, 1],
[1, 1, 0, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 5
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 6
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 0, 0, 1],
[1, 0, 0, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 7
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 0, 1],
[0, 0, 0, 1, 1, 0, 0, 0], [1, 0, 1, 1, 1, 1, 0, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 8
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
# frame 9
[[1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 1, 1, 1, 1, 0, 1],
[0, 0, 0, 1, 1, 0, 0, 0], [1, 0, 1, 1, 1, 1, 0, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]],
]
#
# run until we are out of animation frames
# use Gemma's built-in reset button or switch to restart
#
# populate matrix
while True:
if frame_count < len(animation) and rep_count >= 0:
for x in range(x_pix):
for y in range(y_pix):
matrix.pixel(x, y, animation[frame_count][x][y])
# next animation frame
frame_count += 1
# show animation
matrix.show()
# pause for effect
time.sleep(frame_delay[frame_count])
else:
matrix.fill(0)
matrix.show()
time.sleep(.1)
# track repitions
rep_count -= 1
# play it again
frame_count = 0
# A0/D1 pin has been touched
# reset animation
if touch.value:
frame_count = 0
rep_count = reps

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,132 +0,0 @@
// SPDX-FileCopyrightText: 2017 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// Fiery demon horns (rawr!) for Adafruit Trinket/Gemma.
// Adafruit invests time and resources providing this open source code,
// please support Adafruit and open-source hardware by purchasing
// products from Adafruit!
#include <Adafruit_NeoPixel.h>
#include <avr/power.h>
#define N_HORNS 1
#define N_LEDS 30 // Per horn
#define PIN 0
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(N_HORNS * N_LEDS, PIN);
// /\ -> Fire-like effect is the sum of multiple triangle
// ____/ \____ waves in motion, with a 'warm' color map applied.
#define N_WAVES 6 // Number of simultaneous waves (per horn)
// Coordinate space for waves is 16x the pixel spacing,
// allowing fixed-point math to be used instead of floats.
struct {
int16_t lower; // Lower bound of wave
int16_t upper; // Upper bound of wave
int16_t mid; // Midpoint (peak) ((lower+upper)/2)
uint8_t vlower; // Velocity of lower bound
uint8_t vupper; // Velocity of upper bound
uint16_t intensity; // Brightness at peak
} wave[N_HORNS][N_WAVES];
long fade; // Decreases brightness as wave moves
// Gamma correction improves appearance of midrange colors
const uint8_t gamma[] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
static void random_wave(uint8_t h,uint8_t w) { // Randomize one wave struct
wave[h][w].upper = -1; // Always start just below head of strip
wave[h][w].lower = -16 * (3 + random(4)); // Lower end starts ~3-7 pixels back
wave[h][w].mid = (wave[h][w].lower + wave[h][w].upper) / 2;
wave[h][w].vlower = 3 + random(4); // Lower end moves at ~1/8 to 1/4 pixel/frame
wave[h][w].vupper = wave[h][w].vlower + random(4); // Upper end moves a bit faster, spreading wave
wave[h][w].intensity = 300 + random(600);
}
void setup() {
uint8_t h, w;
randomSeed(analogRead(1));
pixels.begin();
for(h=0; h<N_HORNS; h++) {
for(w=0; w<N_WAVES; w++) random_wave(h, w);
}
fade = 233 + N_LEDS / 2;
if(fade > 255) fade = 255;
// A ~100 Hz timer interrupt on Timer/Counter1 makes everything run
// at regular intervals, regardless of current amount of motion.
#if F_CPU == 16000000L
clock_prescale_set(clock_div_1);
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS11) | _BV(CS10); // 1:1024 prescale
OCR1C = F_CPU / 1024 / 100 - 1;
#else
TCCR1 = _BV(PWM1A) | _BV(CS13) | _BV(CS11); // 1:512 prescale
OCR1C = F_CPU / 512 / 100 - 1;
#endif
GTCCR = 0; // No PWM out
TIMSK |= _BV(TOIE1); // Enable overflow interrupt
}
void loop() { } // Not used -- everything's in interrupt below
ISR(TIMER1_OVF_vect) {
uint8_t h, w, i, r, g, b;
int16_t x;
uint16_t sum;
for(h=0; h<N_HORNS; h++) { // For each horn...
for(x=7, i=0; i<N_LEDS; i++, x+=16) { // For each LED along horn...
for(sum=w=0; w<N_WAVES; w++) { // For each wave of horn...
if((x < wave[h][w].lower) || (x > wave[h][w].upper)) continue; // Out of range
if(x <= wave[h][w].mid) { // Lower half of wave (ramping up to peak brightness)
sum += wave[h][w].intensity * (x - wave[h][w].lower) / (wave[h][w].mid - wave[h][w].lower);
} else { // Upper half of wave (ramping down from peak)
sum += wave[h][w].intensity * (wave[h][w].upper - x) / (wave[h][w].upper - wave[h][w].mid);
}
}
// Now the magnitude (sum) is remapped to color for the LEDs.
// A blackbody palette is used - fades white-yellow-red-black.
if(sum < 255) { // 0-254 = black to red-1
r = pgm_read_byte(&gamma[sum]);
g = b = 0;
} else if(sum < 510) { // 255-509 = red to yellow-1
r = 255;
g = pgm_read_byte(&gamma[sum - 255]);
b = 0;
} else if(sum < 765) { // 510-764 = yellow to white-1
r = g = 255;
b = pgm_read_byte(&gamma[sum - 510]);
} else { // 765+ = white
r = g = b = 255;
}
pixels.setPixelColor(h * N_LEDS + i, r, g, b);
}
for(w=0; w<N_WAVES; w++) { // Update wave positions for each horn
wave[h][w].lower += wave[h][w].vlower; // Advance lower position
if(wave[h][w].lower >= (N_LEDS * 16)) { // Off end of strip?
random_wave(h, w); // Yes, 'reboot' wave
} else { // No, adjust other values...
wave[h][w].upper += wave[h][w].vupper;
wave[h][w].mid = (wave[h][w].lower + wave[h][w].upper) / 2;
wave[h][w].intensity = (wave[h][w].intensity * fade) / 256; // Dimmer
}
}
}
pixels.show();
}

View file

@ -1,4 +0,0 @@
# 3D Printed LED Fire Horns
Code to accompany this tutorial:
https://learn.adafruit.com/3d-printed-led-fire-horns/fire-code

View file

@ -1,151 +0,0 @@
# SPDX-FileCopyrightText: 2018 Phil Burgess and Mikey Sklar for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Fiery demon horns (rawr!) for Adafruit Trinket/Gemma.
# Adafruit invests time and resources providing this open source code,
# please support Adafruit and open-source hardware by purchasing
# products from Adafruit!
import board
import neopixel
from analogio import AnalogIn
# pylint: disable=global-statement
try:
import urandom as random
except ImportError:
import random
# /\ -> Fire-like effect is the sum_total of multiple triangle
# ____/ \____ waves in motion, with a 'warm' color map applied.
n_horns = 1 # number of horns
led_pin = board.D0 # which pin your pixels are connected to
n_leds = 30 # number of LEDs per horn
frames_per_second = 50 # animation frames per second
brightness = 0 # current wave height
fade = 0 # Decreases brightness as wave moves
pixels = neopixel.NeoPixel(led_pin, n_leds, brightness=1, auto_write=False)
offset = 0
# Coordinate space for waves is 16x the pixel spacing,
# allowing fixed-point math to be used instead of floats.
lower = 0 # lower bound of wave
upper = 1 # upper bound of wave
mid = 2 # midpoint (peak) ((lower+upper)/2)
vlower = 3 # velocity of lower bound
vupper = 4 # velocity of upper bound
intensity = 5 # brightness at peak
y = 0
brightness = 0
count = 0
# initialize 3D list
wave = [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6, [[0] * 6] * 6
# Number of simultaneous waves (per horn)
n_waves = len(wave)
# Gamma-correction table
gamma = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110,
112, 114, 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133,
135, 137, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158,
160, 162, 164, 167, 169, 171, 173, 175, 177, 180, 182, 184, 186,
189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, 215, 218,
220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252,
255
]
def random_wave(he, wi):
wave[he][wi][upper] = -1 # Always start below head of strip
wave[he][wi][lower] = -16 * (3 + random.randint(0,4)) # Lower end starts ~3-7 pixels back
wave[he][wi][mid] = (wave[he][wi][lower]+ wave[he][wi][upper]) / 2
wave[he][wi][vlower] = 3 + random.randint(0,4) # Lower end moves at ~1/8 to 1/pixels
wave[he][wi][vupper] = wave[he][wi][vlower]+ random.randint(0,4) # Upper end moves a bit faster
wave[he][wi][intensity] = 300 + random.randint(0,600)
def setup():
global fade
# Random number generator is seeded from an unused 'floating'
# analog input - this helps ensure the random color choices
# aren't always the same order.
pin = AnalogIn(board.A0)
random.seed(pin.value)
pin.deinit()
for he in range(n_horns):
for wi in range(n_waves):
random_wave(he, wi)
fade = 233 + n_leds / 2
if fade > 233:
fade = 233
setup()
while True:
h = w = i = r = g = b = 0
x = 0
for h in range(n_horns): # For each horn...
x = 7
sum_total = 0
for i in range(n_leds): # For each LED along horn...
x += 16
for w in range(n_waves): # For each wave of horn...
if (x < wave[h][w][lower]) or (x > wave[h][w][upper]):
continue # Out of range
if x <= wave[h][w][mid]: # Lower half of wave (ramping up peak brightness)
sum_top = wave[h][w][intensity] * (x - wave[h][w][lower])
sum_bottom = (wave[h][w][mid] - wave[h][w][lower])
sum_total += sum_top / sum_bottom
else: # Upper half of wave (ramping down from peak)
sum_top = wave[h][w][intensity] * (wave[h][w][upper] - x)
sum_bottom = (wave[h][w][upper] - wave[h][w][mid])
sum_total += sum_top / sum_bottom
sum_total = int(sum_total) # convert from decimal to whole number
# Now the magnitude (sum_total) is remapped to color for the LEDs.
# A blackbody palette is used - fades white-yellow-red-black.
if sum_total < 255: # 0-254 = black to red-1
r = gamma[sum_total]
g = b = 0
elif sum_total < 510: # 255-509 = red to yellow-1
r = 255
g = gamma[sum_total - 255]
b = 0
elif sum_total < 765: # 510-764 = yellow to white-1
r = g = 255
b = gamma[sum_total - 510]
else: # 765+ = white
r = g = b = 255
pixels[i] = (r, g, b)
for w in range(n_waves): # Update wave positions for each horn
wave[h][w][lower] += wave[h][w][vlower] # Advance lower position
if wave[h][w][lower] >= (n_leds * 16): # Off end of strip?
random_wave(h, w) # Yes, 'reboot' wave
else: # No, adjust other values...
wave[h][w][upper] += wave[h][w][vupper]
wave[h][w][mid] = (wave[h][w][lower] + wave[h][w][upper]) / 2
wave[h][w][intensity] = (wave[h][w][intensity] * fade) / 256 # Dimmer
pixels.show()

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,235 +0,0 @@
// SPDX-FileCopyrightText: 2013 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: BSD-3-Clause
/*
LED VU meter for Arduino and Adafruit NeoPixel LEDs.
Hardware requirements:
- Most Arduino or Arduino-compatible boards (ATmega 328P or better).
- Adafruit Electret Microphone Amplifier (ID: 1063)
- Adafruit Flora RGB Smart Pixels (ID: 1260)
OR
- Adafruit NeoPixel Digital LED strip (ID: 1138)
- Optional: battery for portable use (else power through USB or adapter)
Software requirements:
- Adafruit NeoPixel library
Connections:
- 3.3V to mic amp +
- GND to mic amp -
- Analog pin to microphone output (configurable below)
- Digital pin to LED data input (configurable below)
See notes in setup() regarding 5V vs. 3.3V boards - there may be an
extra connection to make and one line of code to enable or disable.
Written by Adafruit Industries. Distributed under the BSD license.
This paragraph must be included in any redistribution.
fscale function:
Floating Point Autoscale Function V0.1
Written by Paul Badger 2007
Modified from code by Greg Shakar
*/
#include <Adafruit_NeoPixel.h>
#include <math.h>
#define N_PIXELS 16 // Number of pixels in strand
#define MIC_PIN A1 // Microphone is attached to this analog pin
#define LED_PIN 1 // NeoPixel LED strand is connected to this pin
#define SAMPLE_WINDOW 10 // Sample window for average level
#define PEAK_HANG 24 //Time of pause before peak dot falls
#define PEAK_FALL 4 //Rate of falling peak dot
#define INPUT_FLOOR 10 //Lower range of analogRead input
#define INPUT_CEILING 300 //Max range of analogRead input, the lower the value the more sensitive (1023 = max)
byte peak = 16; // Peak level of column; used for falling dots
unsigned int sample;
byte dotCount = 0; //Frame counter for peak dot
byte dotHangCount = 0; //Frame counter for holding peak dot
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup()
{
// This is only needed on 5V Arduinos (Uno, Leonardo, etc.).
// Connect 3.3V to mic AND TO AREF ON ARDUINO and enable this
// line. Audio samples are 'cleaner' at 3.3V.
// COMMENT OUT THIS LINE FOR 3.3V ARDUINOS (FLORA, ETC.):
// analogReference(EXTERNAL);
// Serial.begin(9600);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop()
{
unsigned long startMillis= millis(); // Start of sample window
float peakToPeak = 0; // peak-to-peak level
unsigned int signalMax = 0;
unsigned int signalMin = 1023;
unsigned int c, y;
// collect data for length of sample window (in mS)
while (millis() - startMillis < SAMPLE_WINDOW)
{
sample = analogRead(MIC_PIN);
if (sample < 1024) // toss out spurious readings
{
if (sample > signalMax)
{
signalMax = sample; // save just the max levels
}
else if (sample < signalMin)
{
signalMin = sample; // save just the min levels
}
}
}
peakToPeak = signalMax - signalMin; // max - min = peak-peak amplitude
// Serial.println(peakToPeak);
//Fill the strip with rainbow gradient
for (int i=0;i<=strip.numPixels()-1;i++){
strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
}
//Scale the input logarithmically instead of linearly
c = fscale(INPUT_FLOOR, INPUT_CEILING, strip.numPixels(), 0, peakToPeak, 2);
if(c < peak) {
peak = c; // Keep dot on top
dotHangCount = 0; // make the dot hang before falling
}
if (c <= strip.numPixels()) { // Fill partial column with off pixels
drawLine(strip.numPixels(), strip.numPixels()-c, strip.Color(0, 0, 0));
}
// Set the peak dot to match the rainbow gradient
y = strip.numPixels() - peak;
strip.setPixelColor(y-1,Wheel(map(y,0,strip.numPixels()-1,30,150)));
strip.show();
// Frame based peak dot animation
if(dotHangCount > PEAK_HANG) { //Peak pause length
if(++dotCount >= PEAK_FALL) { //Fall rate
peak++;
dotCount = 0;
}
}
else {
dotHangCount++;
}
}
//Used to draw a line between two points of a given color
void drawLine(uint8_t from, uint8_t to, uint32_t c) {
uint8_t fromTemp;
if (from > to) {
fromTemp = from;
from = to;
to = fromTemp;
}
for(int i=from; i<=to; i++){
strip.setPixelColor(i, c);
}
}
float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
boolean invFlag = 0;
// condition curve parameter
// limit range
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
/*
Serial.println(curve * 100, DEC); // multply by 100 to preserve resolution
Serial.println();
*/
// Check for out of range inputValues
if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
// Zero Refference the values
OriginalRange = originalMax - originalMin;
if (newEnd > newBegin){
NewRange = newEnd - newBegin;
}
else
{
NewRange = newBegin - newEnd;
invFlag = 1;
}
zeroRefCurVal = inputValue - originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float
// Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0){
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else // invert the ranges
{
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

View file

@ -1,4 +0,0 @@
# 3D_Printed_LED_Microphone_Flag
Code to accompany this tutorial:
https://learn.adafruit.com/3d-printed-led-microphone-flag

View file

@ -1,184 +0,0 @@
# SPDX-FileCopyrightText: 2013 Phil Burgess for Adafruit Industries
# SPDX-FileCopyrightText: 2017 Mikey Sklar for Adafruit Industries
#
# SPDX-License-Identifier: BSD-3-Clause
# LED VU meter for Arduino and Adafruit NeoPixel LEDs.
# Hardware requirements:
# - M0 boards
# - Adafruit Electret Microphone Amplifier (ID: 1063)
# - Adafruit Flora RGB Smart Pixels (ID: 1260)
# OR
# - Adafruit NeoPixel Digital LED strip (ID: 1138)
# - Optional: battery for portable use (else power through USB or adapter)
# Software requirements:
# - Adafruit NeoPixel library
# Connections:
# - 3.3V to mic amp +
# - GND to mic amp -
# - Analog pin to microphone output (configurable below)
# - Digital pin to LED data input (configurable below)
# See notes in setup() regarding 5V vs. 3.3V boards - there may be an
# extra connection to make and one line of code to enable or disable.
# Written by Adafruit Industries. Distributed under the BSD license.
# This paragraph must be included in any redistribution.
# fscale function:
# Floating Point Autoscale Function V0.1
# Written by Paul Badger 2007
# Modified fromhere code by Greg Shakar
# Ported to Circuit Python by Mikey Sklar
import time
import board
import neopixel
from rainbowio import colorwheel
from analogio import AnalogIn
n_pixels = 16 # Number of pixels you are using
mic_pin = AnalogIn(board.A1) # Microphone is attached to this analog pin
led_pin = board.D1 # NeoPixel LED strand is connected to this pin
sample_window = .1 # Sample window for average level
peak_hang = 24 # Time of pause before peak dot falls
peak_fall = 4 # Rate of falling peak dot
input_floor = 10 # Lower range of analogRead input
# Max range of analogRead input, the lower the value the more sensitive
# (1023 = max)
input_ceiling = 300
peak = 16 # Peak level of column; used for falling dots
sample = 0
dotcount = 0 # Frame counter for peak dot
dothangcount = 0 # Frame counter for holding peak dot
strip = neopixel.NeoPixel(led_pin, n_pixels, brightness=1, auto_write=False)
def remapRange(value, leftMin, leftMax, rightMin, rightMax):
# this remaps a value fromhere original (left) range to new (right) range
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (int)
valueScaled = int(value - leftMin) / int(leftSpan)
# Convert the 0-1 range into a value in the right range.
return int(rightMin + (valueScaled * rightSpan))
def fscale(originalmin, originalmax, newbegin, newend, inputvalue, curve):
invflag = 0
# condition curve parameter
# limit range
if curve > 10:
curve = 10
if curve < -10:
curve = -10
# - invert and scale -
# this seems more intuitive
# postive numbers give more weight to high end on output
curve = (curve * -.1)
# convert linear scale into lograthimic exponent for other pow function
curve = pow(10, curve)
# Check for out of range inputValues
if inputvalue < originalmin:
inputvalue = originalmin
if inputvalue > originalmax:
inputvalue = originalmax
# Zero Refference the values
originalrange = originalmax - originalmin
if newend > newbegin:
newrange = newend - newbegin
else:
newrange = newbegin - newend
invflag = 1
zerorefcurval = inputvalue - originalmin
# normalize to 0 - 1 float
normalizedcurval = zerorefcurval / originalrange
# Check for originalMin > originalMax
# -the math for all other cases
# i.e. negative numbers seems to work out fine
if originalmin > originalmax:
return 0
if invflag == 0:
rangedvalue = (pow(normalizedcurval, curve) * newrange) + newbegin
else: # invert the ranges
rangedvalue = newbegin - (pow(normalizedcurval, curve) * newrange)
return rangedvalue
def drawLine(fromhere, to):
if fromhere > to:
to, fromhere = fromhere, to
for index in range(fromhere, to):
strip[index] = (0, 0, 0)
while True:
time_start = time.monotonic() # current time used for sample window
peaktopeak = 0 # peak-to-peak level
signalmax = 0
signalmin = 1023
c = 0
y = 0
# collect data for length of sample window (in seconds)
while (time.monotonic() - time_start) < sample_window:
# convert to arduino 10-bit [1024] fromhere 16-bit [65536]
sample = mic_pin.value / 64
if sample < 1024: # toss out spurious readings
if sample > signalmax:
signalmax = sample # save just the max levels
elif sample < signalmin:
signalmin = sample # save just the min levels
peaktopeak = signalmax - signalmin # max - min = peak-peak amplitude
# Fill the strip with rainbow gradient
for i in range(0, len(strip)):
strip[i] = colorwheel(remapRange(i, 0, (n_pixels - 1), 30, 150))
# Scale the input logarithmically instead of linearly
c = fscale(input_floor, input_ceiling, (n_pixels - 1), 0, peaktopeak, 2)
if c < peak:
peak = c # keep dot on top
dothangcount = 0 # make the dot hang before falling
if c <= n_pixels: # fill partial column with off pixels
drawLine(n_pixels, n_pixels - int(c))
# Set the peak dot to match the rainbow gradient
y = n_pixels - peak
strip.fill = (y - 1, colorwheel(remapRange(y, 0, (n_pixels - 1), 30, 150)))
strip.write()
# Frame based peak dot animation
if dothangcount > peak_hang: # Peak pause length
dotcount += 1
if dotcount >= peak_fall: # Fall rate
peak += 1
dotcount = 0
else:
dothangcount += 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,75 +0,0 @@
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
#include <Adafruit_NeoPixel.h>
#define PIN 0
#define NUM_LEDS 24
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, PIN);
uint8_t mode = 0, // Current animation effect
offset = 0; // Position of spinner animation
uint32_t color = 0xFF0000; // Starting color = red
uint32_t prevTime; // Time of last animation mode switch
void setup() {
pixels.begin();
pixels.setBrightness(85); // 1/3 brightness
prevTime = millis(); // Starting time
}
void loop() {
uint8_t i;
uint32_t t;
switch(mode) {
case 0: // Random sparkles - just one LED on at a time!
i = random(NUM_LEDS); // Choose a random pixel
pixels.setPixelColor(i, color); // Set it to current color
pixels.show(); // Refresh LED states
// Set same pixel to "off" color now but DON'T refresh...
// it stays on for now...both this and the next random
// pixel will be refreshed on the next pass.
pixels.setPixelColor(i, 0);
delay(10); // 10 millisecond delay
break;
case 1: // Spinny wheel
// A little trick here: pixels are processed in groups of 8
// (with 2 of 8 on at a time), NeoPixel rings are 24 pixels
// (8*3) and 16 pixels (8*2), so we can issue the same data
// to both rings and it appears correct and contiguous
// (also, the pixel order is different between the two ring
// types, so we get the reversed motion on #2 for free).
for(i=0; i<NUM_LEDS; i++) { // For each LED...
uint32_t c = 0; // Assume pixel will be "off" color
if(((offset + i) & 7) < 2) { // For each 8 pixels, 2 will be...
c = color; // ...assigned the current color
}
pixels.setPixelColor(i, c); // Set color of pixel 'i'
}
pixels.show(); // Refresh LED states
delay(50); // 50 millisecond delay
offset++; // Shift animation by 1 pixel on next frame
if(offset >= 8) offset = 0; // Reset offset every 8 pixels
break;
// More animation modes could be added here!
}
t = millis(); // Current time in milliseconds
if((t - prevTime) > 8000) { // Every 8 seconds...
mode++; // Advance to next animation mode
if(mode > 1) { // End of modes?
mode = 0; // Start over from beginning
color >>= 8; // Next color R->G->B
if(!color) color = 0xFF0000; // Preiodically reset to red
}
pixels.clear(); // Set all pixels to 'off' state
prevTime = t; // Record the time of the last mode change
}
}

View file

@ -1,4 +0,0 @@
# 3D_Printed_NeoPixel_Gas_Mask
Code to accompany this tutorial:
https://learn.adafruit.com/3d-printed-el-wire-laser-neopixel-led-gas-mask

View file

@ -1,62 +0,0 @@
# SPDX-FileCopyrightText: 2017 Phil Burgess for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#
import time
import board
import neopixel
try:
import urandom as random # for v1.0 API support
except ImportError:
import random
numpix = 24 # Number of NeoPixels
pixpin = board.D0 # Pin where NeoPixels are connected
strip = neopixel.NeoPixel(pixpin, numpix, brightness=0.3)
mode = 0 # Current animation effect
offset = 0 # Position of spinner animation
color = [255, 0, 0] # RGB color - red
prevtime = time.monotonic() # Time of last animation mode switch
while True: # Loop forever...
if mode == 0: # Random sparkles - lights just one LED at a time
i = random.randint(0, numpix - 1) # Choose random pixel
strip[i] = color # Set it to current color
strip.write() # Refresh LED states
# Set same pixel to "off" color now but DON'T refresh...
# it stays on for now...bot this and the next random
# pixel will be refreshed on the next pass.
strip[i] = [0, 0, 0]
time.sleep(0.008) # 8 millisecond delay
elif mode == 1: # Spinny wheels
# A little trick here: pixels are processed in groups of 8
# (with 2 of 8 on at a time), NeoPixel rings are 24 pixels
# (8*3) and 16 pixels (8*2), so we can issue the same data
# to both rings and it appears correct and contiguous
# (also, the pixel order is different between the two ring
# types, so we get the reversed motion on #2 for free).
for i in range(numpix): # For each LED...
if ((offset + i) & 7) < 2: # 2 pixels out of 8...
strip[i] = color # are set to current color
else:
strip[i] = [0, 0, 0] # other pixels are off
strip.write() # Refresh LED states
time.sleep(0.04) # 40 millisecond delay
offset += 1 # Shift animation by 1 pixel on next frame
if offset >= 8:
offset = 0
# Additional animation modes could be added here!
t = time.monotonic() # Current time in seconds
if (t - prevtime) >= 8: # Every 8 seconds...
mode += 1 # Advance to next mode
if mode > 1: # End of modes?
mode = 0 # Start over from beginning
# Rotate color R->G->B
color = [color[2], color[0], color[1]]
strip.fill([0, 0, 0]) # Turn off all pixels
prevtime = t # Record time of last mode change

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,323 +0,0 @@
// SPDX-FileCopyrightText: 2014 HerrRausB https://github.com/HerrRausB
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
/******************************************************************************
*
* this file is part of the gemma hoop animator example sketch
*
* it is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* it is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. see the
* GNU Lesser General Public License for more details.
*
* you should have received a copy of the GNU Lesser General Public
* License along with NeoPixel. If not, see
* <http://www.gnu.org/licenses/>.
*
* ----------------------------------------------------------------------------
*
* this is the general implementation of the gemma hoop animator - unless you
* don't like the preset animations or find a major bug, you don't need to
* change anything here
*
* ----------------------------------------------------------------------------
*
* this sketch simply cycles through the action list defined in
* GemmaHoopActiuonList.h. it should run on any arduino compatible µC
* and with all available NeoPixel products - you just have to adjust
* the general settings in GemmaHoopActionList.h.
*
* it hereby loads the individually defined actions one after the other
* and continously steps through these actions according to the action
* speed specified for the respective action.
*
* independently from stepping through the current action, it also changes
* the current color according to the color change interval and the
* respective color selection method (random or spectrum)
* definied for the current action.
*
* each action will continue according to the current action duration
* as defined in the action list. then the next action will be loaded. when
* the last action in the list is reached, it will continue with the first
* action.
*
* ----------------------------------------------------------------------------
*
* the number of actions possible is limited by the RAM of the used µC. shall
* the list be too long, the µC will crash and nothing will go on.
*
* i'd rather like to put the action definitions on a SD card or any external
* storage to get more space for as well more different action implementations
* as an unlimited number of actions per animation including more control
* parameters as for example:
*
* - brightnes control per action
* - speed wipes per action, which would reduce the number
* of actions to be defined for seamless speed changes
*
* as i designed this for the gemma hoops as suggested on adafruit's web page
* there seems to be no suitable way of connecting an external storage device
*
******************************************************************************/
#include <Adafruit_NeoPixel.h>
/******************************************************************************
*
* where the action list is to be declared and all animation actions
* are to be defined:
*
******************************************************************************/
#include "GemmaHoopActionList.h"
/******************************************************************************
*
* general global variables
*
******************************************************************************/
uint32_t color = 0,
color_timer = 0,
action_timer = 0,
action_step_timer = 0;
uint16_t color_idx = 0,
curr_color_interval = 0,
curr_action_step_duration = 0,
curr_action_duration = 0;
uint8_t spectrum_part = 0,
curr_action = 0,
curr_color_gen = COL_RANDOM,
idx = 0,
offset = 0,
number_of_actions = 0,
curr_action_idx = 0,
curr_color_granularity = 1;
/******************************************************************************
*
* general global variables
*
******************************************************************************/
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, PIXEL_OUTPUT);
/******************************************************************************
*
* initializing - note that the action list is declared and initialized
* in GemmaHoopActionList.h!
*
******************************************************************************/
void setup()
{
// fingers corssed, the seeding makes sense to really get random colors...
randomSeed(analogRead(ANALOG_INPUT));
// we need to know, how many actions are defined - shall the there be too
// many actions defined, the RAM will overflow and he µC won't do anything
// --> rather easy diagnosis ;-)
number_of_actions = sizeof (theActionList) / sizeof (actiondesc);
// let's go!
pixels.begin();
pixels.setBrightness(BRIGHTNESS);
nextColor();
pixels.show();
}
/******************************************************************************
*
* where all the magic happens - note that the action list is declared and
* initialized in GemmaHoopActionList.h!
*
******************************************************************************/
void loop()
{
// do we need to load the next action?
if ((millis() - action_timer) > curr_action_duration)
{
curr_action_duration = theActionList[curr_action_idx].action_duration;
curr_action = theActionList[curr_action_idx].action_and_color_gen & 0b00111111;
curr_action_step_duration = theActionList[curr_action_idx].action_step_duration;
curr_color_gen = theActionList[curr_action_idx].action_and_color_gen & 0b11000000;
curr_color_granularity = theActionList[curr_action_idx].color_granularity;
curr_color_interval = theActionList[curr_action_idx].color_interval;
curr_action_idx++;
// take care to rotate the action list!
curr_action_idx %= number_of_actions;
action_timer = millis();
}
// do we need to change to the next color?
if ((millis() - color_timer) > curr_color_interval)
{
nextColor();
color_timer = millis();
}
// do we need to step up the current action?
if ((millis() - action_step_timer) > curr_action_step_duration)
{
switch (curr_action)
{
case ACT_NOP :
{
// rather trivial even tho this will be repeated as long as the
// NOP continues - i could have prevented it from repeating
// unnecessarily, but that would mean more code and less
// space for more actions within the animation
for (int i = 0; i < NUM_PIXELS; i++) pixels.setPixelColor(i,0);
break;
}
case ACT_SIMPLE_RING :
{
// even more trivial - just set the new color, if there is one
for (int i = 0; i < NUM_PIXELS; i++) pixels.setPixelColor(i,color);
break;
}
case ACT_CYCLING_RING_ACLK :
case ACT_CYCLING_RING_CLKW :
{
// spin the ring clockwise or anti clockwise
(curr_action == ACT_CYCLING_RING_ACLK) ? idx++ : idx--;
// prevent overflows or underflows
idx %= NUM_PIXELS;
// set the new color, if there is one
pixels.setPixelColor(idx,color);
break;
}
case ACT_WHEEL_ACLK :
case ACT_WHEEL_CLKW :
{
// switch on / off the appropriate pixels according to
// the current offset
for(idx=0; idx < NUM_PIXELS; idx++)
{
pixels.setPixelColor(idx, ((offset + idx) & 7) < 2 ? color : 0);
}
// advance the offset and thus, spin the wheel
// clockwise or anti clockwise
(curr_action == ACT_WHEEL_CLKW) ? offset++ : offset--;
// prevent overflows or underflows
offset %= NUM_PIXELS;
break;
}
case ACT_SPARKLING_RING :
{
// switch current pixel off
pixels.setPixelColor(idx,0);
// pick a new pixel
idx = random (NUM_PIXELS);
// set new pixel to the current color
pixels.setPixelColor(idx,color);
break;
}
/* for the sake of free RAM we disobey the rules
of consistent coding and leave the following
default :
{
}
*/
}
pixels.show();
action_step_timer = millis();
}
}
void nextColor ()
{
/*
* detailed color generation method selection is obsolete
* as long as there are just two methods
switch (curr_color_gen)
{
case COL_RANDOM :
{
nextRandomColor();
break;
}
case COL_SPECTRUM :
{
nextSpectrumColor();
break;
}
default :
{
}
}
*/
// save some RAM for more animation actions
(curr_color_gen & COL_RANDOM) ? nextRandomColor() : nextSpectrumColor();
}
void nextSpectrumColor ()
{
switch (spectrum_part)
{
case 0 : // spectral wipe from red to blue
{
color = Adafruit_NeoPixel::Color(255-color_idx,color_idx,0);
color_idx += curr_color_granularity;
if (color_idx > 255)
{
spectrum_part = 1;
color_idx = 0;
}
break;
}
case 1 : // spectral wipe from blue to green
{
color = Adafruit_NeoPixel::Color(0,255-color_idx,color_idx);
color_idx += curr_color_granularity;
if (color_idx > 255)
{
spectrum_part = 2;
color_idx = 0;
}
break;
}
case 2 : // spectral wipe from green to red
{
color = Adafruit_NeoPixel::Color(color_idx,0,255-color_idx);
color_idx += curr_color_granularity;
if (color_idx > 255)
{
spectrum_part = 0;
color_idx = 0;
}
break;
}
/* for the sake of free RAM we disobey the rules
of consistent coding and leave the following
default :
{
}
*/
}
}
void nextRandomColor ()
{
color = Adafruit_NeoPixel::Color(random(256/curr_color_granularity) * curr_color_granularity,
// granularity = 1 --> [0 .. 255] * 1 --> 0,1,2,3 ... 255
random(256/curr_color_granularity) * curr_color_granularity,
// granularity = 10 --> [0 .. 25] * 10 --> 0,10,20,30 ... 250
random(256/curr_color_granularity) * curr_color_granularity);
// granularity = 100 --> [0 .. 2] * 100 --> 0,100, 200 (boaring...)
}

View file

@ -1,113 +0,0 @@
// SPDX-FileCopyrightText: 2014 HerrRausB https://github.com/HerrRausB
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
/******************************************************************************
*
* this file is part of the gemma hoop animator example sketch
*
* it is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* it is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. see the
* GNU Lesser General Public License for more details.
*
* you should have received a copy of the GNU Lesser General Public
* License along with NeoPixel. If not, see
* <http://www.gnu.org/licenses/>.
*
* ----------------------------------------------------------------------------
*
* use this file to set up your individual animation actions and
* general settings and then simply recompile the sketch
*
* the number of actions possible is limited by the RAM of the used µC. shall
* the list be too long, the µC will crash and nothing will go on.
*
* ----------------------------------------------------------------------------
*
* AND NOW HAVE FUN! :-)
*
******************************************************************************/
#ifndef _GEMMA_HOOP_ACTIONLIST_H_
#define _GEMMA_HOOP_ACTIONLIST_H_
#include "GemmaHoopDefs.h"
/******************************************************************************
*
* general settings
*
******************************************************************************/
#define PIXEL_OUTPUT 0 // output pin the NeoPixels are connected to
#define ANALOG_INPUT 0 // needed to seed the random generator
#define NUM_PIXELS 16 // total number of NeoPixels
#define BRIGHTNESS 30 // overall brightness of NeoPixels
/******************************************************************************
*
* defining the animation actions by simply initializing the array of actions
* this array variable must be called theActionList !!!
*
* valid actions are:
* ACT_NOP simply do nothing and switch everything off
* ACT_SIMPLE_RING all leds on
* ACT_CYCLING_RING_ACLK anti clockwise cycling colors
* ACT_CYCLING_RING_CLKW clockwise cycling colors acording
* ACT_WHEEL_ACLK anti clockwise spinning wheel
* ACT_WHEEL_CLKW clockwise spinning wheel
* ACT_SPARKLING_RING sparkling effect
*
* valid color options are:
* COL_RANDOM colors will be selected randomly, which might
* be not very sufficient due to well known
* limitations of the random generation algorithm
* COL_SPECTRUM colors will be set as cyclic spectral wipe
* R -> G -> B -> R -> G -> B -> R -> ...
*
******************************************************************************/
actionlist theActionList =
{
// action action name & action step color color change
// duration color generation method duration granularity interval
{ 5000, ACT_SPARKLING_RING | COL_RANDOM, 10, 25, 1000 },
{ 2000, ACT_CYCLING_RING_CLKW | COL_RANDOM, 20, 1, 5 },
{ 5000, ACT_SPARKLING_RING | COL_RANDOM, 10, 25, 1000 },
{ 2000, ACT_CYCLING_RING_ACLK | COL_RANDOM, 20, 1, 5 },
{ 5000, ACT_SPARKLING_RING | COL_RANDOM, 10, 25, 1000 },
{ 2500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 25, 20, 20 },
{ 1000, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 50, 1, 20 },
{ 750, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 75, 1, 20 },
{ 500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 100, 1, 20 },
{ 500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 125, 1, 20 },
{ 500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 150, 1, 50 },
{ 500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 175, 1, 100 },
{ 500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 200, 1, 200 },
{ 750, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 225, 1, 250 },
{ 1000, ACT_CYCLING_RING_CLKW | COL_SPECTRUM, 250, 1, 350 },
{ 30000, ACT_SIMPLE_RING | COL_SPECTRUM, 50, 1, 10 },
{ 2500, ACT_WHEEL_ACLK | COL_SPECTRUM, 10, 1, 10 },
{ 2500, ACT_WHEEL_ACLK | COL_SPECTRUM, 15, 1, 20 },
{ 2000, ACT_WHEEL_ACLK | COL_SPECTRUM, 25, 1, 30 },
{ 1000, ACT_WHEEL_ACLK | COL_SPECTRUM, 50, 1, 40 },
{ 1000, ACT_WHEEL_ACLK | COL_SPECTRUM, 75, 1, 40 },
{ 1000, ACT_WHEEL_ACLK | COL_SPECTRUM, 100, 1, 50 },
{ 500, ACT_WHEEL_ACLK | COL_SPECTRUM, 125, 1, 60 },
{ 500, ACT_WHEEL_CLKW | COL_SPECTRUM, 125, 5, 50 },
{ 1000, ACT_WHEEL_CLKW | COL_SPECTRUM, 100, 10, 40 },
{ 1500, ACT_WHEEL_CLKW | COL_SPECTRUM, 75, 15, 30 },
{ 2000, ACT_WHEEL_CLKW | COL_SPECTRUM, 50, 20, 20 },
{ 2500, ACT_WHEEL_CLKW | COL_SPECTRUM, 25, 25, 10 },
{ 3000, ACT_WHEEL_CLKW | COL_SPECTRUM, 10, 30, 5 },
{ 5000, ACT_SPARKLING_RING | COL_RANDOM, 10, 25, 1000 },
{ 5000, ACT_NOP, 0, 0, 0 }
};
#endif

View file

@ -1,84 +0,0 @@
// SPDX-FileCopyrightText: 2014 HerrRausB https://github.com/HerrRausB
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
/******************************************************************************
*
* this file is part of the gemma hoop animator example sketch
*
* it is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* it is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. see the
* GNU Lesser General Public License for more details.
*
* you should have received a copy of the GNU Lesser General Public
* License along with NeoPixel. If not, see
* <http://www.gnu.org/licenses/>.
*
* ----------------------------------------------------------------------------
*
* these are the general definitions and declarations for the
* gemma hoop animator - unless you don't like the preset animations or
* find a major bug, you don't need to change anything here
*
******************************************************************************/
#ifndef _GEMMA_HOOP_DEFS_H_
#define _GEMMA_HOOP_DEFS_H_
/******************************************************************************
*
* available actions
*
******************************************************************************/
#define ACT_NOP 0b00000000 // all leds off, do nothing
#define ACT_SIMPLE_RING 0b00000001 // all leds on
#define ACT_CYCLING_RING_ACLK 0b00000010 // anti clockwise cycling colors
#define ACT_CYCLING_RING_CLKW 0b00000100 // clockwise cycling colors
#define ACT_WHEEL_ACLK 0b00001000 // anti clockwise spinning wheel
#define ACT_WHEEL_CLKW 0b00010000 // clockwise spinning wheel
#define ACT_SPARKLING_RING 0b00100000 // sparkling effect
/******************************************************************************
*
* available color generation methods
*
******************************************************************************/
#define COL_RANDOM 0b01000000 // colors will be generated randomly
#define COL_SPECTRUM 0b10000000 // colors will be set as cyclic spectral wipe
// R -> G -> B -> R -> ...
/******************************************************************************
*
* specifiyng the action list
*
******************************************************************************/
typedef struct
{
uint16_t action_duration; // the action's overall duration in milliseconds (be careful not
// to use values > 2^16-1 - roughly one minute :-)
uint8_t action_and_color_gen; // the color generation method
uint16_t action_step_duration; // the duration of each action step rsp. the delay of the main
// loop in milliseconds - thus, controls the action speed (be
// careful not to use values > 2^16-1 - roughly one minute :-)
uint8_t color_granularity; // controls the increment of the R, G, and B portions of the
// rsp. color. 1 means the increment is 0,1,2,3,..., 10 means
// the increment is 0,10,20,... don't use values > 255, and note
// that even values > 127 wouldn't make much sense...
uint16_t color_interval; // controls the speed of color changing independently from action
// speed (be careful not to use values > 2^16-1 - roughly one minute :-)
} actiondesc;
typedef actiondesc actionlist[]; // a simple array of actions that will be continously cycled through
// by the sketch's main loop. the number of elemnts is limitted by
// the size of RAM available on the rsp. µC
#endif

View file

@ -1,5 +0,0 @@
# 3D_Printed_NeoPixel_Ring_Hair_Dress
Code to accompany this tutorial:
https://learn.adafruit.com/neopixel-ring-hair-dress

View file

@ -1,315 +0,0 @@
# SPDX-FileCopyrightText: 2014 HerrRausB https://github.com/HerrRausB
# SPDX-FileCopyrightText: 2017 Mikey Sklar for Adafruit Industries
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# 3D_Printed_NeoPixel_Ring_Hair_Dress.py
#
# this was ported to CircuitPython from the 'Gemma Hoop Animator'
#
# https://github.com/HerrRausB/GemmaHoopAnimator
#
# unless you # don't like the preset animations or find a
# major bug, you don't need tochange anything here
#
import time
import board
import neopixel
try:
import urandom as random # for v1.0 API support
except ImportError:
import random
from analogio import AnalogIn
# available actions
ACT_NOP = 0x00 # all leds off, do nothing
ACT_SIMPLE_RING = 0x01 # all leds on
ACT_CYCLING_RING_ACLK = 0x02 # anti clockwise cycling colors
ACT_CYCLING_RING_CLKW = 0x04 # clockwise cycling colors
ACT_WHEEL_ACLK = 0x08 # anti clockwise spinning wheel
ACT_WHEEL_CLKW = 0x10 # clockwise spinning wheel
ACT_SPARKLING_RING = 0x20 # sparkling effect
numpix = 16 # total number of NeoPixels
pixel_output = board.D0 # pin where NeoPixels are connected
analog_input = board.A0 # needed to seed the random generator
strip = neopixel.NeoPixel(pixel_output, numpix,
brightness=.3, auto_write=False)
# available color generation methods
COL_RANDOM = 0x40 # colors will be generated randomly
COL_SPECTRUM = 0x80 # colors will be set as cyclic spectral wipe
# specifiyng the action list
# the action's overall duration in milliseconds (be careful not
action_duration = 0
# to use values > 2^16-1 - roughly one minute :-)
action_and_color_gen = 1 # the color generation method
# the duration of each action step rsp. the delay of the main
action_step_duration = 2
# loop in milliseconds - thus, controls the action speed (be
# careful not to use values > 2^16-1 - roughly one minute :-)
color_granularity = 3 # controls the increment of the R, G, and B
# portions of the rsp. color. 1 means the increment is 0,1,2,3,...,
# 10 means the increment is 0,10,20,... don't use values > 255, and
# note that even values > 127 wouldn't make much sense...
# controls the speed of color changing independently from action
color_interval = 4
# general global variables
color = 0
color_timer = 0
action_timer = 0
action_step_timer = 0
color_idx = 0
curr_color_interval = 0
curr_action_step_duration = 0
curr_action_duration = 0
curr_action = 0
curr_color_gen = COL_RANDOM
idx = 0
offset = 0
number_of_actions = 31
curr_action_idx = 0
curr_color_granularity = 1
spectrum_part = 0
# defining the animation actions by simply initializing the array of actions
# this array variable must be called theactionlist !!!
#
# valid actions are:
# ACT_NOP simply do nothing and switch everything off
# ACT_SIMPLE_RING all leds on
# ACT_CYCLING_RING_ACLK anti clockwise cycling colors
# ACT_CYCLING_RING_CLKW clockwise cycling colors acording
# ACT_WHEEL_ACLK anti clockwise spinning wheel
# ACT_WHEEL_CLKW clockwise spinning wheel
# ACT_SPARKLING_RING sparkling effect
#
# valid color options are:
# COL_RANDOM colors will be selected randomly, which might
# be not very sufficient due to well known
# limitations of the random generation algorithm
# COL_SPECTRUM colors will be set as cyclic spectral wipe
# R -> G -> B -> R -> G -> B -> R -> ...
# action action name & action step color color change
# duration color generation method duration granularity interval
theactionlist = [
[5, ACT_SPARKLING_RING | COL_RANDOM, 0.01, 25, 1],
[2, ACT_CYCLING_RING_CLKW | COL_RANDOM,
0.02, 1, 0.005],
[5, ACT_SPARKLING_RING | COL_RANDOM, 0.01, 25, 1],
[2, ACT_CYCLING_RING_ACLK | COL_RANDOM,
0.02, 1, 0.005],
[5, ACT_SPARKLING_RING | COL_RANDOM, 0.01, 25, 1],
[2.5, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.25, 20, 0.020],
[1, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.50, 1, 0.020],
[.750, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.075, 1, 0.020],
[.500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.100, 1, 0.020],
[.500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.125, 1, 0.020],
[.500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.150, 1, 0.050],
[.500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.175, 1, 0.100],
[.500, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.200, 1, 0.200],
[.750, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.225, 1, 0.250],
[1, ACT_CYCLING_RING_CLKW | COL_SPECTRUM,
0.250, 1, 0.350],
[30, ACT_SIMPLE_RING | COL_SPECTRUM,
0.050, 1, 0.010],
[2.5, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.010, 1, 0.010],
[2.5, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.015, 1, 0.020],
[2, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.025, 1, 0.030],
[1, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.050, 1, 0.040],
[1, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.075, 1, 0.040],
[1, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.100, 1, 0.050],
[.500, ACT_WHEEL_ACLK | COL_SPECTRUM,
0.125, 1, 0.060],
[.500, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.125, 5, 0.050],
[1, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.100, 10, 0.040],
[1.5, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.075, 15, 0.030],
[2, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.050, 20, 0.020],
[2.5, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.025, 25, 0.010],
[3, ACT_WHEEL_CLKW | COL_SPECTRUM,
0.010, 30, 0.005],
[5, ACT_SPARKLING_RING | COL_RANDOM, 0.010, 25, 1],
[5, ACT_NOP, 0, 0, 0]
]
# pylint: disable=global-statement
def nextspectrumcolor():
global spectrum_part, color_idx, curr_color_granularity, color
# spectral wipe from green to red
if spectrum_part == 2:
color = (color_idx, 0, 255-color_idx)
color_idx += curr_color_granularity
if color_idx > 255:
spectrum_part = 0
color_idx = 0
# spectral wipe from blue to green
elif spectrum_part == 1:
color = (0, 255 - color_idx, color_idx)
color_idx += curr_color_granularity
if color_idx > 255:
spectrum_part = 2
color_idx = 0
# spectral wipe from red to blue
elif spectrum_part == 0:
color = (255 - color_idx, color_idx, 0)
color_idx += curr_color_granularity
if color_idx > 255:
spectrum_part = 1
color_idx = 0
def nextrandomcolor():
global color
# granularity = 1 --> [0 .. 255] * 1 --> 0,1,2,3 ... 255
# granularity = 10 --> [0 .. 25] * 10 --> 0,10,20,30 ... 250
# granularity = 100 --> [0 .. 2] * 100 --> 0,100, 200 (boaring...)
random_red = random.randint(0, int(256 / curr_color_granularity))
random_red *= curr_color_granularity
random_green = random.randint(0, int(256 / curr_color_granularity))
random_green *= curr_color_granularity
random_blue = random.randint(0, int(256 / curr_color_granularity))
random_blue *= curr_color_granularity
color = (random_red, random_green, random_blue)
def nextcolor():
# save some RAM for more animation actions
if curr_color_gen & COL_RANDOM:
nextrandomcolor()
else:
nextspectrumcolor()
def setup():
# fingers corssed, the seeding makes sense to really get random colors...
apin = AnalogIn(analog_input)
random.seed(apin.value)
apin.deinit()
# let's go!
nextcolor()
strip.write()
setup()
while True: # Loop forever...
# do we need to load the next action?
if (time.monotonic() - action_timer) > curr_action_duration:
current_action = theactionlist[curr_action_idx]
curr_action_duration = current_action[action_duration]
curr_action = current_action[action_and_color_gen] & 0x3F
curr_action_step_duration = current_action[action_step_duration]
curr_color_gen = current_action[action_and_color_gen] & 0xC0
curr_color_granularity = current_action[color_granularity]
curr_color_interval = current_action[color_interval]
curr_action_idx += 1
# take care to rotate the action list!
curr_action_idx %= number_of_actions
action_timer = time.monotonic()
# do we need to change to the next color?
if (time.monotonic() - color_timer) > curr_color_interval:
nextcolor()
color_timer = time.monotonic()
# do we need to step up the current action?
if (time.monotonic() - action_step_timer) > curr_action_step_duration:
if curr_action:
is_act_cycling = (ACT_CYCLING_RING_ACLK or ACT_CYCLING_RING_CLKW)
if curr_action == ACT_NOP:
# rather trivial even tho this will be repeated as long as the
# NOP continues - i could have prevented it from repeating
# unnecessarily, but that would mean more code and less
# space for more actions within the animation
for i in range(0, numpix):
strip[i] = (0, 0, 0)
elif curr_action == ACT_SIMPLE_RING:
# even more trivial - just set the new color, if there is one
for i in range(0, numpix):
strip[i] = color
elif curr_action == is_act_cycling:
# spin the ring clockwise or anti clockwise
if curr_action == ACT_CYCLING_RING_ACLK:
idx += 1
else:
idx -= 1
# prevent overflows or underflows
idx %= numpix
# set the new color, if there is one
strip[idx] = color
elif curr_action == ACT_WHEEL_ACLK or ACT_WHEEL_CLKW:
# switch on / off the appropriate pixels according to
# the current offset
for idx in range(0, numpix):
if ((offset + idx) & 7) < 2:
strip[idx] = color
else:
strip[idx] = (0, 0, 0)
# advance the offset and thus, spin the wheel
if curr_action == ACT_WHEEL_CLKW:
offset += 1
else:
offset -= 1
# prevent overflows or underflows
offset %= numpix
elif curr_action == ACT_SPARKLING_RING:
# switch current pixel off
strip[idx] = (0, 0, 0)
# pick a new pixel
idx = random.randint(0, numpix)
# set new pixel to the current color
strip[idx] = color
strip.write()
action_step_timer = time.monotonic()

BIN
3D_Printed_Unicorn_Horn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,59 +0,0 @@
// SPDX-FileCopyrightText: 2015 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
#include <Adafruit_NeoPixel.h>
#define PIN 1
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: Avoid connecting on a live circuit...if you must, connect GND first.
void setup() {
strip.begin();
strip.setBrightness(100); //adjust brightness here
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
rainbowCycle(20);
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}

View file

@ -1,4 +0,0 @@
# 3D_Printed_Unicorn_Horn
Code to accompany this tutorial:
https://learn.adafruit.com/3d-printed-unicorn-horn

View file

@ -1,39 +0,0 @@
# SPDX-FileCopyrightText: 2017 Mikey Sklar for Adafruit Industries
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#
import time
import board
import neopixel
from rainbowio import colorwheel
from digitalio import DigitalInOut, Direction
pixpin = board.D1
numpix = 8
led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT
strip = neopixel.NeoPixel(pixpin, numpix, brightness=1, auto_write=True)
def rainbow_cycle(wait):
for j in range(255 * 5):
for i in range(len(strip)):
idx = int((i * 256 / len(strip)) + j)
strip[i] = colorwheel(idx & 255)
time.sleep(wait)
def rainbow(wait):
for j in range(255):
for i in range(len(strip)):
idx = int(i + j)
strip[i] = colorwheel(idx & 255)
time.sleep(wait)
while True:
rainbow_cycle(0.05)

BIN
4x4_MIDI_Messenger.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

View file

@ -1,310 +0,0 @@
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import time
import asyncio
import board
import digitalio
from rainbowio import colorwheel
import keypad
import displayio
import i2cdisplaybus
import busio
import adafruit_seesaw.seesaw
import adafruit_seesaw.neopixel
import adafruit_seesaw.rotaryio
import adafruit_seesaw.digitalio
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
import adafruit_displayio_ssd1306
import adafruit_midi
from adafruit_midi.control_change import ControlChange
import neopixel
# default MIDI channel (1-16)
midi_in_channel = 2
midi_out_channel = 2
# MIDI CC messages, values and names assigned to each encoder
cc_values = [
{'cc_val': (0, 127), 'cc_message': (14), 'cc_name': "Volume"},
{'cc_val': (0, 127), 'cc_message': (15), 'cc_name': "Repeats"},
{'cc_val': (0, 127), 'cc_message': (16), 'cc_name': "Size"},
{'cc_val': (0, 127), 'cc_message': (17), 'cc_name': "Mod"},
{'cc_val': (0, 127), 'cc_message': (18), 'cc_name': "Spread"},
{'cc_val': (0, 127), 'cc_message': (19), 'cc_name': "Scan"},
{'cc_val': (0, 127), 'cc_message': (20), 'cc_name': "Ramp"},
{'cc_val': (1, 3), 'cc_message': (21), 'cc_name': "Mod Number"},
{'cc_val': (1, 3), 'cc_message': (22), 'cc_name': "Mod Bank"},
{'cc_val': (1, 3), 'cc_message': (23), 'cc_name': "Mode"},
{'cc_val': (0, 1), 'cc_message': (102), 'cc_name': "Bypass/Engage"},
{'cc_val': (0, 127), 'cc_message': (93), 'cc_name': "Tap Tempo"},
{'cc_val': (0, 1), 'cc_message': (24), 'cc_name': "Loop (R Hold)"},
{'cc_val': (0, 1), 'cc_message': (25), 'cc_name': "Scan (L Hold)"},
{'cc_val': (0, 127), 'cc_message': (26), 'cc_name': "Clear (Both Hold)"},
{'cc_val': (0, 1), 'cc_message': (51), 'cc_name': "MIDI Clock Ignore"}
]
displayio.release_displays()
oled_reset = board.D13
i2c = board.STEMMA_I2C()
# STEMMA OLED setup
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3D, reset=oled_reset)
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=64)
splash = displayio.Group()
display.root_group = splash
font = bitmap_font.load_font('/OCRA_small.pcf')
# main label/MIDI message name text; centered
main_area = label.Label(
font, text="4x4 MIDI Messenger", color=0xFFFFFF)
main_area.anchor_point = (0.5, 0.0)
main_area.anchored_position = (display.width / 2, 0)
# MIDI message number text
msg_area = label.Label(
font, text="CC Msg: 10", color=0xFFFFFF)
msg_area.anchor_point = (0.0, 0.5)
msg_area.anchored_position = (0, display.height / 2)
# MIDI message value text
val_area = label.Label(
font, text="CC Val: 50", color=0xFFFFFF)
val_area.anchor_point = (0.0, 1.0)
val_area.anchored_position = (0, display.height)
# MIDI message status text
status_area = label.Label(
font, text="Sent!", color=0xFFFFFF)
status_area.anchor_point = (1.0, 1.0)
status_area.anchored_position = (display.width, display.height)
splash.append(main_area)
splash.append(msg_area)
splash.append(val_area)
splash.append(status_area)
# MIDI over UART setup for MIDI FeatherWing
uart = busio.UART(board.TX, board.RX, baudrate=31250, timeout=0.001)
midi = adafruit_midi.MIDI(
midi_in=uart,
midi_out=uart,
in_channel=(midi_in_channel - 1),
out_channel=(midi_out_channel - 1),
debug=False,
)
# quad rotary encoder setup
ss0 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x49)
ss1 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4A)
ss2 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4B)
ss3 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4C)
# button pins for the encoders
pins = [12, 14, 17, 9]
# interrupts for the button pins. pins are passed as a bitmask
ss0.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
ss1.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
ss2.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
ss3.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
# arrays for the encoders and switches
enc0 = []
enc1 = []
enc2 = []
enc3 = []
sw0 = []
sw1 = []
sw2 = []
sw3 = []
# creating encoders and switches, enabling interrupts for encoders
for i in range(4):
enc0.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss0, i))
enc1.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss1, i))
enc2.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss2, i))
enc3.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss3, i))
sw0.append(adafruit_seesaw.digitalio.DigitalIO(ss0, pins[i]))
sw0[i].switch_to_input(digitalio.Pull.UP)
sw1.append(adafruit_seesaw.digitalio.DigitalIO(ss1, pins[i]))
sw1[i].switch_to_input(digitalio.Pull.UP)
sw2.append(adafruit_seesaw.digitalio.DigitalIO(ss2, pins[i]))
sw2[i].switch_to_input(digitalio.Pull.UP)
sw3.append(adafruit_seesaw.digitalio.DigitalIO(ss3, pins[i]))
sw3[i].switch_to_input(digitalio.Pull.UP)
ss0.enable_encoder_interrupt(encoder=i)
ss1.enable_encoder_interrupt(encoder=i)
ss2.enable_encoder_interrupt(encoder=i)
ss3.enable_encoder_interrupt(encoder=i)
# neopixels on each PCB
pix0 = adafruit_seesaw.neopixel.NeoPixel(ss0, 18, 4, auto_write = True)
pix0.brightness = 0.5
pix1 = adafruit_seesaw.neopixel.NeoPixel(ss1, 18, 4, auto_write = True)
pix1.brightness = 0.5
pix2 = adafruit_seesaw.neopixel.NeoPixel(ss2, 18, 4, auto_write = True)
pix2.brightness = 0.5
pix3 = adafruit_seesaw.neopixel.NeoPixel(ss3, 18, 4, auto_write = True)
pix3.brightness = 0.5
# onboard Feather neopixel
pix_feather = neopixel.NeoPixel(board.NEOPIXEL, 1, auto_write = True)
pix_feather.brightness = 0.5
# encoder position arrays
last_pos0 = [60, 60, 60, 60]
last_pos1 = [60, 60, 60, 0]
last_pos2 = [0, 0, 0, 120]
last_pos3 = [0, 0, 0, 0]
pos0 = [60, 60, 60, 60]
pos1 = [60, 60, 60, 0]
pos2 = [0, 0, 0, 120]
pos3 = [0, 0, 0, 0]
# color arrays for the neopixels
c0 = [0, 16, 32, 48]
c1 = [64, 80, 96, 112]
c2 = [128, 144, 160, 176]
c3 = [192, 208, 224, 240]
# setting starting colors for neopixels
for r in range(4):
pix0[r] = colorwheel(c0[r])
pix1[r] = colorwheel(c1[r])
pix2[r] = colorwheel(c2[r])
pix3[r] = colorwheel(c3[r])
# feather neopixel color
c_feather = 0
pix_feather[0] = colorwheel(c_feather)
# array of all 16 encoder positions
encoder_posititions = [60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 120, 0, 0, 0, 0]
class MIDI_Messages:
# tracks sending a message and index 0-15
def __init__(self):
self.send_msg = False
self.midi_index = 0
class NeoPixel_Attributes:
# tracks color, neopixel index and seesaw
def __init__(self):
self.color = c0
self.index = 0
self.strip = pix0
self.feather_color = c_feather
async def send_midi(midi_msg):
# sends MIDI message if send_msg is True/button pressed
while True:
if midi_msg.send_msg is True:
m = midi_msg.midi_index
main_area.text = f"{cc_values[m]['cc_name']}"
msg_area.text = f"CC Msg: {cc_values[m]['cc_message']}"
val_area.text = f"CC Val: {encoder_posititions[m]}"
midi.send(ControlChange(cc_values[m]['cc_message'], encoder_posititions[m]))
status_area.text = "Sent!"
print(f"sending midi: {m}, {encoder_posititions[m]}, {cc_values[m]['cc_message']}")
time.sleep(1)
midi_msg.send_msg = False
else:
status_area.text = " "
await asyncio.sleep(0)
async def rainbows(the_color):
# Updates colors of the neopixels to scroll through rainbow
while True:
the_color.feather_color += 8
the_color.strip[the_color.index] = colorwheel(the_color.color[the_color.index])
pix_feather[0] = colorwheel(the_color.feather_color)
await asyncio.sleep(0)
async def monitor_interrupts(pin0, pin1, pin2, pin3, the_color, midi_msg): #pylint: disable=too-many-statements
# function to keep encoder value pinned between CC value range
def normalize(val, min_v, max_v):
return max(min(max_v, val), min_v)
# read encoder function
def read_encoder(enc_group, pos, last_pos, pix, colors, index_diff):
# check all four encoders if interrupt is detected
for p in range(4):
pos[p] = enc_group[p].position
if pos[p] != last_pos[p]:
main_index = p + index_diff
# update CC value
if pos[p] > last_pos[p]:
colors[p] += 8
encoder_posititions[main_index] = encoder_posititions[main_index] + 1
else:
colors[p] -= 8
encoder_posititions[main_index] = encoder_posititions[main_index] - 1
encoder_posititions[main_index] = normalize(encoder_posititions[main_index],
cc_values[main_index]['cc_val'][0],
cc_values[main_index]['cc_val'][1])
colors[p] = (colors[p] + 256) % 256 # wrap around to 0-256
print(main_index, encoder_posititions[main_index])
main_area.text = f"{cc_values[main_index]['cc_name']}"
msg_area.text = f"CC Msg: {cc_values[main_index]['cc_message']}"
val_area.text = f"CC Val: {encoder_posititions[main_index]}"
last_pos[p] = pos[p]
# update NeoPixel colors
the_color.color = colors
the_color.index = p
the_color.strip = pix
# function to read button press
def press_switches(sw, index):
if not sw[index].value:
# signals that a MIDI message should be sent
midi_msg.send_msg = True
midi_msg.midi_index = index
print(f"button {index} pressed")
# interrupt pins are passed as a keypad
with keypad.Keys(
(pin0, pin1, pin2, pin3,), value_when_pressed=False, pull=True
) as keys:
while True:
key_event = keys.events.get()
if key_event and key_event.pressed:
key_number = key_event.key_number
# seesaw 0
if key_number == 0:
read_encoder(enc0, pos0, last_pos0, pix0, c0, 0)
press_switches(sw0, 0)
press_switches(sw0, 1)
press_switches(sw0, 2)
press_switches(sw0, 3)
# seesaw 1
elif key_number == 1:
read_encoder(enc1, pos1, last_pos1, pix1, c1, 4)
press_switches(sw1, 0)
press_switches(sw1, 1)
press_switches(sw1, 2)
press_switches(sw1, 3)
# update index to 4-7
midi_msg.midi_index = midi_msg.midi_index + 4
# seesaw 2
elif key_number == 2:
read_encoder(enc2, pos2, last_pos2, pix2, c2, 8)
press_switches(sw2, 0)
press_switches(sw2, 1)
press_switches(sw2, 2)
press_switches(sw2, 3)
# update index 8-11
midi_msg.midi_index = midi_msg.midi_index + 8
# seesaw 3
else:
read_encoder(enc3, pos3, last_pos3, pix3, c3, 12)
press_switches(sw3, 0)
press_switches(sw3, 1)
press_switches(sw3, 2)
press_switches(sw3, 3)
# update index 12-15
midi_msg.midi_index = midi_msg.midi_index + 12
# clear interrupt flag to reset interrupt pin
ss0.get_GPIO_interrupt_flag()
ss1.get_GPIO_interrupt_flag()
ss2.get_GPIO_interrupt_flag()
ss3.get_GPIO_interrupt_flag()
await asyncio.sleep(0)
async def main():
the_color = NeoPixel_Attributes()
midi_msg = MIDI_Messages()
# interrupt listener task
interrupt_task = asyncio.create_task(monitor_interrupts(board.D5, board.D6, board.D9,
board.D10, the_color, midi_msg))
# neopixel task
pixels_task = asyncio.create_task(rainbows(the_color))
# midi task
midi_task = asyncio.create_task(send_midi(midi_msg))
await asyncio.gather(interrupt_task, pixels_task, midi_task)
asyncio.run(main())

View file

@ -1,61 +0,0 @@
// SPDX-FileCopyrightText: 2022 Phil B. for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// Example for 5x5 NeoBFF - scrolls a message across the LED matrix.
// Requires Adafruit_GFX, Adafruit_NeoPixel and Adafruit_NeoMatrix libraries.
#include <Adafruit_GFX.h> // Graphics library
#include <Adafruit_NeoPixel.h> // NeoPixel library
#include <Adafruit_NeoMatrix.h> // Bridges GFX and NeoPixel
#include <Fonts/TomThumb.h> // A tiny 3x5 font incl. w/GFX
#define PIN A3
// NeoMatrix declaration for BFF with the power and
// Neo pins at the top (same edge as QT Py USB port):
Adafruit_NeoMatrix matrix(5, 5, PIN,
NEO_MATRIX_TOP + NEO_MATRIX_RIGHT +
NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
NEO_GRB + NEO_KHZ800);
// Message to display, and a set of colors to cycle through. Because
// the matrix is only 5 pixels tall, characters with descenders (e.g.
// lowercase p or y) are best avoided. There are even smaller fonts
// but these get progressively less legible. ALL CAPS helps!
const char message[] = "HELLO BFF";
const uint16_t colors[] = {
matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255) };
uint16_t message_width; // Computed in setup() below
void setup() {
matrix.begin();
matrix.setBrightness(40); // Turn down brightness to about 15%
matrix.setFont(&TomThumb); // Use custom font
matrix.setTextWrap(false); // Allows text to scroll off edges
matrix.setTextColor(colors[0]); // Start with first color in list
// To determine when the message has fully scrolled off the left side,
// get the bounding rectangle of the text. As we only need the width
// value, a couple of throwaway variables are passed to the bounds
// function for the other values:
int16_t d1;
uint16_t d2;
matrix.getTextBounds(message, 0, 0, &d1, &d1, &message_width, &d2);
}
int x = matrix.width(); // Start with message off right edge
int y = matrix.height(); // With custom fonts, y is the baseline, not top
int pass = 0; // Counts through the colors[] array
void loop() {
matrix.fillScreen(0); // Erase message in old position.
matrix.setCursor(x, y); // Set new cursor position,
matrix.print(message); // draw the message
matrix.show(); // and update the matrix.
if(--x < -message_width) { // Move 1 pixel left. Then, if scrolled off left...
x = matrix.width(); // reset position off right edge and
if(++pass >= 3) pass = 0; // increment color in list, rolling over if needed.
matrix.setTextColor(colors[pass]);
}
delay(100); // 1/10 sec pause
}

View file

@ -1,37 +0,0 @@
# SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
import time
import board
import neopixel
from adafruit_display_text.bitmap_label import Label
from adafruit_bitmap_font import bitmap_font
from displayio import Bitmap
from rainbowio import colorwheel
font = bitmap_font.load_font("tom-thumb.pcf", Bitmap)
label = Label(text="Hello World!! Adafruit QT Py RP2040 + NeoPixel BFF ", font=font)
bitmap = label.bitmap
pixels = neopixel.NeoPixel(board.A3, 5*5, brightness=.07, auto_write=False)
pixels.fill(0)
pixels.show()
colors = [0, 0]
hue = 0
while True:
for i in range(bitmap.width):
# Use a rainbow of colors, shifting each column of pixels
hue = hue + 7
if hue >= 256:
hue = hue - 256
colors[1] = colorwheel(hue)
# Scoot the old text left by 1 pixel
pixels[0:20] = pixels[5:25]
# Draw in the next line of text
for y in range(5):
# Select black or color depending on the bitmap pixel
pixels[20+y] = colors[bitmap[i,y]]
pixels.show()
time.sleep(.1)

View file

@ -1,83 +0,0 @@
# SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
import time
import board
import neopixel
import fontio
from adafruit_display_text.bitmap_label import Label
from adafruit_bitmap_font import bitmap_font
from displayio import Bitmap
from rainbowio import colorwheel
tom_thumb = bitmap_font.load_font("tom-thumb.pcf", Bitmap)
_glyph_keys = ['bitmap', 'tile_index', 'width', 'height', 'dx', 'dy', 'shift_x', 'shift_y']
def patch_glyph(base, **kw):
d = {}
for k in _glyph_keys:
d[k] = kw.get(k, getattr(base, k))
return fontio.Glyph(**d)
class PatchedFont:
def __init__(self, base_font, patches):
self.base_font = base_font
self.patches = patches
def get_glyph(self, glyph):
g = self.base_font.get_glyph(glyph)
patch = self.patches.get(glyph)
if patch is not None:
print("patching", repr(chr(glyph)), g)
g = patch_glyph(g, **patch)
print("patched", g)
return g
def get_bounding_box(self):
return self.base_font.get_bounding_box()
font = PatchedFont(tom_thumb,
{
32: {'shift_x': 1, 'dx': 0},
105: {'dx': 0, 'shift_x': 2},
33: {'dx': 0, 'shift_x': 2},
})
label = Label(text=" adafruit! ", font=font)
bitmap = label.bitmap
heart_bitmap = [
0,1,1,0,0,
1,1,1,1,0,
0,1,1,1,1,
1,1,1,1,0,
0,1,1,0,0,
]
pixels = neopixel.NeoPixel(board.A3, 5*5, brightness=.06, auto_write=False)
while True:
for hue in range(0, 255, 3):
color = colorwheel(hue)
pixels[:] = [pixel * color for pixel in heart_bitmap]
pixels.show()
time.sleep(.01)
hue = 0
for i in range(bitmap.width):
# Use a rainbow of colors, shifting each column of pixels
hue = hue + 7
if hue >= 256:
hue = hue - 256
color = colorwheel(hue)
# Scoot the old text left by 1 pixel
pixels[:20] = pixels[5:]
# Draw in the next line of text
for y in range(5):
# Select black or color depending on the bitmap pixel
pixels[20+y] = color * bitmap[i,y]
pixels.show()
time.sleep(.1)

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -1,47 +0,0 @@
// SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include <Adafruit_MCP23X17.h>
#define NOID_1 0 // MCP23XXX pin LED is attached to
#define NOID_2 4 // MCP23XXX pin LED is attached to
Adafruit_MCP23X17 mcp;
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println("8 Channel Solenoid Driver Demo");
if (!mcp.begin_I2C()) {
Serial.println("Couldn't find MCP23017..");
while (1);
}
mcp.pinMode(NOID_1, OUTPUT);
mcp.pinMode(NOID_2, OUTPUT);
Serial.println("Found MCP23017, looping...");
}
void loop() {
Serial.println("Solenoid 1!");
mcp.digitalWrite(NOID_1, HIGH);
delay(500);
mcp.digitalWrite(NOID_1, LOW);
delay(500);
Serial.println("Solenoid 2!");
mcp.digitalWrite(NOID_2, HIGH);
delay(500);
mcp.digitalWrite(NOID_2, LOW);
delay(500);
Serial.println("Together!");
mcp.digitalWrite(NOID_1, HIGH);
mcp.digitalWrite(NOID_2, HIGH);
delay(1000);
mcp.digitalWrite(NOID_1, LOW);
mcp.digitalWrite(NOID_2, LOW);
delay(2000);
Serial.println("Repeat!");
Serial.println();
delay(500);
}

View file

@ -1,38 +0,0 @@
# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import board
from adafruit_mcp230xx.mcp23017 import MCP23017
i2c = board.STEMMA_I2C()
mcp = MCP23017(i2c)
noid_1 = mcp.get_pin(0)
noid_2 = mcp.get_pin(4)
noid_1.switch_to_output(value=False)
noid_2.switch_to_output(value=False)
while True:
noid_1.value = True
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(0.2)
noid_1.value = False
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(0.2)
noid_2.value = True
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(0.2)
noid_2.value = False
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(1)
noid_1.value = True
noid_2.value = True
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(1)
noid_1.value = False
noid_2.value = False
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
time.sleep(2)

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -1,31 +0,0 @@
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
//
// SPDX-License-Identifier: MIT
const int DIR = 5;
const int STEP = 6;
const int microMode = 16; // microstep mode, default is 1/16 so 16; ex: 1/4 would be 4
// full rotation * microstep divider
const int steps = 200 * microMode;
void setup()
{
// setup step and dir pins as outputs
pinMode(STEP, OUTPUT);
pinMode(DIR, OUTPUT);
}
void loop()
{
// change direction every loop
digitalWrite(DIR, !digitalRead(DIR));
// toggle STEP to move
for(int x = 0; x < steps; x++)
{
digitalWrite(STEP, HIGH);
delay(2);
digitalWrite(STEP, LOW);
delay(2);
}
delay(1000); // 1 second delay
}

View file

@ -1,32 +0,0 @@
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import board
from digitalio import DigitalInOut, Direction
# direction and step pins as outputs
DIR = DigitalInOut(board.D5)
DIR.direction = Direction.OUTPUT
STEP = DigitalInOut(board.D6)
STEP.direction = Direction.OUTPUT
# microstep mode, default is 1/16 so 16
# another ex: 1/4 microstep would be 4
microMode = 16
# full rotation multiplied by the microstep divider
steps = 200 * microMode
while True:
# change direction every loop
DIR.value = not DIR.value
# toggle STEP pin to move the motor
for i in range(steps):
STEP.value = True
time.sleep(0.001)
STEP.value = False
time.sleep(0.001)
print("rotated! now reverse")
# 1 second delay before starting again
time.sleep(1)

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -1,2 +0,0 @@
ABC_Soundboards_for_NeoTrellis/code.py 169: Comparison 'currently_playing['voice'] != None' should be 'currently_playing['voice'] is not None' (singleton-comparison)
ABC_Soundboards_for_NeoTrellis/code.py 186: Comparison 'currently_playing['voice'] != None' should be 'currently_playing['voice'] is not None' (singleton-comparison)

Some files were not shown because too many files have changed in this diff Show more