Now it's network-aware
This commit is contained in:
parent
0f65cd1f92
commit
de0505cf79
|
@ -12,10 +12,10 @@ furnished to do so, subject to the following conditions:
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
The software is provided "as is", without warranty of any kind, express or
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
implied, including but not limited to the warranties of merchantability,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
fitness for a particular purpose and noninfringement. In no event shall the
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
authors or copyright holders be liable for any claim, damages or other
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
liability, whether in an action of contract, tort or otherwise, arising from,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
out of or in connection with the software or the use or other dealings in the
|
||||||
SOFTWARE.
|
software.
|
|
@ -1,13 +1,10 @@
|
||||||
Wall Art
|
Wall Art
|
||||||
========
|
========
|
||||||
|
|
||||||
This is a CircuitPython port of an art piece I have
|
This an art piece I have
|
||||||
hanging in the wall of my office, with
|
hanging in the wall of my house, with
|
||||||
pixels crammed into a cardboard box.
|
pixels crammed into a cardboard box.
|
||||||
|
|
||||||
This port is running on a 1x1 stick of wood,
|
|
||||||
with tissue paper around it.
|
|
||||||
|
|
||||||
It doesn't display anything significant.
|
It doesn't display anything significant.
|
||||||
The idea is to have something to look at if you're idle,
|
The idea is to have something to look at if you're idle,
|
||||||
without it being a distraction from more pressing issues.
|
without it being a distraction from more pressing issues.
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
#include <FastLED.h>
|
||||||
|
#include <WiFiManager.h>
|
||||||
|
#include <esp_wifi.h>
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
|
WiFiManager wfm;
|
||||||
|
|
||||||
|
void network_setup(char *password) {
|
||||||
|
String hostid = String(ESP.getEfuseMac(), HEX);
|
||||||
|
String hostname = "Wall Art " + hostid;
|
||||||
|
|
||||||
|
wfm.setConfigPortalBlocking(false);
|
||||||
|
wfm.setHostname(hostname);
|
||||||
|
wfm.autoConnect(hostname.c_str(), password);
|
||||||
|
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool connected() {
|
||||||
|
return WiFi.status() == WL_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pause(uint32_t dwMs) {
|
||||||
|
for (uint32_t t = 0; t < dwMs; t += 10) {
|
||||||
|
wfm.process();
|
||||||
|
digitalWrite(LED_BUILTIN, connected());
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
|
||||||
|
|
||||||
|
void network_setup(char *password);
|
||||||
|
bool connected();
|
||||||
|
void pause(uint32_t dwMs);
|
||||||
|
void netget(int count);
|
147
wallart.ino
147
wallart.ino
|
@ -1,14 +1,23 @@
|
||||||
#include <FastLED.h>
|
#include <FastLED.h>
|
||||||
#include "picker.h"
|
#include "picker.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
#define NEOPIXEL_PIN 2
|
#define NEOPIXEL_PIN 32
|
||||||
#define GRIDLEN 50
|
#define GRIDLEN 64
|
||||||
|
#define WFM_PASSWORD "artsy fartsy"
|
||||||
|
#define ART_URL "https://sweetums.woozle.org/public/wallart.bin"
|
||||||
|
|
||||||
#define MILLISECOND 1
|
#define MILLISECOND 1
|
||||||
#define SECOND (1000 * MILLISECOND)
|
#define SECOND (1000 * MILLISECOND)
|
||||||
|
|
||||||
CRGB grid[GRIDLEN];
|
CRGB grid[GRIDLEN];
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
FastLED.addLeds<WS2812, NEOPIXEL_PIN, GRB>(grid, GRIDLEN);
|
||||||
|
FastLED.setBrightness(32);
|
||||||
|
network_setup(WFM_PASSWORD);
|
||||||
|
}
|
||||||
|
|
||||||
void fade(int cycles = 2) {
|
void fade(int cycles = 2) {
|
||||||
int reps = (cycles*GRIDLEN) + random(GRIDLEN);
|
int reps = (cycles*GRIDLEN) + random(GRIDLEN);
|
||||||
int hue = random(256);
|
int hue = random(256);
|
||||||
|
@ -17,15 +26,15 @@ void fade(int cycles = 2) {
|
||||||
grid[(i+pos) % GRIDLEN] = CHSV(hue, 255, pos * 32);
|
grid[(i+pos) % GRIDLEN] = CHSV(hue, 255, pos * 32);
|
||||||
}
|
}
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
delay(80);
|
pause(80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void singleCursor(int count = 80) {
|
void singleCursor(int count = 80) {
|
||||||
for (int i = 0; i < 80; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
grid[20] = CHSV(0, 210, 127 * (i%2));
|
grid[20] = CHSV(0, 210, 127 * (i%2));
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
delay(120);
|
pause(120);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +50,7 @@ void sparkle(int cycles=50) {
|
||||||
for (int j = 0; j < NUM_SPARKS; j++) {
|
for (int j = 0; j < NUM_SPARKS; j++) {
|
||||||
grid[pos[j]] = CRGB::Black;
|
grid[pos[j]] = CRGB::Black;
|
||||||
}
|
}
|
||||||
delay(40);
|
pause(40);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,11 +85,11 @@ void glitchPulse(int cycles=1000) {
|
||||||
steps[i]--;
|
steps[i]--;
|
||||||
}
|
}
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
delay(100);
|
pause(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void conwayish(int cycles=1000) {
|
void conwayish(int cycles=5000) {
|
||||||
uint8_t total[GRIDLEN];
|
uint8_t total[GRIDLEN];
|
||||||
uint8_t left[GRIDLEN] = {0};
|
uint8_t left[GRIDLEN] = {0};
|
||||||
uint8_t hue = random(0, 64);
|
uint8_t hue = random(0, 64);
|
||||||
|
@ -104,29 +113,115 @@ void conwayish(int cycles=1000) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
delay(20);
|
pause(20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void cm5(int cycles=200) {
|
||||||
FastLED.addLeds<WS2812, NEOPIXEL_PIN, RGB>(grid, GRIDLEN);
|
for (int frame = 0; frame < cycles; frame++) {
|
||||||
FastLED.setBrightness(52);
|
int val = 127 * random(2);
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
for (int pos = 0; pos < GRIDLEN; pos++) {
|
||||||
|
if (pos < GRIDLEN-1) {
|
||||||
|
grid[pos] = grid[pos + 1];
|
||||||
|
} else {
|
||||||
|
grid[pos] = CHSV(0, 255, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FastLED.show();
|
||||||
|
pause(500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Art from the network
|
||||||
|
bool NetArtExists = false;
|
||||||
|
CRGB NetArt[GRIDLEN];
|
||||||
|
|
||||||
|
void netart() {
|
||||||
|
if (NetArtExists) {
|
||||||
|
memcpy(grid, NetArt, GRIDLEN*3);
|
||||||
|
FastLED.show();
|
||||||
|
pause(10 * SECOND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int netgetStatus(int hue) {
|
||||||
|
static int positions[4] = {0};
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
grid[positions[j]] = CHSV(0, 0, 0);
|
||||||
|
positions[j] = random(GRIDLEN);
|
||||||
|
grid[positions[j]] = CHSV(hue, 255, 180);
|
||||||
|
}
|
||||||
|
FastLED.show();
|
||||||
|
pause(500);
|
||||||
|
return hue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void netget(int count=30) {
|
||||||
|
int hue = netgetStatus(HUE_BLUE);
|
||||||
|
|
||||||
|
if (connected()) {
|
||||||
|
WiFiClientSecure scli;
|
||||||
|
|
||||||
|
hue = netgetStatus(hue - 32);
|
||||||
|
scli.setInsecure();
|
||||||
|
|
||||||
|
{
|
||||||
|
HTTPClient https;
|
||||||
|
|
||||||
|
if (https.begin(scli, ART_URL)) {
|
||||||
|
hue = netgetStatus(hue - 32);
|
||||||
|
int code = https.GET();
|
||||||
|
if (code == HTTP_CODE_OK) {
|
||||||
|
hue = netgetStatus(hue - 32);
|
||||||
|
String resp = https.getString();
|
||||||
|
for (int i = 0; i < resp.length(); i += 3) {
|
||||||
|
if (resp.length() < i+3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CRGB pixel = CRGB(resp[i], resp[i+1], resp[i+2]);
|
||||||
|
NetArt[i/3] = rgb2hsv_approximate(pixel);
|
||||||
|
}
|
||||||
|
NetArtExists = true;
|
||||||
|
hue = hue - 32;
|
||||||
|
}
|
||||||
|
https.end();
|
||||||
|
|
||||||
|
FastLED.show();
|
||||||
|
for (int i = 0; i < 4*4; i++) {
|
||||||
|
pause(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scli.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
netgetStatus(hue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
Picker p;
|
Picker p;
|
||||||
|
|
||||||
if (p.Pick(1)) {
|
if (p.Pick(1)) {
|
||||||
fade();
|
fade();
|
||||||
singleCursor(20);
|
singleCursor(20);
|
||||||
} else if (p.Pick(1)) {
|
} else if (p.Pick(1)) {
|
||||||
sparkle();
|
sparkle();
|
||||||
} else if (p.Pick(4)) {
|
} else if (p.Pick(4)) {
|
||||||
singleCursor();
|
singleCursor();
|
||||||
} else if (p.Pick(8)) {
|
} else if (p.Pick(8)) {
|
||||||
conwayish();
|
conwayish();
|
||||||
} else if (p.Pick(8)) {
|
} else if (p.Pick(8)) {
|
||||||
glitchPulse();
|
glitchPulse();
|
||||||
}
|
} else if (p.Pick(8)) {
|
||||||
|
cm5();
|
||||||
|
} else if (p.Pick(4) || !connected()) {
|
||||||
|
netget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// trying to debug why we get freezing
|
||||||
|
grid[0] = CHSV(HUE_YELLOW, 255, 255);
|
||||||
|
FastLED.show();
|
||||||
}
|
}
|
104
wallart.py
104
wallart.py
|
@ -1,104 +0,0 @@
|
||||||
import board
|
|
||||||
from digitalio import DigitalInOut, Direction, Pull
|
|
||||||
import adafruit_dotstar as dotstar
|
|
||||||
import adafruit_fancyled.adafruit_fancyled as fancy
|
|
||||||
import time
|
|
||||||
import neopixel
|
|
||||||
import random
|
|
||||||
import microcontroller
|
|
||||||
|
|
||||||
# One pixel connected internally!
|
|
||||||
dot = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
|
||||||
dot[0] = 0
|
|
||||||
|
|
||||||
# Built in red LED
|
|
||||||
led = DigitalInOut(board.D13)
|
|
||||||
led.direction = Direction.OUTPUT
|
|
||||||
|
|
||||||
# NeoPixel strip (of 16 LEDs) connected on D4
|
|
||||||
GRIDLEN = 64
|
|
||||||
grid = neopixel.NeoPixel(board.D4, GRIDLEN, brightness=0.2, auto_write=False, pixel_order=neopixel.GRB)
|
|
||||||
|
|
||||||
|
|
||||||
class GlitchPixel:
|
|
||||||
def __init__(self):
|
|
||||||
self.init()
|
|
||||||
self.nsteps = 64
|
|
||||||
self.step = random.randrange(self.nsteps)
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
self.step = 0
|
|
||||||
self.pos = random.randrange(GRIDLEN)
|
|
||||||
self.color = fancy.CHSV(random.random()).pack()
|
|
||||||
|
|
||||||
def frame(self):
|
|
||||||
bmask = (0xff * self.step // 32) & 0xff
|
|
||||||
if self.step > self.nsteps/2:
|
|
||||||
bmask = 0xff - bmask
|
|
||||||
mask = (bmask << 16) | (bmask << 8) | (bmask << 0)
|
|
||||||
color = self.color & mask
|
|
||||||
grid[self.pos] = color
|
|
||||||
|
|
||||||
self.step += 1
|
|
||||||
if self.step > self.nsteps:
|
|
||||||
self.init()
|
|
||||||
|
|
||||||
def fade():
|
|
||||||
reps = 300 + random.randrange(GRIDLEN)
|
|
||||||
hue = random.randrange(256)
|
|
||||||
colors = [fancy.CHSV(hue, 255, v).pack() for v in range(0, 256, 32)]
|
|
||||||
rcolors = colors[:]
|
|
||||||
rcolors.reverse()
|
|
||||||
colors = colors + rcolors
|
|
||||||
for count in range(reps):
|
|
||||||
pos = count % GRIDLEN
|
|
||||||
for color in colors:
|
|
||||||
grid[pos] = color
|
|
||||||
pos -= 1
|
|
||||||
grid.show()
|
|
||||||
|
|
||||||
def singleCursor():
|
|
||||||
red = fancy.CHSV(0, 210, 127).pack()
|
|
||||||
pos = 20
|
|
||||||
for i in range(80):
|
|
||||||
grid[pos] = red * (i % 2)
|
|
||||||
led.value = not (i % 2)
|
|
||||||
grid.show()
|
|
||||||
time.sleep(0.08)
|
|
||||||
|
|
||||||
def sparkle():
|
|
||||||
white = fancy.CHSV(0, 0, 127).pack()
|
|
||||||
pos = [0,0,0]
|
|
||||||
for i in range(50):
|
|
||||||
for j in range(len(pos)):
|
|
||||||
pos[j] = random.randrange(GRIDLEN)
|
|
||||||
grid[pos[j]] = white
|
|
||||||
grid.show()
|
|
||||||
for p in pos:
|
|
||||||
grid[p] = 0
|
|
||||||
grid.show()
|
|
||||||
|
|
||||||
def glitchPulse():
|
|
||||||
grid.fill(0)
|
|
||||||
pixels = []
|
|
||||||
for i in range(4):
|
|
||||||
p = GlitchPixel()
|
|
||||||
pixels.append(p)
|
|
||||||
|
|
||||||
for f in range(1000):
|
|
||||||
for p in pixels:
|
|
||||||
p.frame()
|
|
||||||
grid.show()
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def loop():
|
|
||||||
fade()
|
|
||||||
singleCursor()
|
|
||||||
sparkle()
|
|
||||||
glitchPulse()
|
|
||||||
# For some reason, this program freezes occasionally.
|
|
||||||
# I don't want to debug CircuitPython.
|
|
||||||
microcontroller.reset()
|
|
||||||
|
|
||||||
while True:
|
|
||||||
loop()
|
|
Loading…
Reference in New Issue