Compare commits
No commits in common. "main" and "folder-images" have entirely different histories.
main
...
folder-ima
46
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -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**
|
||||
26
.github/PULL_REQUEST_TEMPLATE.md
vendored
|
|
@ -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.
|
||||
134
.github/workflows/arduino_cron.yml
vendored
|
|
@ -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."
|
||||
35
.github/workflows/githubci.yml
vendored
|
|
@ -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
|
||||
52
.github/workflows/images.yml
vendored
|
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||
*~
|
||||
Hue_Controller/secrets.h
|
||||
.idea
|
||||
*.DS_Store
|
||||
CircuitPython_Logger/secrets\.py
|
||||
.python-version
|
||||
__pycache__
|
||||
*.swp
|
||||
1
.mailmap
|
|
@ -1 +0,0 @@
|
|||
Anne Barela <mydigitalhome@gmail.com>
|
||||
433
.pylintrc
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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
|
After Width: | Height: | Size: 22 KiB |
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# 3D_Printed_Bionic_Eye
|
||||
|
||||
Code to accompany this Adafruit tutorial:
|
||||
https://learn.adafruit.com/3d-printed-bionic-eye
|
||||
|
|
@ -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)
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
@ -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 };
|
||||
|
|
@ -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()
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# 3D Printed Daft Punk Helmet
|
||||
|
||||
Code to accompany this tutorial:
|
||||
https://learn.adafruit.com/3d-printed-daft-punk-helmet
|
||||
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
BIN
3D_Printed_Guardian_Sword.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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).
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
BIN
3D_Printed_LED-Animation_BMO.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -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
|
||||
|
Before Width: | Height: | Size: 76 KiB |
|
|
@ -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
|
||||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
@ -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
|
||||
BIN
3D_Printed_LED_Fire_Horns.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
BIN
3D_Printed_LED_Microphone_Flag.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# 3D_Printed_LED_Microphone_Flag
|
||||
|
||||
Code to accompany this tutorial:
|
||||
https://learn.adafruit.com/3d-printed-led-microphone-flag
|
||||
|
|
@ -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
|
||||
BIN
3D_Printed_NeoPixel_Gas_Mask.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
BIN
3D_Printed_NeoPixel_Ring_Hair_Dress.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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...)
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# 3D_Printed_NeoPixel_Ring_Hair_Dress
|
||||
|
||||
Code to accompany this tutorial:
|
||||
|
||||
https://learn.adafruit.com/neopixel-ring-hair-dress
|
||||
|
|
@ -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
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# 3D_Printed_Unicorn_Horn
|
||||
|
||||
Code to accompany this tutorial:
|
||||
https://learn.adafruit.com/3d-printed-unicorn-horn
|
||||
|
|
@ -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
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -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())
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
BIN
5x5_NeoPixel_BFF_Examples_CircuitPython_Scrolling_Text.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
5x5_NeoPixel_BFF_Examples_CircuitPython_Store_Demo.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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)
|
||||
BIN
8_Channel_Solenoid_Driver_CircuitPython.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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)
|
||||
BIN
A4988_Examples_CircuitPython_A4988.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
ABC_Soundboards_for_NeoTrellis.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
|
@ -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)
|
||||