diff --git a/.github/workflows/filesystem.yml b/.github/workflows/filesystem.yml index 2c674a4..7fc5f18 100644 --- a/.github/workflows/filesystem.yml +++ b/.github/workflows/filesystem.yml @@ -16,12 +16,14 @@ jobs: - name: TinyFX shortname: tiny_fx board: PIMORONI_TINYFX + - name: TinyFX W + shortname: tiny_fx_w + board: PIMORONI_TINYFX env: RELEASE_FILE: ${{matrix.shortname}}-${{github.event.release.tag_name || github.sha}} ROOT_DIR: "picofx" BOARD_DIR: "picofx/boards/${{matrix.board}}" - EXAMPLES_DIR: "picofx/examples/${{matrix.shortname}}" LIBS_DIR: "picofx/lib_temp" EX_DIR: "picofx/ex_temp" @@ -42,26 +44,34 @@ jobs: - name: "Assemble example content" shell: bash run: | - mkdir -p ${{env.EXAMPLES_DIR}} - cp -v -r ${{env.EXAMPLES_DIR}}/. ${{env.EX_DIR}} + mkdir -p ${{env.EX_DIR}} + cp -v -r picofx/examples/tiny_fx/. ${{env.EX_DIR}} rm -v ${{env.EX_DIR}}/README.md rm -v -r ${{env.EX_DIR}}/examples/audio/photon_sword rm -v ${{env.EX_DIR}}/examples/audio/photon_sword.py + - name: "Append W example content" + if: matrix.shortname == 'tiny_fx_w' + shell: bash + run: | + cp -v -r picofx/examples/tiny_fx_w/. ${{env.EX_DIR}} + rm -v ${{env.EX_DIR}}/README.md + - name: Libs .zip artifact + if: matrix.shortname == 'tiny_fx' uses: actions/upload-artifact@v4 with: name: ${{env.RELEASE_FILE}}-libraries-only path: picofx/lib_temp - - name: Examples .zip artifact + - name: Examples .zip artifact uses: actions/upload-artifact@v4 with: name: ${{env.RELEASE_FILE}}-examples-only path: "picofx/ex_temp" - name: Libs .zip release asset - if: github.event_name == 'release' + if: github.event_name == 'release' && matrix.shortname == 'tiny_fx' uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/micropython.yml b/.github/workflows/micropython.yml index 4a272c7..82900e8 100644 --- a/.github/workflows/micropython.yml +++ b/.github/workflows/micropython.yml @@ -64,10 +64,12 @@ jobs: - name: TinyFX shortname: tiny_fx board: PIMORONI_TINYFX + manifest: uf2-manifest - name: TinyFX W shortname: tiny_fx_w board: PIMORONI_TINYFX variant: w + manifest: uf2-manifest-w env: RELEASE_FILE: pimoroni-${{matrix.shortname}}-${{github.event.release.tag_name || github.sha}}-micropython @@ -75,6 +77,7 @@ jobs: ROOT_DIR: "$GITHUB_WORKSPACE/picofx" BOARD_DIR: "$GITHUB_WORKSPACE/picofx/boards/${{matrix.board}}" EXAMPLES_DIR: "$GITHUB_WORKSPACE/picofx/examples/tiny_fx" + EXAMPLES_W_DIR: "$GITHUB_WORKSPACE/picofx/examples/tiny_fx_w" FILESYSTEM_DIR: "$GITHUB_WORKSPACE/picofx/temp" FILESYSTEM_SUFFIX: "with-libs-and-examples" BOARD: "PIMORONI_TINYFX" @@ -186,12 +189,17 @@ jobs: cp -v -r ${{env.BOARD_DIR}}/visible_libs/. ${{env.FILESYSTEM_DIR}}/lib cp -v -r ${{env.EXAMPLES_DIR}}/. ${{env.FILESYSTEM_DIR}} + - name: "HACK: Mangle W examples into user filesystem" + if: matrix.shortname == 'tiny_fx_w' + shell: bash + run: | + cp -v -r ${{env.EXAMPLES_W_DIR}}/. ${{env.FILESYSTEM_DIR}} + - name: Append Filesystem shell: bash run: | python3 -m pip install littlefs-python==0.12.0 - ./dir2uf2/dir2uf2 --fs-compact --append-to micropython/ports/rp2/build/${{env.RELEASE_FILE}}.uf2 --manifest ${{env.BOARD_DIR}}/uf2-manifest.txt --filename ${{env.FILESYSTEM_SUFFIX}}.uf2 ${{env.FILESYSTEM_DIR}}/ - + ./dir2uf2/dir2uf2 --fs-compact --append-to micropython/ports/rp2/build/${{env.RELEASE_FILE}}.uf2 --manifest ${{env.BOARD_DIR}}/${{matrix.manifest}}.txt --filename ${{env.FILESYSTEM_SUFFIX}}.uf2 ${{env.FILESYSTEM_DIR}}/ - name: Store .uf2 as artifact uses: actions/upload-artifact@v4 diff --git a/boards/PIMORONI_TINYFX/uf2-manifest-w.txt b/boards/PIMORONI_TINYFX/uf2-manifest-w.txt new file mode 100644 index 0000000..08583cb --- /dev/null +++ b/boards/PIMORONI_TINYFX/uf2-manifest-w.txt @@ -0,0 +1,15 @@ +main.py +secrets.py +examples/*.py +examples/effects/*.py +examples/effects/mono/*.py +examples/effects/colour/*.py +examples/function/*.py +examples/showcase/*.py +examples/audio/race_start.py +examples/audio/fair_use_encounters.py +examples/wireless/*.py +lib/*.py +lib/picofx/*.py +lib/picofx/colour/*.py +lib/picofx/mono/*.py \ No newline at end of file diff --git a/examples/tiny_fx_w/README.md b/examples/tiny_fx_w/README.md new file mode 100644 index 0000000..d4b07da --- /dev/null +++ b/examples/tiny_fx_w/README.md @@ -0,0 +1,27 @@ +# TinyFX W Micropython Examples + +These are micropython examples for the wireless functionality of the Pimoroni [TinyFX W](https://shop.pimoroni.com/products/tiny_fx_w), a stamp-sized light and sound effects controller board for model making, construction kits, and dioramas. + +For examples that show off the rest of the board's functions, refer to the regular [TinyFX Micropython Examples](../tiny_fx/README.md) + +- [Wireless Examples](#wireless-examples) + - [Random](#random) + - [CheerLights](#cheerlights) + + +## Wireless Examples + +These examples requires a `secrets.py` file to be on your board's file system with the credentials of your WiFi network. + +### Random +[wireless/random.py](examples/wireless/random.py) + +Show the state of TinyFX's Boot button on its RGB output. +Show random colours and patterns obtained from the internet on TinyFX's outputs. + + +### CheerLights +[wireless/cheerlights.py](examples/wireless/cheerlights.py) + +Obtain the current CheerLights colour from the internet and show it on TinyFX's RGB output. +For more information about CheerLights, visit: [https://cheerlights.com/](https://cheerlights.com/) diff --git a/examples/tiny_fx_w/examples/wireless/cheerlights.py b/examples/tiny_fx_w/examples/wireless/cheerlights.py new file mode 100644 index 0000000..46e2c22 --- /dev/null +++ b/examples/tiny_fx_w/examples/wireless/cheerlights.py @@ -0,0 +1,70 @@ +import time +import network +import requests +from tiny_fx import TinyFX + +""" +Obtain the current CheerLights colour from the internet and show it on TinyFX's RGB output. +For more information about CheerLights, visit: https://cheerlights.com/ + +This example requires a secrets.py file to be on your board's file system with the credentials of your WiFi network. + +Press "Boot" to exit the program. +""" + +try: + from secrets import WIFI_SSID, WIFI_PASSWORD + if len(WIFI_SSID) == 0: + raise ValueError("no WiFi network set. Open the 'secrets.py' file on your device to add your WiFi credentials") +except ImportError: + raise ImportError("no module named 'secrets'. Create a 'secrets.py' file on your device with your WiFi credentials") + + +# Constants +COLOUR_NAMES = ("R", "G", "B") +CONNECTION_INTERVAL = 1.0 # The time to sleep between each connection check +REQUEST_INTERVAL = 5.0 # The time to sleep between each internet request + +# Variables +tiny = TinyFX() # Create a new TinyFX object to interact with the board +wlan = network.WLAN(network.STA_IF) # Create a new network object for interacting with WiFI + + +# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt) +try: + # Connect to WLAN + wlan.active(True) + print(f"Connecting to network '{WIFI_SSID}'") + wlan.connect(WIFI_SSID, WIFI_PASSWORD) + + # Wait until the connection is established + while not wlan.isconnected(): + print('Waiting for connection...') + time.sleep(CONNECTION_INTERVAL) + + # Print out our IP address + print(f'Connected on {wlan.ifconfig()[0]}') + + # Loop forever + while True: + # Get the current CheerLights colour from the internet + req = requests.get("http://api.thingspeak.com/channels/1417/field/2/last.json") + json = req.json() + req.close() + + # Use the second to get the colour components for the RGB output + colour = tuple(int(json['field2'][i:i + 2], 16) for i in (1, 3, 5)) + + # Set the colour output, and print the values + tiny.rgb.set_rgb(*colour) + for i in range(len(colour)): + print(f"{COLOUR_NAMES[i]} = {colour[i]}", end=", ") + + print() + + time.sleep(REQUEST_INTERVAL) + +# Turn off all the outputs +finally: + tiny.shutdown() + wlan.disconnect() diff --git a/examples/tiny_fx_w/examples/wireless/random.py b/examples/tiny_fx_w/examples/wireless/random.py new file mode 100644 index 0000000..2d60ff9 --- /dev/null +++ b/examples/tiny_fx_w/examples/wireless/random.py @@ -0,0 +1,78 @@ +import time +import network +import requests +from tiny_fx import TinyFX + +""" +Show random colours and patterns obtained from the internet on TinyFX's outputs. + +This example requires a secrets.py file to be on your board's file system with the credentials of your WiFi network. + +Press "Boot" to exit the program. +""" + +try: + from secrets import WIFI_SSID, WIFI_PASSWORD + if len(WIFI_SSID) == 0: + raise ValueError("no WiFi network set. Open the 'secrets.py' file on your device to add your WiFi credentials") +except ImportError: + raise ImportError("no module named 'secrets'. Create a 'secrets.py' file on your device with your WiFi credentials") + + +# Constants +MONO_NAMES = ("One", "Two", "Three", "Four", "Five", "Six") +COLOUR_NAMES = ("R", "G", "B") +CONNECTION_INTERVAL = 1.0 # The time to sleep between each connection check +REQUEST_INTERVAL = 5.0 # The time to sleep between each internet request + +# Variables +tiny = TinyFX() # Create a new TinyFX object to interact with the board +wlan = network.WLAN(network.STA_IF) # Create a new network object for interacting with WiFI + + +# Wrap the code in a try block, to catch any exceptions (including KeyboardInterrupt) +try: + # Connect to WLAN + wlan.active(True) + print(f"Connecting to network '{WIFI_SSID}'") + wlan.connect(WIFI_SSID, WIFI_PASSWORD) + + # Wait until the connection is established + while not wlan.isconnected(): + print('Waiting for connection...') + time.sleep(CONNECTION_INTERVAL) + + # Print out our IP address + print(f'Connected on {wlan.ifconfig()[0]}') + + # Loop forever + while True: + # Get two colours from the internet + req = requests.get("https://random-flat-colors.vercel.app/api/random?count=2") + json = req.json() + req.close() + + # Use the first to get brightness values for the six mono outputs + mono = tuple(int(json['colors'][0][i:i + 1], 16) / 15 for i in range(1, 7)) + + # Use the second to get the colour components for the RGB output + colour = tuple(int(json['colors'][1][i:i + 2], 16) for i in (1, 3, 5)) + + # Set the mono outputs, and print the values + for i in range(len(tiny.outputs)): + tiny.outputs[i].brightness(mono[i]) + print(f"{MONO_NAMES[i]} = {round(mono[i], 2)}", end=", ") + + # Set the colour output, and print the values + tiny.rgb.set_rgb(*colour) + for i in range(len(colour)): + print(f"{COLOUR_NAMES[i]} = {colour[i]}", end=", ") + + print() + + time.sleep(REQUEST_INTERVAL) + +# Turn off all the outputs +finally: + tiny.shutdown() + wlan.disconnect() diff --git a/examples/tiny_fx_w/secrets.py b/examples/tiny_fx_w/secrets.py new file mode 100644 index 0000000..f290ec1 --- /dev/null +++ b/examples/tiny_fx_w/secrets.py @@ -0,0 +1,2 @@ +WIFI_SSID = "" +WIFI_PASSWORD = ""