Compare commits
2 commits
main
...
pb-macropa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5bf35da48 | ||
|
|
827423399b |
6314 changed files with 76860 additions and 1121007 deletions
134
.github/workflows/arduino_cron.yml
vendored
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."
|
||||
59
.github/workflows/githubci.yml
vendored
59
.github/workflows/githubci.yml
vendored
|
|
@ -1,35 +1,60 @@
|
|||
name: SPDX and Pylint
|
||||
name: Arduino Library CI
|
||||
|
||||
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
|
||||
arduino:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform: ["uno", "nrf52832", "cpx_ada", "pyportal", "protrinket_3v", "protrinket_5v", "metro_m0", "esp8266", "esp32", "trinket_3v", "trinket_5v", "gemma", "flora", "feather32u4", "feather_m0_express", "gemma_m0", "trinket_m0", "hallowing_m0", "monster_m4sk", "hallowing_m4", "hallowing_m4_tinyusb", "neotrellis_m4", "pybadge", "cpb", "cpc", "funhouse", "magtag"]
|
||||
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.8'
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v2
|
||||
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
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
||||
- 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
|
||||
- name: Set up Python 3.6
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: 3.6
|
||||
- name: Versions
|
||||
run: |
|
||||
python3 --version
|
||||
- name: Pip install pylint
|
||||
- name: Pip install pylint, black, & Sphinx
|
||||
run: |
|
||||
pip install --force-reinstall pylint==2.7.1
|
||||
pip install --force-reinstall pylint==1.9.2
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: lint
|
||||
run: ./pylint_check.sh
|
||||
|
|
|
|||
14
.github/workflows/images.yml
vendored
14
.github/workflows/images.yml
vendored
|
|
@ -8,25 +8,24 @@ on:
|
|||
branches: [main]
|
||||
|
||||
concurrency:
|
||||
group: folder-images-concurrency # https://github.com/adafruit/Adafruit_Learning_System_Guides/issues/2327
|
||||
group: folder-images
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update-images:
|
||||
if: github.repository_owner == 'adafruit'
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2.2.0
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: "3.x"
|
||||
python-version: 3.9
|
||||
|
||||
- name: Checkout screenshot maker
|
||||
run: git clone --depth=1 https://github.com/circuitpython/CircuitPython_Library_Screenshot_Maker
|
||||
|
|
@ -50,3 +49,4 @@ jobs:
|
|||
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
|
||||
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,4 +5,3 @@ Hue_Controller/secrets.h
|
|||
CircuitPython_Logger/secrets\.py
|
||||
.python-version
|
||||
__pycache__
|
||||
*.swp
|
||||
|
|
|
|||
1
.mailmap
1
.mailmap
|
|
@ -1 +0,0 @@
|
|||
Anne Barela <mydigitalhome@gmail.com>
|
||||
|
|
@ -52,7 +52,7 @@ confidence=
|
|||
# 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
|
||||
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
|
||||
|
||||
# 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
|
||||
|
|
@ -72,7 +72,7 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme
|
|||
|
||||
# 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})'
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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,7 +1,5 @@
|
|||
// SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#define BITMAP_WIDTH 64
|
||||
#define BITMAP_HEIGHT 32
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
// 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;
|
||||
bool show_2021 = 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
|
||||
|
|
@ -27,19 +13,11 @@ bool show_new_year = true;
|
|||
#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 addrPins[] = {17, 18, 19, 20};
|
||||
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(
|
||||
|
|
@ -72,10 +50,10 @@ void setup(void) {
|
|||
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++) {
|
||||
// Count number of 'on' pixels (sand grains) in bitmap_2020
|
||||
for (int i=0; i<sizeof(bitmap_2020); i++) {
|
||||
for (int b=0; b<8; b++) {
|
||||
if (THIS_YEAR_BITMAP[i] & (1 << b)) {
|
||||
if (bitmap_2020[i] & (1 << b)) {
|
||||
n_grains++;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,15 +77,15 @@ void setup(void) {
|
|||
|
||||
void loop() {
|
||||
Serial.print("Tick");
|
||||
uint16_t sandColor = show_new_year ? 0xF800 : 0xFFFF; // Red or white
|
||||
uint16_t sandColor = show_2021 ? 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 i=0; i<sizeof(bitmap_2020); i++) {
|
||||
for (int b=0; b<8; b++, pixel++) {
|
||||
if (THIS_YEAR_BITMAP[i] & (1 << (7-b))) {
|
||||
if (bitmap_2020[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);
|
||||
|
|
@ -165,7 +143,7 @@ void loop() {
|
|||
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)
|
||||
if (show_2021)
|
||||
sandColor = (rb * 0b100000000000); // Just show red
|
||||
else
|
||||
sandColor = (rb * 0b100000000001) + (g << 5);
|
||||
|
|
@ -181,16 +159,16 @@ void loop() {
|
|||
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;
|
||||
// If the show_2021 flag is set, don't return to 2020 shake detect,
|
||||
// instead switch to sparkly '2021' display forever (reset to start over)
|
||||
if (show_2021) {
|
||||
uint16_t frame = 0;
|
||||
matrix.fillScreen(0);
|
||||
for(;;) {
|
||||
int pixel = 0;
|
||||
for (int i=0; i<sizeof(NEXT_YEAR_BITMAP); i++) {
|
||||
for (int i=0; i<sizeof(bitmap_2021); i++) {
|
||||
for (int b=0; b<8; b++, pixel++) {
|
||||
if (NEXT_YEAR_BITMAP[i] & (1 << (7-b))) {
|
||||
if (bitmap_2021[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);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// 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,
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2018 Bill Earl and Mikey Sklar for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*******************************************************************
|
||||
Bionic Eye sketch for Adafruit Trinket.
|
||||
|
||||
|
|
|
|||
50
3D_Printed_Bionic_Eye/3D_Printed_Bionic_Eye.py
Normal file
50
3D_Printed_Bionic_Eye/3D_Printed_Bionic_Eye.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# 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,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,7 +1,3 @@
|
|||
// 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
|
||||
|
|
@ -30,7 +26,7 @@ struct {
|
|||
long fade; // Decreases brightness as wave moves
|
||||
|
||||
// Gamma correction improves appearance of midrange colors
|
||||
const uint8_t gamma[] PROGMEM = {
|
||||
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,
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
# 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,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,7 +1,3 @@
|
|||
// 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.
|
||||
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
# 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,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,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/power.h>
|
||||
|
|
|
|||
50
3D_Printed_Guardian_Sword/3D_Printed_Guardian_Sword.py
Normal file
50
3D_Printed_Guardian_Sword/3D_Printed_Guardian_Sword.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# 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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
// 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.
|
||||
|
|
|
|||
117
3D_Printed_LED-Animation_BMO/3D_Printed_LED-Animation_BMO.py
Normal file
117
3D_Printed_LED-Animation_BMO/3D_Printed_LED-Animation_BMO.py
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# 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
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Animation data for Trinket/Gemma + LED matrix backpack jewelry.
|
||||
// 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[] = {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
// 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
|
||||
|
|
|
|||
147
3D_Printed_LED_Fire_Horns/3D_Printed_LED_Fire_Horns.py
Normal file
147
3D_Printed_LED_Fire_Horns/3D_Printed_LED_Fire_Horns.py
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
# 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,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()
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2013 Phil Burgess for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
LED VU meter for Arduino and Adafruit NeoPixel LEDs.
|
||||
|
||||
|
|
|
|||
195
3D_Printed_LED_Microphone_Flag/3D_Printed_LED_Microphone_Flag.py
Normal file
195
3D_Printed_LED_Microphone_Flag/3D_Printed_LED_Microphone_Flag.py
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
# 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 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 wheel(pos):
|
||||
# Input a value 0 to 255 to get a color value.
|
||||
# The colours are a transition r - g - b - back to r.
|
||||
if pos < 0 or pos > 255:
|
||||
return (0, 0, 0)
|
||||
if pos < 85:
|
||||
return (int(pos * 3), int(255 - (pos * 3)), 0)
|
||||
elif pos < 170:
|
||||
pos -= 85
|
||||
return (int(255 - pos * 3), 0, int(pos * 3))
|
||||
else:
|
||||
pos -= 170
|
||||
return (0, int(pos * 3), int(255 - pos * 3))
|
||||
|
||||
|
||||
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:
|
||||
fromheretemp = fromhere
|
||||
fromhere = to
|
||||
to = fromheretemp
|
||||
|
||||
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] = wheel(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, wheel(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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2014 Phil Burgess for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
#define PIN 0
|
||||
|
|
|
|||
58
3D_Printed_NeoPixel_Gas_Mask/3D_Printed_NeoPixel_Gas_Mask.py
Normal file
58
3D_Printed_NeoPixel_Gas_Mask/3D_Printed_NeoPixel_Gas_Mask.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,311 @@
|
|||
#
|
||||
# 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()
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// 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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2015 Phil Burgess for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
#define PIN 1
|
||||
|
|
|
|||
48
3D_Printed_Unicorn_Horn/3D_Printed_Unicorn_Horn.py
Normal file
48
3D_Printed_Unicorn_Horn/3D_Printed_Unicorn_Horn.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import time
|
||||
|
||||
import board
|
||||
import neopixel
|
||||
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 wheel(pos):
|
||||
# Input a value 0 to 255 to get a color value.
|
||||
# The colours are a transition r - g - b - back to r.
|
||||
if (pos < 0) or (pos > 255):
|
||||
return (0, 0, 0)
|
||||
if pos < 85:
|
||||
return (int(pos * 3), int(255 - (pos*3)), 0)
|
||||
elif pos < 170:
|
||||
pos -= 85
|
||||
return (int(255 - pos * 3), 0, int(pos * 3))
|
||||
else:
|
||||
pos -= 170
|
||||
return (0, int(pos * 3), int(255 - pos * 3))
|
||||
|
||||
|
||||
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] = wheel(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] = wheel(idx & 255)
|
||||
time.sleep(wait)
|
||||
|
||||
|
||||
while True:
|
||||
rainbow_cycle(0.05)
|
||||
|
|
@ -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)
|
||||
Binary file not shown.
|
|
@ -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)
|
||||
Binary file not shown.
|
|
@ -1,83 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
import time
|
||||
import board
|
||||
import neopixel
|
||||
import fontio
|
||||
from adafruit_display_text.bitmap_label import Label
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from displayio import Bitmap
|
||||
from rainbowio import colorwheel
|
||||
|
||||
tom_thumb = bitmap_font.load_font("tom-thumb.pcf", Bitmap)
|
||||
|
||||
_glyph_keys = ['bitmap', 'tile_index', 'width', 'height', 'dx', 'dy', 'shift_x', 'shift_y']
|
||||
def patch_glyph(base, **kw):
|
||||
d = {}
|
||||
for k in _glyph_keys:
|
||||
d[k] = kw.get(k, getattr(base, k))
|
||||
return fontio.Glyph(**d)
|
||||
|
||||
class PatchedFont:
|
||||
def __init__(self, base_font, patches):
|
||||
self.base_font = base_font
|
||||
self.patches = patches
|
||||
|
||||
def get_glyph(self, glyph):
|
||||
g = self.base_font.get_glyph(glyph)
|
||||
patch = self.patches.get(glyph)
|
||||
if patch is not None:
|
||||
print("patching", repr(chr(glyph)), g)
|
||||
g = patch_glyph(g, **patch)
|
||||
print("patched", g)
|
||||
return g
|
||||
|
||||
def get_bounding_box(self):
|
||||
return self.base_font.get_bounding_box()
|
||||
|
||||
font = PatchedFont(tom_thumb,
|
||||
{
|
||||
32: {'shift_x': 1, 'dx': 0},
|
||||
105: {'dx': 0, 'shift_x': 2},
|
||||
33: {'dx': 0, 'shift_x': 2},
|
||||
})
|
||||
|
||||
label = Label(text=" adafruit! ", font=font)
|
||||
bitmap = label.bitmap
|
||||
|
||||
heart_bitmap = [
|
||||
0,1,1,0,0,
|
||||
1,1,1,1,0,
|
||||
0,1,1,1,1,
|
||||
1,1,1,1,0,
|
||||
0,1,1,0,0,
|
||||
]
|
||||
|
||||
pixels = neopixel.NeoPixel(board.A3, 5*5, brightness=.06, auto_write=False)
|
||||
|
||||
while True:
|
||||
for hue in range(0, 255, 3):
|
||||
color = colorwheel(hue)
|
||||
pixels[:] = [pixel * color for pixel in heart_bitmap]
|
||||
pixels.show()
|
||||
time.sleep(.01)
|
||||
|
||||
hue = 0
|
||||
for i in range(bitmap.width):
|
||||
# Use a rainbow of colors, shifting each column of pixels
|
||||
hue = hue + 7
|
||||
if hue >= 256:
|
||||
hue = hue - 256
|
||||
|
||||
color = colorwheel(hue)
|
||||
|
||||
# Scoot the old text left by 1 pixel
|
||||
pixels[:20] = pixels[5:]
|
||||
|
||||
# Draw in the next line of text
|
||||
for y in range(5):
|
||||
# Select black or color depending on the bitmap pixel
|
||||
pixels[20+y] = color * bitmap[i,y]
|
||||
pixels.show()
|
||||
time.sleep(.1)
|
||||
Binary file not shown.
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2020 Anne Barela for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Talking A, B, Cs Soundboards: Animal ABCs and "E is for Electronics" ABCs
|
||||
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_ADG72x.h>
|
||||
|
||||
Adafruit_ADG72x adg72x;
|
||||
|
||||
bool isADG728 = false; // which chip are we connected to?
|
||||
|
||||
int analogIn = A0;
|
||||
int analogValue = 0;
|
||||
unsigned long switchTimer = 1000; // 1000 ms = 1 second for channel switch
|
||||
unsigned long readTimer = 10; // 10 ms for analog read
|
||||
unsigned long lastSwitchTime = 0; // Last time the channels were switched
|
||||
unsigned long lastReadTime = 0; // Last time the analog was read
|
||||
uint8_t currentChannel = 0; // Current channel being selected
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Wait for serial port to open
|
||||
while (!Serial) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Try with the ADG728 default address first...
|
||||
if (adg72x.begin(ADG728_DEFAULT_ADDR, &Wire)) {
|
||||
Serial.println("ADG728 found!");
|
||||
isADG728 = true;
|
||||
}
|
||||
// Maybe they have an ADG729?
|
||||
else if (adg72x.begin(ADG729_DEFAULT_ADDR, &Wire)) {
|
||||
Serial.println("ADG729 found!");
|
||||
isADG728 = false;
|
||||
}
|
||||
else {
|
||||
Serial.println("No ADG device found? Check wiring!");
|
||||
while (1); // Stop here if no device was found
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// read and print analog value every 10ms
|
||||
if ((currentTime - lastReadTime) >= readTimer) {
|
||||
analogValue = analogRead(analogIn);
|
||||
Serial.println(analogValue);
|
||||
lastReadTime = currentTime;
|
||||
}
|
||||
|
||||
// switch channels every 1 second
|
||||
if ((currentTime - lastSwitchTime) >= switchTimer) {
|
||||
uint8_t bits = 1 << currentChannel; // Shift a '1' from LSB to MSB
|
||||
if (!adg72x.selectChannels(bits)) {
|
||||
Serial.println("Failed to set channels...");
|
||||
}
|
||||
/*Serial.print((currentChannel % 4) + 1);
|
||||
if (currentChannel < 4) Serial.println("A");
|
||||
else Serial.println("B");*/
|
||||
currentChannel = (currentChannel + 1) % 8; // Move to the next channel, wrap around at 8
|
||||
lastSwitchTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_ADG72x.h>
|
||||
|
||||
Adafruit_ADG72x adg72x;
|
||||
|
||||
int analogInA0 = A0;
|
||||
int analogInA1 = A1;
|
||||
int analogValueDA = 0;
|
||||
int analogValueDB = 0;
|
||||
unsigned long switchTimer = 1000; // 1000 ms = 1 second for channel switch
|
||||
unsigned long readTimer = 10; // 10 ms for analog read
|
||||
unsigned long lastSwitchTime = 0; // Last time the channels were switched
|
||||
unsigned long lastReadTime = 0; // Last time the analog was read
|
||||
uint8_t currentChannel = 0; // Current channel being selected
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Wait for serial port to open
|
||||
while (!Serial) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Try with the ADG728 default address first...
|
||||
if (adg72x.begin(ADG728_DEFAULT_ADDR, &Wire)) {
|
||||
//Serial.println("ADG728 found!");
|
||||
}
|
||||
// Maybe they have an ADG729?
|
||||
else if (adg72x.begin(ADG729_DEFAULT_ADDR, &Wire)) {
|
||||
//Serial.println("ADG729 found!");
|
||||
}
|
||||
else {
|
||||
Serial.println("No ADG72x device found? Check wiring!");
|
||||
while (1); // Stop here if no device was found
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// read and print analog value every 10ms
|
||||
if ((currentTime - lastReadTime) >= readTimer) {
|
||||
analogValueDA = analogRead(analogInA0);
|
||||
analogValueDB = analogRead(analogInA1);
|
||||
Serial.print(analogValueDA);
|
||||
Serial.print(",");
|
||||
Serial.println(analogValueDB);
|
||||
lastReadTime = currentTime;
|
||||
}
|
||||
|
||||
// switch channels every 1 second
|
||||
if ((currentTime - lastSwitchTime) >= switchTimer) {
|
||||
uint8_t bits = 1 << currentChannel; // Shift a '1' from LSB to MSB
|
||||
if (!adg72x.selectChannels(bits)) {
|
||||
Serial.println("Failed to set channels...");
|
||||
}
|
||||
/*Serial.print((currentChannel % 4) + 1);
|
||||
if (currentChannel < 4) Serial.println("A");
|
||||
else Serial.println("B");*/
|
||||
currentChannel = (currentChannel + 1) % 8; // Move to the next channel, wrap around at 8
|
||||
lastSwitchTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2024 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import adafruit_adg72x
|
||||
from analogio import AnalogIn
|
||||
|
||||
analog_in = AnalogIn(board.A0)
|
||||
|
||||
i2c = board.I2C()
|
||||
switch = adafruit_adg72x.ADG72x(i2c)
|
||||
|
||||
c = 0
|
||||
switch_time = 2
|
||||
channels = [0, 4]
|
||||
clock = time.monotonic()
|
||||
while True:
|
||||
if (time.monotonic() - clock) > switch_time:
|
||||
print(f"Selecting channel {channels[c] + 1}")
|
||||
switch.channel = channels[c]
|
||||
c = (c + 1) % 2
|
||||
clock = time.monotonic()
|
||||
print((analog_in.value,))
|
||||
time.sleep(0.1)
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2024 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import adafruit_adg72x
|
||||
from analogio import AnalogIn
|
||||
|
||||
analog_in_DA = AnalogIn(board.A0)
|
||||
analog_in_DB = AnalogIn(board.A1)
|
||||
|
||||
i2c = board.I2C()
|
||||
switch = adafruit_adg72x.ADG72x(i2c, 0x44)
|
||||
|
||||
c = 0
|
||||
switch_time = 3
|
||||
clock = time.monotonic()
|
||||
|
||||
while True:
|
||||
if (time.monotonic() - clock) > switch_time:
|
||||
if c < 4:
|
||||
channels = "A"
|
||||
else:
|
||||
channels = "B"
|
||||
print(f"Selecting channel {(c % 4) + 1}{channels}")
|
||||
switch.channel = c
|
||||
c = (c + 1) % 8
|
||||
clock = time.monotonic()
|
||||
print((analog_in_DA.value, analog_in_DB.value,))
|
||||
time.sleep(0.1)
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2020 Andy Doro for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
""" Example for using the AHT20 and OLED with CircuitPython and the Adafruit library"""
|
||||
|
||||
import time
|
||||
|
|
@ -11,7 +7,6 @@ import adafruit_ahtx0
|
|||
|
||||
# OLED
|
||||
import displayio
|
||||
import i2cdisplaybus
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
import adafruit_displayio_ssd1306
|
||||
|
|
@ -26,15 +21,15 @@ aht20 = adafruit_ahtx0.AHTx0(i2c)
|
|||
|
||||
|
||||
#OLED
|
||||
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3C)
|
||||
display_bus = displayio.I2CDisplay(i2c, device_address=0x3C)
|
||||
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32)
|
||||
|
||||
# Make the display context
|
||||
splash = displayio.Group()
|
||||
display.root_group = splash
|
||||
splash = displayio.Group(max_size=8)
|
||||
display.show(splash)
|
||||
|
||||
text = "hello world"
|
||||
text_area = label.Label(terminalio.FONT, color=0xFFFF00, x=15, y=0)
|
||||
text_area = label.Label(terminalio.FONT, color=0xFFFF00, x=15, y=0, max_glyphs=200)
|
||||
splash.append(text_area)
|
||||
|
||||
while True:
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Adafruit IO Environmental Monitor for Feather or Raspberry Pi -
|
||||
# an internet-enabled environmental monitor
|
||||
|
||||
# Import standard python modules
|
||||
import time
|
||||
|
||||
# import Adafruit Blinka
|
||||
import board
|
||||
import busio
|
||||
|
||||
# import CircuitPython sensor libraries
|
||||
import adafruit_sgp30
|
||||
import adafruit_veml6070
|
||||
from adafruit_bme280 import basic as adafruit_bme280
|
||||
|
||||
# import Adafruit IO REST client
|
||||
from Adafruit_IO import Client, Feed, RequestError
|
||||
|
||||
# loop timeout, in seconds.
|
||||
LOOP_DELAY = 10
|
||||
|
||||
# Set to your Adafruit IO key.
|
||||
# Remember, your key is a secret,
|
||||
# so make sure not to publish it when you publish this code!
|
||||
ADAFRUIT_IO_KEY = 'YOUR_AIO_KEY'
|
||||
|
||||
# Set to your Adafruit IO username.
|
||||
# (go to https://accounts.adafruit.com to find your username)
|
||||
ADAFRUIT_IO_USERNAME = 'YOUR_AIO_USERNAME'
|
||||
|
||||
# Create an instance of the REST client
|
||||
aio = Client(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)
|
||||
|
||||
try: # if we already have the feeds, assign them.
|
||||
tvoc_feed = aio.feeds('tvoc')
|
||||
eCO2_feed = aio.feeds('eco2')
|
||||
uv_feed = aio.feeds('uv')
|
||||
temperature_feed = aio.feeds('temperature')
|
||||
humidity_feed = aio.feeds('humidity')
|
||||
pressure_feed = aio.feeds('pressure')
|
||||
altitude_feed = aio.feeds('altitude')
|
||||
except RequestError: # if we don't, create and assign them.
|
||||
tvoc_feed = aio.create_feed(Feed(name='tvoc'))
|
||||
eCO2_feed = aio.create_feed(Feed(name='eco2'))
|
||||
uv_feed = aio.create_feed(Feed(name='uv'))
|
||||
temperature_feed = aio.create_feed(Feed(name='temperature'))
|
||||
humidity_feed = aio.create_feed(Feed(name='humidity'))
|
||||
pressure_feed = aio.create_feed(Feed(name='pressure'))
|
||||
altitude_feed = aio.create_feed(Feed(name='altitude'))
|
||||
|
||||
# Create busio I2C
|
||||
i2c = busio.I2C(board.SCL, board.SDA)
|
||||
# Create VEML6070 object.
|
||||
uv = adafruit_veml6070.VEML6070(i2c)
|
||||
# Create BME280 object.
|
||||
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
|
||||
bme280.sea_level_pressure = 1013.25
|
||||
# Create SGP30 object using I2C.
|
||||
sgp30 = adafruit_sgp30.Adafruit_SGP30(i2c)
|
||||
sgp30.iaq_init()
|
||||
sgp30.set_iaq_baseline(0x8973, 0x8aae)
|
||||
|
||||
# Sample VEML6070
|
||||
def sample_VEML():
|
||||
for _ in range(10):
|
||||
uv_raw = uv.uv_raw
|
||||
return uv_raw
|
||||
|
||||
while True:
|
||||
print('Reading sensors...')
|
||||
# Read SGP30.
|
||||
eCO2_data = sgp30.eCO2
|
||||
tvoc_data = sgp30.TVOC
|
||||
|
||||
# Read VEML6070.
|
||||
uv_data = sample_VEML()
|
||||
|
||||
# Read BME280.
|
||||
temp_data = bme280.temperature
|
||||
# convert temperature (C->F)
|
||||
temp_data = int(temp_data) * 1.8 + 32
|
||||
humid_data = bme280.humidity
|
||||
pressure_data = bme280.pressure
|
||||
alt_data = bme280.altitude
|
||||
|
||||
print('sending data to adafruit io...')
|
||||
# Send SGP30 Data to Adafruit IO.
|
||||
print('eCO2:', eCO2_data)
|
||||
aio.send(eCO2_feed.key, eCO2_data)
|
||||
print('tvoc:', tvoc_data)
|
||||
aio.send(tvoc_feed.key, tvoc_data)
|
||||
time.sleep(2)
|
||||
# Send VEML6070 Data to Adafruit IO.
|
||||
print('UV Level: ', uv_data)
|
||||
aio.send(uv_feed.key, uv_data)
|
||||
time.sleep(2)
|
||||
# Send BME280 Data to Adafruit IO.
|
||||
print('Temperature: %0.1f C' % temp_data)
|
||||
aio.send(temperature_feed.key, temp_data)
|
||||
print("Humidity: %0.1f %%" % humid_data)
|
||||
aio.send(humidity_feed.key, int(humid_data))
|
||||
time.sleep(2)
|
||||
print("Pressure: %0.1f hPa" % pressure_data)
|
||||
aio.send(pressure_feed.key, int(pressure_data))
|
||||
print("Altitude = %0.2f meters" % alt_data)
|
||||
aio.send(altitude_feed.key, int(alt_data))
|
||||
# avoid timeout from adafruit io
|
||||
time.sleep(LOOP_DELAY * 60)
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2018 John Edgar Park for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// For Adafruit_AMRadio library -- Morse code transmits on AM 540.
|
||||
// Connect antenna (40" wire) to pin A0 and GND
|
||||
// RANGE IS LIMITED TO A FEW FEET
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <RotaryEncoder.h>
|
||||
|
||||
#define PIN_ENCODER_A 13
|
||||
#define PIN_ENCODER_B 12
|
||||
#define COM_A 11
|
||||
#define COM_B SDA
|
||||
#define BUTTON_UP 5
|
||||
#define BUTTON_LEFT SCL
|
||||
#define BUTTON_DOWN 9
|
||||
#define BUTTON_RIGHT 6
|
||||
#define BUTTON_IN 10
|
||||
|
||||
RotaryEncoder encoder(PIN_ENCODER_A, PIN_ENCODER_B, RotaryEncoder::LatchMode::TWO03);
|
||||
// This interrupt will do our encoder reading/checking!
|
||||
void checkPosition() {
|
||||
encoder.tick(); // just call tick() to check the state.
|
||||
}
|
||||
int last_rotary = 0;
|
||||
|
||||
|
||||
#define NUMPIXELS 12
|
||||
Adafruit_NeoPixel pixels(NUMPIXELS, A0, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println("ANO Rotary Encoder Demo");
|
||||
|
||||
pinMode(COM_A, OUTPUT);
|
||||
digitalWrite(COM_A, LOW);
|
||||
pinMode(COM_B, OUTPUT);
|
||||
digitalWrite(COM_B, LOW);
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_ENCODER_A), checkPosition, CHANGE);
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_ENCODER_B), checkPosition, CHANGE);
|
||||
|
||||
pinMode(BUTTON_UP, INPUT_PULLUP);
|
||||
pinMode(BUTTON_DOWN, INPUT_PULLUP);
|
||||
pinMode(BUTTON_LEFT, INPUT_PULLUP);
|
||||
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
|
||||
pinMode(BUTTON_IN, INPUT_PULLUP);
|
||||
pixels.begin();
|
||||
pixels.setBrightness(30);
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
// read encoder
|
||||
int curr_rotary = encoder.getPosition();
|
||||
RotaryEncoder::Direction direction = encoder.getDirection();
|
||||
|
||||
pixels.clear();
|
||||
if (curr_rotary != last_rotary) {
|
||||
Serial.print("Encoder value: ");
|
||||
Serial.print(curr_rotary);
|
||||
Serial.print(" direction: ");
|
||||
Serial.println((int)direction);
|
||||
}
|
||||
last_rotary = curr_rotary;
|
||||
|
||||
pixels.setPixelColor((curr_rotary + (1000*NUMPIXELS)) % NUMPIXELS, pixels.Color(0, 150, 0));
|
||||
|
||||
if (! digitalRead(BUTTON_UP)) {
|
||||
pixels.setPixelColor(0, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_LEFT)) {
|
||||
pixels.setPixelColor(NUMPIXELS/4, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_DOWN)) {
|
||||
pixels.setPixelColor(NUMPIXELS/2, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_RIGHT)) {
|
||||
pixels.setPixelColor(NUMPIXELS*3/4, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_IN)) {
|
||||
pixels.fill(pixels.Color(50, 50, 50));
|
||||
}
|
||||
pixels.show();
|
||||
|
||||
delay(20);
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
CircuitPython ANO Rotary Encoder and NeoPixel Ring example.
|
||||
"""
|
||||
import board
|
||||
import digitalio
|
||||
import rotaryio
|
||||
import neopixel
|
||||
|
||||
# The pin assignments for the breakout pins. Update this is you are not using a Feather.
|
||||
ENCA = board.D13
|
||||
ENCB = board.D12
|
||||
COMA = board.D11
|
||||
SW1 = board.D10
|
||||
SW2 = board.D9
|
||||
SW3 = board.D6
|
||||
SW4 = board.D5
|
||||
SW5 = board.SCL
|
||||
COMB = board.SDA
|
||||
|
||||
# Rotary encoder setup
|
||||
encoder = rotaryio.IncrementalEncoder(ENCA, ENCB)
|
||||
last_position = None
|
||||
|
||||
# NeoPixel ring setup. Update num_pixels if using a different ring.
|
||||
num_pixels = 12
|
||||
pixels = neopixel.NeoPixel(board.A0, num_pixels, auto_write=False)
|
||||
|
||||
# Set the COMA and COMB pins LOW. This is only necessary when using the direct-to-Feather or other
|
||||
# GPIO-based wiring method. If connecting COMA and COMB to ground, you do not need to include this.
|
||||
com_a = digitalio.DigitalInOut(COMA)
|
||||
com_a.switch_to_output()
|
||||
com_a = False
|
||||
com_b = digitalio.DigitalInOut(COMB)
|
||||
com_b.switch_to_output()
|
||||
com_b = False
|
||||
|
||||
# Button pin setup
|
||||
button_pins = (SW1, SW2, SW3, SW4, SW5)
|
||||
buttons = []
|
||||
for button_pin in button_pins:
|
||||
pin = digitalio.DigitalInOut(button_pin)
|
||||
pin.switch_to_input(digitalio.Pull.UP)
|
||||
buttons.append(pin)
|
||||
|
||||
while True:
|
||||
position = encoder.position
|
||||
if last_position is None or position != last_position:
|
||||
print("Position: {}".format(position))
|
||||
last_position = position
|
||||
|
||||
pixels.fill((0, 0, 0))
|
||||
pixels[position % num_pixels] = (0, 150, 0)
|
||||
|
||||
if not buttons[0].value:
|
||||
print("Center button!")
|
||||
pixels.fill((100, 100, 100))
|
||||
|
||||
if not buttons[1].value:
|
||||
print("Up button!")
|
||||
pixels[0] = (150, 0 ,0)
|
||||
|
||||
if not buttons[2].value:
|
||||
print("Left button!")
|
||||
pixels[3] = (150, 0, 0)
|
||||
|
||||
if not buttons[3].value:
|
||||
print("Down button!")
|
||||
pixels[6] = (150, 0, 0)
|
||||
|
||||
if not buttons[4].value:
|
||||
print("Right button!")
|
||||
pixels[9] = (150, 0, 0)
|
||||
|
||||
pixels.show()
|
||||
|
|
@ -1,740 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from random import randint
|
||||
import ulab.numpy as np
|
||||
import board
|
||||
import audiobusio
|
||||
import audiomixer
|
||||
import synthio
|
||||
import simpleio
|
||||
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
|
||||
from adafruit_ht16k33 import segments
|
||||
from adafruit_ht16k33.matrix import Matrix8x8x2
|
||||
from adafruit_seesaw import seesaw, rotaryio, digitalio
|
||||
|
||||
SAMPLE_RATE = 44100
|
||||
SAMPLE_SIZE = 256
|
||||
VOLUME = 5000
|
||||
|
||||
# waveforms, envelopes and synth setup
|
||||
|
||||
square = np.concatenate((np.ones(SAMPLE_SIZE//2, dtype=np.int16)*VOLUME,np.ones(SAMPLE_SIZE//2,
|
||||
dtype=np.int16)*-VOLUME))
|
||||
sine = np.array(np.sin(np.linspace(0, 4*np.pi, SAMPLE_SIZE, endpoint=False)) * VOLUME,
|
||||
dtype=np.int16)
|
||||
saw = np.linspace(VOLUME, -VOLUME, num=SAMPLE_SIZE, dtype=np.int16)
|
||||
noise = np.array([randint(-VOLUME, VOLUME) for i in range(SAMPLE_SIZE)], dtype=np.int16)
|
||||
|
||||
lfo = synthio.LFO(rate = .5, waveform = sine)
|
||||
|
||||
amp_env0 = synthio.Envelope(attack_time=0.1, decay_time = 0.1, release_time=0.1,
|
||||
attack_level=1, sustain_level=0.05)
|
||||
amp_env1 = synthio.Envelope(attack_time=0.05, decay_time = 0.1, release_time=0.1,
|
||||
attack_level=1, sustain_level=0.05)
|
||||
|
||||
# synth plays the notes
|
||||
synth = synthio.Synthesizer(sample_rate=SAMPLE_RATE)
|
||||
|
||||
# these are the notes
|
||||
synth0 = synthio.Note(frequency = 0.0, envelope=amp_env0, waveform=square, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth1 = synthio.Note(frequency = 0.0, envelope=amp_env1, waveform=sine, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth2 = synthio.Note(frequency = 0.0, envelope=amp_env0, waveform=square, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth3 = synthio.Note(frequency = 0.0, envelope=amp_env1, waveform=sine, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
|
||||
synths = [synth0, synth1, synth2, synth3]
|
||||
wave_names = ["SQUR", "SINE", "SAW ", "NOIZ"]
|
||||
waveforms = [square, sine, saw, noise]
|
||||
synth0_wave = 0
|
||||
synth1_wave = 1
|
||||
synth2_wave = 0
|
||||
synth3_wave = 1
|
||||
|
||||
# i2s amp setup
|
||||
audio = audiobusio.I2SOut(bit_clock=board.D10, word_select=board.D11, data=board.D9)
|
||||
mixer = audiomixer.Mixer(voice_count=4, sample_rate=SAMPLE_RATE, channel_count=1,
|
||||
bits_per_sample=16, samples_signed=True, buffer_size=2048 )
|
||||
audio.play(mixer)
|
||||
vol_val = 2
|
||||
mixer.voice[0].play(synth)
|
||||
mixer.voice[0].level = 0.3
|
||||
|
||||
# these are the triads, all major
|
||||
c_tones = [130.81, 164.81, 196.00]
|
||||
g_tones = [196.00, 246.94, 293.66]
|
||||
d_tones = [146.83, 185.00, 220.00]
|
||||
a_tones = [220.00, 277.18, 329.63]
|
||||
e_tones = [164.81, 207.65, 246.94]
|
||||
b_tones = [246.94, 311.13, 369.99]
|
||||
fsharp_tones = [185.00, 233.08, 277.18]
|
||||
csharp_tones = [138.59, 174.61, 207.65]
|
||||
aflat_tones = [207.65, 261.63, 311.13]
|
||||
eflat_tones = [155.56, 196.00, 233.08]
|
||||
bflat_tones = [233.08, 293.66, 349.23]
|
||||
f_tones = [174.61, 220.00, 261.63]
|
||||
|
||||
# names for the alphanumeric displays
|
||||
chord_names = ["Cmaj", "Gmaj", "Dmaj", "Amaj", "Emaj", "Bmaj",
|
||||
"F#ma", "C#ma", "Abma", "Ebma", "Bbma", "Fmaj"]
|
||||
chords = [c_tones, g_tones, d_tones, a_tones, e_tones, b_tones, fsharp_tones, csharp_tones,
|
||||
aflat_tones, eflat_tones, bflat_tones, f_tones]
|
||||
|
||||
# i2c setup
|
||||
i2c = board.I2C()
|
||||
# the encoders
|
||||
seesaw0 = seesaw.Seesaw(i2c, addr=0x49)
|
||||
seesaw1 = seesaw.Seesaw(i2c, addr=0x4A)
|
||||
seesaw2 = seesaw.Seesaw(i2c, addr=0x4B)
|
||||
seesaw3 = seesaw.Seesaw(i2c, addr=0x4C)
|
||||
menu_seesaw = seesaw.Seesaw(i2c, addr=0x4D)
|
||||
# the alphanumeric displays
|
||||
display0 = segments.Seg14x4(i2c, address=0x70)
|
||||
display1 = segments.Seg14x4(i2c, address=0x71)
|
||||
display2 = segments.Seg14x4(i2c, address=0x72)
|
||||
display3 = segments.Seg14x4(i2c, address=0x73)
|
||||
menu_display = segments.Seg14x4(i2c, address=0x74)
|
||||
# the matrix
|
||||
matrix0 = Matrix8x8x2(i2c, address=0x75)
|
||||
|
||||
seesaws = [seesaw0, seesaw1, seesaw2, seesaw3, menu_seesaw]
|
||||
buttons0 = []
|
||||
buttons1 = []
|
||||
buttons2 = []
|
||||
buttons3 = []
|
||||
menu_buttons = []
|
||||
button0_states = []
|
||||
button1_states = []
|
||||
button2_states = []
|
||||
button3_states = []
|
||||
menu_states = []
|
||||
button0_names = ["Select", "Up", "Left", "Down", "Right"]
|
||||
|
||||
# setup the buttons on all of the encoders
|
||||
for i in range(1, 6):
|
||||
seesaw0.pin_mode(i, seesaw0.INPUT_PULLUP)
|
||||
seesaw1.pin_mode(i, seesaw1.INPUT_PULLUP)
|
||||
seesaw2.pin_mode(i, seesaw2.INPUT_PULLUP)
|
||||
seesaw3.pin_mode(i, seesaw3.INPUT_PULLUP)
|
||||
menu_seesaw.pin_mode(i, menu_seesaw.INPUT_PULLUP)
|
||||
buttons0.append(digitalio.DigitalIO(seesaw0, i))
|
||||
buttons1.append(digitalio.DigitalIO(seesaw1, i))
|
||||
buttons2.append(digitalio.DigitalIO(seesaw2, i))
|
||||
buttons3.append(digitalio.DigitalIO(seesaw3, i))
|
||||
menu_buttons.append(digitalio.DigitalIO(menu_seesaw, i))
|
||||
button0_states.append(False)
|
||||
button1_states.append(False)
|
||||
button2_states.append(False)
|
||||
button3_states.append(False)
|
||||
menu_states.append(False)
|
||||
|
||||
# make all of the encoders
|
||||
encoder0 = rotaryio.IncrementalEncoder(seesaw0)
|
||||
last_position0 = 0
|
||||
encoder1 = rotaryio.IncrementalEncoder(seesaw1)
|
||||
last_position1 = 0
|
||||
encoder2 = rotaryio.IncrementalEncoder(seesaw2)
|
||||
last_position2 = 0
|
||||
encoder3 = rotaryio.IncrementalEncoder(seesaw3)
|
||||
last_position3 = 0
|
||||
menu_enc = rotaryio.IncrementalEncoder(menu_seesaw)
|
||||
last_menuPosition = 0
|
||||
|
||||
# Python Implementation of Björklund's Algorithm by Brian House
|
||||
# MIT License 2011
|
||||
# https://github.com/brianhouse/bjorklund
|
||||
|
||||
def bjorklund(steps, pulses):
|
||||
steps = int(steps)
|
||||
pulses = int(pulses)
|
||||
if pulses > steps:
|
||||
raise ValueError
|
||||
pattern = []
|
||||
counts = []
|
||||
remainders = []
|
||||
divisor = steps - pulses
|
||||
remainders.append(pulses)
|
||||
level = 0
|
||||
while True:
|
||||
counts.append(divisor // remainders[level])
|
||||
remainders.append(divisor % remainders[level])
|
||||
divisor = remainders[level]
|
||||
level = level + 1
|
||||
if remainders[level] <= 1:
|
||||
break
|
||||
counts.append(divisor)
|
||||
|
||||
def build(level):
|
||||
if level == -1:
|
||||
pattern.append(0)
|
||||
elif level == -2:
|
||||
pattern.append(1)
|
||||
else:
|
||||
for _ in range(0, counts[level]):
|
||||
build(level - 1)
|
||||
if remainders[level] != 0:
|
||||
build(level - 2)
|
||||
|
||||
build(level)
|
||||
p = pattern.index(1)
|
||||
pattern = pattern[p:] + pattern[0:p]
|
||||
return pattern
|
||||
|
||||
# using ticks for time tracking
|
||||
clock = ticks_ms()
|
||||
|
||||
# default BPM
|
||||
bpm = 120
|
||||
|
||||
# beat divison
|
||||
beat_div = [15, 30, 60, 120, 240]
|
||||
beat_index = 2
|
||||
beat_names = ["1/16", "1/8 ", "1/4 ", "1/2 ", "HOLE"]
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
|
||||
# variables for euclidean
|
||||
c0 = 0
|
||||
c1 = 0
|
||||
c2 = 0
|
||||
c3 = 0
|
||||
r0 = 0
|
||||
r1 = 0
|
||||
r2 = 0
|
||||
r3 = 0
|
||||
last_r0 = 0
|
||||
last_r1 = 0
|
||||
last_r2 = 0
|
||||
last_r3 = 0
|
||||
|
||||
euclid0_steps = 8
|
||||
euclid0_pulses = 4
|
||||
euclid1_steps = 8
|
||||
euclid1_pulses = 4
|
||||
euclid2_steps = 8
|
||||
euclid2_pulses = 4
|
||||
euclid3_steps = 8
|
||||
euclid3_pulses = 4
|
||||
|
||||
rhythm0 = bjorklund(euclid0_steps, euclid0_pulses)
|
||||
rhythm1 = bjorklund(euclid1_steps, euclid1_pulses)
|
||||
rhythm2 = bjorklund(euclid2_steps, euclid2_pulses)
|
||||
rhythm3 = bjorklund(euclid3_steps, euclid3_pulses)
|
||||
|
||||
# read buttons to update Euclidean rhythms
|
||||
# pylint: disable=too-many-branches
|
||||
def read_buttons(button_array, button_states, euc, e_step, e_pulse, the_step):
|
||||
for b in range(5):
|
||||
if not button_array[b].value and button_states[b] is False:
|
||||
button_states[b] = True
|
||||
if button0_names[b] == "Select":
|
||||
e_step = 8
|
||||
e_pulse = 4
|
||||
if the_step >= e_step:
|
||||
the_step = 0
|
||||
elif button0_names[b] == "Up":
|
||||
if e_step > 16:
|
||||
e_step = 16
|
||||
else:
|
||||
e_step += 1
|
||||
elif button0_names[b] == "Down":
|
||||
if e_step < 1:
|
||||
e_step = 1
|
||||
else:
|
||||
e_step -= 1
|
||||
if the_step >= e_step:
|
||||
the_step = 0
|
||||
elif button0_names[b] == "Left":
|
||||
e_pulse -= 1
|
||||
e_pulse = max(e_pulse, 1)
|
||||
else:
|
||||
e_pulse += 1
|
||||
e_pulse = min(e_pulse, e_step)
|
||||
euc = bjorklund(e_step, e_pulse)
|
||||
if button_array[b].value and button_states[b] is True:
|
||||
button_states[b] = False
|
||||
if button0_names[b] in ("Select", "Up", "Down"):
|
||||
matrix0.fill(matrix0.LED_OFF)
|
||||
draw_steps(euclid0_steps, 0)
|
||||
draw_steps(euclid1_steps, 2)
|
||||
draw_steps(euclid2_steps, 4)
|
||||
draw_steps(euclid3_steps, 6)
|
||||
return euc, e_step, e_pulse, the_step
|
||||
|
||||
# play euclidean rhythms and update matrix
|
||||
def play_euclidean(this_synth, n, the_rhythm, rhythm_count, last_count, c, matrix_slot):
|
||||
if last_count <= 7:
|
||||
matrix0[matrix_slot, last_count] = matrix0.LED_GREEN
|
||||
else:
|
||||
c -= 1
|
||||
matrix0[matrix_slot + 1, (last_count - last_count) + c] = matrix0.LED_GREEN
|
||||
c += 1
|
||||
|
||||
if the_rhythm[rhythm_count] == 1:
|
||||
this_synth.frequency = n[randint(0, 2)]
|
||||
synth.press(this_synth)
|
||||
if rhythm_count <= 7:
|
||||
matrix0[matrix_slot, rhythm_count] = matrix0.LED_RED
|
||||
else:
|
||||
matrix0[matrix_slot + 1, (rhythm_count - rhythm_count) + c] = matrix0.LED_RED
|
||||
c += 1
|
||||
else:
|
||||
synth.release(this_synth)
|
||||
if rhythm_count > 7:
|
||||
c += 1
|
||||
last_count = rhythm_count
|
||||
|
||||
rhythm_count += 1
|
||||
if rhythm_count >= len(the_rhythm):
|
||||
rhythm_count = 0
|
||||
if rhythm_count == 1:
|
||||
c = 0
|
||||
return rhythm_count, last_count, c
|
||||
|
||||
# initial matrix draw
|
||||
def draw_steps(euc_steps, col):
|
||||
dif = 0
|
||||
for m in range(euc_steps):
|
||||
if m <= 7:
|
||||
matrix0[col, m] = matrix0.LED_GREEN
|
||||
else:
|
||||
matrix0[col + 1, (m - m) + dif] = matrix0.LED_GREEN
|
||||
dif += 1
|
||||
draw_steps(euclid0_steps, 0)
|
||||
draw_steps(euclid1_steps, 2)
|
||||
draw_steps(euclid2_steps, 4)
|
||||
draw_steps(euclid3_steps, 6)
|
||||
|
||||
# clocks for playing euclidean and reading menu encoder
|
||||
enc_clock = ticks_ms()
|
||||
menu_clock = ticks_ms()
|
||||
|
||||
# the modes menu
|
||||
modes = ["PLAY", "EUC ", "BPM ", "BEAT", "ADSR", "WAVE", "RING", "LFO ", "VOL "]
|
||||
mode_index = 0
|
||||
mode = modes[mode_index]
|
||||
menu_display.print(f" {mode}")
|
||||
|
||||
# default chords
|
||||
chord0_sel = 0
|
||||
chord1_sel = 1
|
||||
chord2_sel = 0
|
||||
chord3_sel = 1
|
||||
|
||||
display0.print(chord_names[chord0_sel])
|
||||
display1.print(chord_names[chord1_sel])
|
||||
display2.print(chord_names[chord2_sel])
|
||||
display3.print(chord_names[chord3_sel])
|
||||
|
||||
# arrays of individual buttons
|
||||
|
||||
select_buttons = [buttons0[0], buttons1[0], buttons2[0], buttons3[0]]
|
||||
left_buttons = [buttons0[2], buttons1[2], buttons2[2], buttons3[2]]
|
||||
right_buttons = [buttons0[4], buttons1[4], buttons2[4], buttons3[4]]
|
||||
select_states = [button0_states[0], button1_states[0], button2_states[0], button3_states[0]]
|
||||
left_states = [button0_states[2], button1_states[2], button2_states[2], button3_states[2]]
|
||||
right_states = [button0_states[4], button1_states[4], button2_states[4], button3_states[4]]
|
||||
select_index = 0
|
||||
left_index = 0
|
||||
right_index = 0
|
||||
|
||||
# adsr mode
|
||||
adsr_names = ["A", "D", "S", "R"]
|
||||
|
||||
synth_adsr_indexes = [0, 0, 0, 0]
|
||||
|
||||
adsr_properties = [0, 1, 4, 2]
|
||||
|
||||
adsr0_values = [amp_env0.attack_time, amp_env0.decay_time,
|
||||
amp_env0.sustain_level, amp_env0.release_time]
|
||||
adsr1_values = [amp_env1.attack_time, amp_env1.decay_time,
|
||||
amp_env1.sustain_level, amp_env1.release_time]
|
||||
adsr2_values = [amp_env0.attack_time, amp_env0.decay_time,
|
||||
amp_env0.sustain_level, amp_env0.release_time]
|
||||
adsr3_values = [amp_env1.attack_time, amp_env1.decay_time,
|
||||
amp_env1.sustain_level, amp_env1.release_time]
|
||||
|
||||
all_adsr_values = [adsr0_values, adsr1_values, adsr2_values, adsr3_values]
|
||||
|
||||
adsr0_val = int(simpleio.map_range(amp_env0.attack_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr1_val = int(simpleio.map_range(amp_env0.decay_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr2_val = int(simpleio.map_range(amp_env0.sustain_level, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr3_val = int(simpleio.map_range(amp_env0.release_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
clock_stretch = False
|
||||
|
||||
ring0_val = 0
|
||||
ring1_val = 0
|
||||
ring2_val = 0
|
||||
ring3_val = 0
|
||||
|
||||
lfo_val = 0
|
||||
|
||||
# used to play/pause
|
||||
play_states = [True, True, True, True]
|
||||
|
||||
while True:
|
||||
# rotary encoder reading
|
||||
if ticks_diff(ticks_ms(), enc_clock) >= 100:
|
||||
position0 = encoder0.position
|
||||
position1 = encoder1.position
|
||||
position2 = encoder2.position
|
||||
position3 = encoder3.position
|
||||
menuPosition = menu_enc.position
|
||||
# menu changes mode
|
||||
if menuPosition != last_menuPosition:
|
||||
if menuPosition > last_menuPosition:
|
||||
mode_index = (mode_index + 1) % len(modes)
|
||||
else:
|
||||
mode_index = (mode_index - 1) % len(modes)
|
||||
if mode in ("EUC ", "ADSR"):
|
||||
clock_stretch = True
|
||||
if mode in ("PLAY", "BPM ", "BEAT", "WAVE") and clock_stretch:
|
||||
clock = ticks_ms()
|
||||
clock_stretch = False
|
||||
mode = modes[mode_index]
|
||||
menu_display.print(f" {mode}")
|
||||
last_menuPosition = menuPosition
|
||||
# encoder functionality depends on mode
|
||||
# encoder 0 has most functionality
|
||||
if position0 != last_position0:
|
||||
if position0 > last_position0:
|
||||
if mode == "PLAY":
|
||||
chord0_sel = (chord0_sel + 1) % len(chords)
|
||||
display0.print(chord_names[chord0_sel])
|
||||
elif mode == "BEAT":
|
||||
beat_index = (beat_index + 1) % 5
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
elif mode == "BPM ":
|
||||
bpm += 1
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {bpm}")
|
||||
elif mode == "ADSR":
|
||||
adsr0_val = (adsr0_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr0_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[0][synth_adsr_indexes[0]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[0][0],
|
||||
decay_time = all_adsr_values[0][1],
|
||||
release_time=all_adsr_values[0][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[0][2])
|
||||
synth0.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth0_wave = (synth0_wave + 1) % len(wave_names)
|
||||
synth0.waveform = waveforms[synth0_wave]
|
||||
elif mode == "RING":
|
||||
ring0_val = (ring0_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring0_val, 0, 24, 0.0, 220.0)
|
||||
synth0.ring_frequency = mapped_val
|
||||
elif mode == "LFO ":
|
||||
lfo_val = (lfo_val + 1) % 10
|
||||
mapped_val = simpleio.map_range(lfo_val, 0, 9, 0.0, 5.0)
|
||||
lfo.rate = mapped_val
|
||||
elif mode == "VOL ":
|
||||
vol_val = (vol_val + 1) % 10
|
||||
mapped_val = simpleio.map_range(vol_val, 0, 9, 0.0, 1.0)
|
||||
mixer.voice[0].level = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord0_sel = (chord0_sel - 1) % len(chords)
|
||||
display0.print(chord_names[chord0_sel])
|
||||
elif mode == "BEAT":
|
||||
beat_index = (beat_index - 1) % 5
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
elif mode == "BPM ":
|
||||
bpm -= 1
|
||||
display0.print(f" {bpm}")
|
||||
elif mode == "ADSR":
|
||||
adsr0_val = (adsr0_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr0_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[0][synth_adsr_indexes[0]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[0][0],
|
||||
decay_time = all_adsr_values[0][1],
|
||||
release_time=all_adsr_values[0][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[0][2])
|
||||
synth0.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth0_wave = (synth0_wave - 1) % len(wave_names)
|
||||
synth0.waveform = waveforms[synth0_wave]
|
||||
elif mode == "RING":
|
||||
ring0_val = (ring0_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring0_val, 0, 24, 0.0, 220.0)
|
||||
synth0.ring_frequency = mapped_val
|
||||
elif mode == "LFO ":
|
||||
lfo_val = (lfo_val - 1) % 10
|
||||
mapped_val = simpleio.map_range(lfo_val, 0, 9, 0.0, 5.0)
|
||||
lfo.rate = mapped_val
|
||||
elif mode == "VOL ":
|
||||
vol_val = (vol_val - 1) % 10
|
||||
mapped_val = simpleio.map_range(vol_val, 0, 9, 0.0, 1.0)
|
||||
mixer.voice[0].level = mapped_val
|
||||
last_position0 = position0
|
||||
if position1 != last_position1:
|
||||
if position1 > last_position1:
|
||||
if mode == "PLAY":
|
||||
chord1_sel = (chord1_sel + 1) % len(chords)
|
||||
display1.print(chord_names[chord1_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr1_val = (adsr1_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr1_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[1][synth_adsr_indexes[1]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[1][0],
|
||||
decay_time = all_adsr_values[1][1],
|
||||
release_time=all_adsr_values[1][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[1][2])
|
||||
synth1.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth1_wave = (synth1_wave + 1) % len(wave_names)
|
||||
synth1.waveform = waveforms[synth1_wave]
|
||||
elif mode == "RING":
|
||||
ring1_val = (ring1_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring1_val, 0, 24, 0.0, 220.0)
|
||||
synth1.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord1_sel = (chord1_sel - 1) % len(chords)
|
||||
display1.print(chord_names[chord1_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr1_val = (adsr1_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr1_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[1][synth_adsr_indexes[1]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[1][0],
|
||||
decay_time = all_adsr_values[1][1],
|
||||
release_time=all_adsr_values[1][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[1][2])
|
||||
synth1.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth1_wave = (synth1_wave - 1) % len(wave_names)
|
||||
synth1.waveform = waveforms[synth1_wave]
|
||||
elif mode == "RING":
|
||||
ring1_val = (ring1_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring1_val, 0, 24, 0.0, 220.0)
|
||||
synth1.ring_frequency = mapped_val
|
||||
last_position1 = position1
|
||||
if position2 != last_position2:
|
||||
if position2 > last_position2:
|
||||
if mode == "PLAY":
|
||||
chord2_sel = (chord2_sel + 1) % len(chords)
|
||||
elif mode == "ADSR":
|
||||
adsr2_val = (adsr2_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr2_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[2][synth_adsr_indexes[2]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[2][0],
|
||||
decay_time = all_adsr_values[2][1],
|
||||
release_time=all_adsr_values[2][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[2][2])
|
||||
synth2.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth2_wave = (synth2_wave + 1) % len(wave_names)
|
||||
synth2.waveform = waveforms[synth2_wave]
|
||||
elif mode == "RING":
|
||||
ring2_val = (ring2_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring2_val, 0, 24, 0.0, 220.0)
|
||||
synth2.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord2_sel = (chord2_sel - 1) % len(chords)
|
||||
display2.print(chord_names[chord2_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr2_val = (adsr2_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr2_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[2][synth_adsr_indexes[2]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[2][0],
|
||||
decay_time = all_adsr_values[2][1],
|
||||
release_time=all_adsr_values[2][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[2][2])
|
||||
synth2.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth2_wave = (synth2_wave - 1) % len(wave_names)
|
||||
synth2.waveform = waveforms[synth2_wave]
|
||||
elif mode == "RING":
|
||||
ring2_val = (ring2_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring2_val, 0, 24, 0.0, 220.0)
|
||||
synth2.ring_frequency = mapped_val
|
||||
last_position2 = position2
|
||||
if position3 != last_position3:
|
||||
if position3 > last_position3:
|
||||
if mode == "PLAY":
|
||||
chord3_sel = (chord3_sel + 1) % len(chords)
|
||||
display3.print(chord_names[chord3_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr3_val = (adsr3_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr3_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[3][synth_adsr_indexes[3]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[3][0],
|
||||
decay_time = all_adsr_values[3][1],
|
||||
release_time=all_adsr_values[3][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[3][2])
|
||||
synth3.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth3_wave = (synth3_wave + 1) % len(wave_names)
|
||||
synth3.waveform = waveforms[synth3_wave]
|
||||
elif mode == "RING":
|
||||
ring3_val = (ring3_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring3_val, 0, 24, 0.0, 220.0)
|
||||
synth3.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord3_sel = (chord3_sel - 1) % len(chords)
|
||||
display3.print(chord_names[chord3_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr3_val = (adsr3_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr3_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[3][synth_adsr_indexes[3]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[3][0],
|
||||
decay_time = all_adsr_values[3][1],
|
||||
release_time=all_adsr_values[3][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[3][2])
|
||||
synth3.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth3_wave = (synth3_wave - 1) % len(wave_names)
|
||||
synth3.waveform = waveforms[synth3_wave]
|
||||
elif mode == "RING":
|
||||
ring3_val = (ring3_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring3_val, 0, 24, 0.0, 220.0)
|
||||
synth3.ring_frequency = mapped_val
|
||||
last_position3 = position3
|
||||
enc_clock = ticks_add(enc_clock, 100)
|
||||
|
||||
# synth plays based on ticks timing
|
||||
if ticks_diff(ticks_ms(), clock) >= delay:
|
||||
if play_states[0] is True:
|
||||
r0, last_r0, c0 = play_euclidean(synth0, chords[chord0_sel],
|
||||
rhythm0, r0, last_r0, c0, 0)
|
||||
if play_states[1] is True:
|
||||
r1, last_r1, c1 = play_euclidean(synth1, chords[chord1_sel],
|
||||
rhythm1, r1, last_r1, c1, 2)
|
||||
if play_states[2] is True:
|
||||
r2, last_r2, c2 = play_euclidean(synth2, chords[chord2_sel],
|
||||
rhythm2, r2, last_r2, c2, 4)
|
||||
if play_states[3] is True:
|
||||
r3, last_r3, c3 = play_euclidean(synth3, chords[chord3_sel],
|
||||
rhythm3, r3, last_r3, c3, 6)
|
||||
clock = ticks_add(clock, delay)
|
||||
# in PLAY select button controls play/pause
|
||||
if mode == "PLAY":
|
||||
for i in range(4):
|
||||
if not select_buttons[i].value and select_states[i] is False:
|
||||
select_states[i] = True
|
||||
if play_states[i] is True:
|
||||
synth.release(synths[i])
|
||||
play_states[i] = False
|
||||
else:
|
||||
play_states[i] = True
|
||||
if select_buttons[i].value and select_states[i] is True:
|
||||
select_states[i] = False
|
||||
display0.print(chord_names[chord0_sel])
|
||||
display1.print(chord_names[chord1_sel])
|
||||
display2.print(chord_names[chord2_sel])
|
||||
display3.print(chord_names[chord3_sel])
|
||||
# EUC menu select resets cycle count
|
||||
elif mode == "EUC ":
|
||||
if not menu_buttons[0].value and menu_states[0] is False:
|
||||
r0 = 0
|
||||
r1 = 0
|
||||
r2 = 0
|
||||
r3 = 0
|
||||
menu_states[0] = True
|
||||
if menu_buttons[0].value and menu_states[0] is True:
|
||||
menu_states[0] = False
|
||||
rhythm0, euclid0_steps, euclid0_pulses, r0 = read_buttons(buttons0, button0_states,
|
||||
rhythm0, euclid0_steps,
|
||||
euclid0_pulses, r0)
|
||||
rhythm1, euclid1_steps, euclid1_pulses, r1 = read_buttons(buttons1, button1_states,
|
||||
rhythm1, euclid1_steps,
|
||||
euclid1_pulses, r1)
|
||||
rhythm2, euclid2_steps, euclid2_pulses, r2 = read_buttons(buttons2, button2_states,
|
||||
rhythm2, euclid2_steps,
|
||||
euclid2_pulses, r2)
|
||||
rhythm3, euclid3_steps, euclid3_pulses, r3 = read_buttons(buttons3, button3_states,
|
||||
rhythm3, euclid3_steps,
|
||||
euclid3_pulses, r3)
|
||||
display0.print(f" {euclid0_pulses}")
|
||||
display1.print(f" {euclid1_pulses}")
|
||||
display2.print(f" {euclid2_pulses}")
|
||||
display3.print(f" {euclid3_pulses}")
|
||||
# BPM is adjusted
|
||||
elif mode == "BPM ":
|
||||
if not select_buttons[0].value and select_states[0] is False:
|
||||
bpm = 120
|
||||
select_states[0] = True
|
||||
if select_buttons[0].value and select_states[0] is True:
|
||||
select_states[0] = False
|
||||
display0.print(f" {bpm}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# beat division is changed
|
||||
elif mode == "BEAT":
|
||||
if not select_buttons[0].value and select_states[0] is False:
|
||||
beat_names[beat_index] = 2
|
||||
select_states[0] = True
|
||||
if select_buttons[0].value and select_states[0] is True:
|
||||
select_states[0] = False
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# adsr for each voice
|
||||
elif mode == "ADSR":
|
||||
for i in range(4):
|
||||
if not left_buttons[i].value and left_states[i] is False:
|
||||
synth_adsr_indexes[i] = (synth_adsr_indexes[i] - 1) % 4
|
||||
left_states[i] = True
|
||||
the_synth = synths[i]
|
||||
if left_buttons[i].value and left_states[i] is True:
|
||||
left_states[i] = False
|
||||
if not right_buttons[i].value and right_states[i] is False:
|
||||
synth_adsr_indexes[i] = (synth_adsr_indexes[i] + 1) % 4
|
||||
right_states[i] = True
|
||||
if right_buttons[i].value and right_states[i] is True:
|
||||
right_states[i] = False
|
||||
if not select_buttons[i].value and select_states[i] is False:
|
||||
the_synth = synths[i]
|
||||
all_adsr_values[i][0] = 0.1
|
||||
all_adsr_values[i][1] = 0.1
|
||||
all_adsr_values[i][3] = 0.1
|
||||
all_adsr_values[i][2] = 0.05
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[i][0],
|
||||
decay_time = all_adsr_values[i][1],
|
||||
release_time=all_adsr_values[i][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[i][2])
|
||||
the_synth.envelope = the_env
|
||||
select_states[i] = True
|
||||
if select_buttons[i].value and select_states[i] is True:
|
||||
select_states[i] = False
|
||||
# pylint: disable=line-too-long
|
||||
display0.print(f"{adsr_names[synth_adsr_indexes[0]]}{synth0.envelope[adsr_properties[synth_adsr_indexes[0]]]:.2f}")
|
||||
display1.print(f"{adsr_names[synth_adsr_indexes[1]]}{synth1.envelope[adsr_properties[synth_adsr_indexes[1]]]:.2f}")
|
||||
display2.print(f"{adsr_names[synth_adsr_indexes[2]]}{synth2.envelope[adsr_properties[synth_adsr_indexes[2]]]:.2f}")
|
||||
display3.print(f"{adsr_names[synth_adsr_indexes[3]]}{synth3.envelope[adsr_properties[synth_adsr_indexes[3]]]:.2f}")
|
||||
# change waveform
|
||||
elif mode == "WAVE":
|
||||
display0.print(f" {wave_names[synth0_wave]}")
|
||||
display1.print(f" {wave_names[synth1_wave]}")
|
||||
display2.print(f" {wave_names[synth2_wave]}")
|
||||
display3.print(f" {wave_names[synth3_wave]}")
|
||||
# adjust ring modulation
|
||||
elif mode == "RING":
|
||||
display0.print(f" {synth0.ring_frequency:.1f}")
|
||||
display1.print(f" {synth1.ring_frequency:.1f}")
|
||||
display2.print(f" {synth2.ring_frequency:.1f}")
|
||||
display3.print(f" {synth3.ring_frequency:.1f}")
|
||||
# adjust lfo rate used for ring modulation
|
||||
elif mode == "LFO ":
|
||||
display0.print("RATE")
|
||||
display1.print(f" {lfo.rate:.1f}")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# overall volume 0.0 - 1.0
|
||||
elif mode == "VOL ":
|
||||
display0.print(f" {mixer.voice[0].level:.1f}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2021 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <RotaryEncoder.h>
|
||||
|
||||
#define PIN_ENCODER_A 12
|
||||
#define PIN_ENCODER_B 13
|
||||
#define COM_A 11 // for wiring simplicity we set these output LOW
|
||||
#define COM_B SDA // ... but you can just wire these to GND instead!
|
||||
#define BUTTON_UP SCL
|
||||
#define BUTTON_LEFT 5
|
||||
#define BUTTON_DOWN 6
|
||||
#define BUTTON_RIGHT 9
|
||||
#define BUTTON_IN 10
|
||||
|
||||
RotaryEncoder encoder(PIN_ENCODER_A, PIN_ENCODER_B, RotaryEncoder::LatchMode::TWO03);
|
||||
// This interrupt will do our encoder reading/checking!
|
||||
void checkPosition() {
|
||||
encoder.tick(); // just call tick() to check the state.
|
||||
}
|
||||
int last_rotary = 0;
|
||||
|
||||
|
||||
#define NUMPIXELS 12
|
||||
Adafruit_NeoPixel pixels(NUMPIXELS, A0, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
// while (!Serial);
|
||||
Serial.println("ANO encoder + NeoPixel test");
|
||||
|
||||
pinMode(COM_A, OUTPUT);
|
||||
digitalWrite(COM_A, LOW);
|
||||
pinMode(COM_B, OUTPUT);
|
||||
digitalWrite(COM_B, LOW);
|
||||
|
||||
attachInterrupt(PIN_ENCODER_A, checkPosition, CHANGE);
|
||||
attachInterrupt(PIN_ENCODER_B, checkPosition, CHANGE);
|
||||
|
||||
pinMode(BUTTON_UP, INPUT_PULLUP);
|
||||
pinMode(BUTTON_DOWN, INPUT_PULLUP);
|
||||
pinMode(BUTTON_LEFT, INPUT_PULLUP);
|
||||
pinMode(BUTTON_RIGHT, INPUT_PULLUP);
|
||||
pinMode(BUTTON_IN, INPUT_PULLUP);
|
||||
pixels.begin();
|
||||
pixels.setBrightness(30);
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
// read encoder
|
||||
int curr_rotary = encoder.getPosition();
|
||||
RotaryEncoder::Direction direction = encoder.getDirection();
|
||||
|
||||
pixels.clear();
|
||||
if (curr_rotary != last_rotary) {
|
||||
Serial.print("Encoder value: ");
|
||||
Serial.print(curr_rotary);
|
||||
Serial.print(" direction: ");
|
||||
Serial.println((int)direction);
|
||||
}
|
||||
last_rotary = curr_rotary;
|
||||
|
||||
pixels.setPixelColor((curr_rotary + (1000*NUMPIXELS)) % NUMPIXELS, pixels.Color(0, 150, 0));
|
||||
|
||||
if (! digitalRead(BUTTON_UP)) {
|
||||
pixels.setPixelColor(0, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_LEFT)) {
|
||||
pixels.setPixelColor(NUMPIXELS/4, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_DOWN)) {
|
||||
pixels.setPixelColor(NUMPIXELS/2, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_RIGHT)) {
|
||||
pixels.setPixelColor(NUMPIXELS*3/4, pixels.Color(150, 0, 0));
|
||||
}
|
||||
if (! digitalRead(BUTTON_IN)) {
|
||||
pixels.fill(pixels.Color(50, 50, 50));
|
||||
}
|
||||
pixels.show();
|
||||
|
||||
delay(20);
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2025 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""AS5600 Encoder"""
|
||||
import usb_hid
|
||||
import board
|
||||
from adafruit_hid.consumer_control import ConsumerControl
|
||||
from adafruit_hid.consumer_control_code import ConsumerControlCode
|
||||
import adafruit_as5600
|
||||
|
||||
i2c = board.STEMMA_I2C()
|
||||
sensor = adafruit_as5600.AS5600(i2c)
|
||||
enc_inc = ConsumerControlCode.VOLUME_INCREMENT
|
||||
enc_dec = ConsumerControlCode.VOLUME_DECREMENT
|
||||
cc = ConsumerControl(usb_hid.devices)
|
||||
|
||||
last_val = sensor.angle
|
||||
|
||||
THRESHOLD = sensor.max_angle // 2 # default max_angle is 4095
|
||||
# you can change the max_angle. ex: sensor.max_angle = 1000
|
||||
|
||||
MIN_CHANGE = 25 # minimum change to register as movement
|
||||
# increase to make less sensitive, decrease to make more sensitive
|
||||
|
||||
while True:
|
||||
enc_val = sensor.angle
|
||||
if abs(enc_val - last_val) >= MIN_CHANGE or abs(enc_val - last_val) > THRESHOLD:
|
||||
# Calculate the difference
|
||||
diff = enc_val - last_val
|
||||
# Check for wraparound
|
||||
if diff > THRESHOLD:
|
||||
# Wrapped from ~4095 to ~0 (actually turning backwards)
|
||||
cc.send(enc_dec)
|
||||
elif diff < -THRESHOLD:
|
||||
# Wrapped from ~0 to ~4095 (actually turning forwards)
|
||||
cc.send(enc_inc)
|
||||
elif diff > 0:
|
||||
# Normal forward rotation
|
||||
cc.send(enc_inc)
|
||||
else:
|
||||
# Normal backward rotation (diff < 0)
|
||||
cc.send(enc_dec)
|
||||
last_val = enc_val
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2020 Collin Cunningham for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
"""ACTIVITY GENERATOR for Adafruit CLUE"""
|
||||
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2020 Collin Cunningham for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
activities = [
|
||||
"DRAWING",
|
||||
"SONG",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
ADAVOICE is an Arduino-based voice pitch changer plus WAV playback.
|
||||
Fun for Halloween costumes, comic convention getups and other shenanigans!
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
This is a mash-up of the adavoice and wavface sketches.
|
||||
Using an Arduino, Wave Shield and some supporting components,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
Dalek voice effect using Wave Shield. This is based on the adavoice sketch
|
||||
with a lot of code & comments ripped out, so see that code for more insight,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2016 James DeVito for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
/*********************************************************************
|
||||
This is an example for our nRF51822 based Bluefruit LE modules
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2016 James DeVito for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// COMMON SETTINGS
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// These settings are used in both SW UART, HW UART and SPI mode
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2016 James DeVito for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
#include <string.h>
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2019 Erin St. Blaine for Adafruit Industries
|
||||
// SPDX-FileCopyrightText: 2019 John Edgar Park for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
//Ada_remoteFXTrigger_RX_NeoPixel
|
||||
//Remote Effects Trigger Box Receiver
|
||||
//by John Park & Erin St Blaine
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
// SPDX-FileCopyrightText: 2019 Erin St. Blaine for Adafruit Industries
|
||||
// SPDX-FileCopyrightText: 2019 John Edgar Park for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
//Ada_remoteFXTrigger_NeoTrellis_TX
|
||||
//Remote Effects Trigger Box Transmitter
|
||||
//by John Park
|
||||
|
|
|
|||
42
Adabot_Operation_Game/adabot_operation_game.py
Normal file
42
Adabot_Operation_Game/adabot_operation_game.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Adabot Operation Game
|
||||
# CPX, alligator clips, copper tape, tweezers, surgery, and fun!
|
||||
|
||||
import board
|
||||
import touchio
|
||||
from adafruit_circuitplayground.express import cpx
|
||||
# import time # uncomment if testing raw read values
|
||||
|
||||
cap_pins = (board.A1, board.A2, board.A3, board.A4, board.A5,
|
||||
board.A6, board.A7)
|
||||
touch_pads = []
|
||||
for i in range(7):
|
||||
touch_pads.append(touchio.TouchIn(cap_pins[i]))
|
||||
for touch_pad in touch_pads:
|
||||
touch_pad.threshold = 3500 # adjust value to fine-tune touch threshold
|
||||
|
||||
MAGENTA = (10, 0, 10)
|
||||
VIOLET = (5, 0, 15)
|
||||
BLUE = (0, 0, 20)
|
||||
CYAN = (0, 10, 10)
|
||||
GREEN = (0, 20, 0)
|
||||
YELLOW = (10, 10, 0)
|
||||
ORANGE = (15, 5, 0)
|
||||
RED = (20, 0, 0)
|
||||
WHITE = (3, 3, 3)
|
||||
|
||||
COLORS = [MAGENTA, VIOLET, BLUE, CYAN, GREEN, YELLOW, ORANGE, RED, WHITE]
|
||||
|
||||
cpx.pixels.fill(WHITE)
|
||||
|
||||
while True:
|
||||
for i in range(7):
|
||||
# uncomment block to check the raw touch pad values
|
||||
# print("raw %s value for pad " % i)
|
||||
# print(touch_pads[i].raw_value)
|
||||
# time.sleep(.5)
|
||||
|
||||
if touch_pads[i].value:
|
||||
# print("Touched %s" % i) # uncomment for debugging
|
||||
cpx.pixels.fill(RED)
|
||||
cpx.play_tone(660, 0.7)
|
||||
cpx.pixels.fill(COLORS[i])
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# SPDX-FileCopyrightText: 2018 John Park for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Adabot Operation Game
|
||||
# CPX, alligator clips, copper tape, tweezers, surgery, and fun!
|
||||
|
||||
import board
|
||||
import touchio
|
||||
from adafruit_circuitplayground.express import cpx
|
||||
# import time # uncomment if testing raw read values
|
||||
|
||||
cap_pins = (board.A1, board.A2, board.A3, board.A4, board.A5,
|
||||
board.A6, board.A7)
|
||||
touch_pads = []
|
||||
for i in range(7):
|
||||
touch_pads.append(touchio.TouchIn(cap_pins[i]))
|
||||
for touch_pad in touch_pads:
|
||||
touch_pad.threshold = 3500 # adjust value to fine-tune touch threshold
|
||||
|
||||
MAGENTA = (10, 0, 10)
|
||||
VIOLET = (5, 0, 15)
|
||||
BLUE = (0, 0, 20)
|
||||
CYAN = (0, 10, 10)
|
||||
GREEN = (0, 20, 0)
|
||||
YELLOW = (10, 10, 0)
|
||||
ORANGE = (15, 5, 0)
|
||||
RED = (20, 0, 0)
|
||||
WHITE = (3, 3, 3)
|
||||
|
||||
COLORS = [MAGENTA, VIOLET, BLUE, CYAN, GREEN, YELLOW, ORANGE, RED, WHITE]
|
||||
|
||||
cpx.pixels.fill(WHITE)
|
||||
|
||||
while True:
|
||||
for i in range(7):
|
||||
# uncomment block to check the raw touch pad values
|
||||
# print("raw %s value for pad " % i)
|
||||
# print(touch_pads[i].raw_value)
|
||||
# time.sleep(.5)
|
||||
|
||||
if touch_pads[i].value:
|
||||
# print("Touched %s" % i) # uncomment for debugging
|
||||
cpx.pixels.fill(RED)
|
||||
cpx.play_tone(660, 0.7)
|
||||
cpx.pixels.fill(COLORS[i])
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue