Created
December 1, 2020 17:23
-
-
Save telent/7c839170a89fe8bee30ee4d992416f32 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Adafruit_NeoPixel.h> | |
#include <math.h> | |
#ifdef __AVR__ | |
#include <avr/power.h> | |
#endif | |
#include <ESP8266WiFi.h> | |
#include <PubSubClient.h> | |
#include "wifi-config.h" | |
WiFiClient espClient; | |
PubSubClient client(espClient); | |
unsigned long lastMsg = 0; | |
#define MSG_BUFFER_SIZE (50) | |
char msg[MSG_BUFFER_SIZE]; | |
int value = 0; | |
void setup_wifi() { | |
delay(10); | |
// We start by connecting to a WiFi network | |
Serial.println(); | |
Serial.print("Connecting to "); | |
Serial.println(SSID); | |
WiFi.mode(WIFI_STA); | |
WiFi.begin(SSID, WPA_PASSPHRASE); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
} | |
randomSeed(micros()); | |
Serial.println(""); | |
Serial.println("WiFi connected"); | |
Serial.println("IP address: "); | |
Serial.println(WiFi.localIP()); | |
} | |
void reconnect() { | |
// Loop until we're reconnected | |
while (!client.connected()) { | |
Serial.print("Attempting MQTT connection..."); | |
// Create a random client ID | |
String clientId = "neoxmas-"; | |
clientId += String(random(0xffff), HEX); | |
// Attempt to connect | |
if (client.connect(clientId.c_str(), | |
MQTT_USERNAME, MQTT_PASSWORD )) { | |
Serial.println("connected"); | |
client.subscribe("sensors/neoxmas"); | |
Serial.print(client.state()); | |
} else { | |
Serial.print("failed, rc="); | |
Serial.print(client.state()); | |
Serial.println(" try again in 5 seconds"); | |
// Wait 5 seconds before retrying | |
delay(5000); | |
} | |
} | |
} | |
#define PIN 4 // https://chewett.co.uk/blog/1066/pin-numbering-for-wemos-d1-mini-esp8266/ | |
#define STRIP_LENGTH 150 | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(STRIP_LENGTH, PIN, NEO_GRB + NEO_KHZ800); | |
float zero = 0; | |
int rotation_speed = -20; | |
int brightness = 18; | |
struct hsv { | |
float h,s,v; | |
}; | |
struct loc { | |
int offset; | |
struct hsv color; | |
}; | |
// byte for loc, 3 bytes for h,s,v = 4 bytes per loc | |
// max message size inc headers is 256 bytes so ~ 64 points | |
struct loc initial_config[] = { | |
(struct loc){ 0, (struct hsv){ 0, 1, 0.10} }, | |
(struct loc){ 10, (struct hsv){ 0, 0.8, 0.7} }, | |
(struct loc){ 20, (struct hsv){ 0, 1, 0.10} }, | |
(struct loc){ 50, (struct hsv){ 0, 1, 0.1} }, | |
(struct loc){ 60, (struct hsv){ 120, 0.8, 0.7} }, | |
(struct loc){ 70, (struct hsv){ 0, 1, 0.1} }, | |
(struct loc){ 100, (struct hsv){ 0, 1, 0.1} }, | |
(struct loc){ 110, (struct hsv){ 240, 0.8, 0.7} }, | |
(struct loc){ 120, (struct hsv){ 0, 1, 0.5} }, | |
(struct loc){ 999, (struct hsv){ 350, 0, 0} }, | |
}; | |
struct loc locations[256/4]; | |
void mqtt_receive_cb(char* topic, byte* payload, unsigned int length) { | |
Serial.print("Message arrived ["); | |
Serial.print(topic); | |
Serial.print("] "); | |
int loc=0; | |
rotation_speed = (int)payload[0]; | |
for(int i=1; i< length; loc++, i+=4) { | |
locations[loc].offset = payload[i]; | |
locations[loc].color.h = payload[i+1] * 360.0 / 256; | |
locations[loc].color.s = payload[i+2] / 256.0; | |
locations[loc].color.v = payload[i+3] / 256.0; | |
} | |
locations[loc].offset = -1; | |
for (int i = 0; i < length; i++) { | |
Serial.print((int)payload[i]); | |
Serial.print(" "); | |
} | |
Serial.println(); | |
set_strip(locations); | |
} | |
void set_from_hsv(byte * rgb, struct hsv *hsv) { | |
float chroma = (1 - abs(2 * hsv->v - 1)) * hsv->s; | |
float h = hsv->h/60; | |
Serial.println(h); | |
float x = (1 - abs((int)h % 2 - 1)) * chroma; | |
float r, g, b; | |
r = g = b = 0; | |
if(h < 1) { | |
r=chroma; g=x; b=0; | |
} else if(h < 2) { | |
r = x; g=chroma; b=0; | |
} else if(h < 3) { | |
r=0; | |
g=chroma; | |
b=x; | |
} else if(h < 4) { | |
r=0; | |
g=x; | |
b=chroma; | |
} else if(h < 5) { | |
r=x; g=0; b=chroma; | |
} else { | |
r=chroma; | |
g=0; | |
b=x; | |
} | |
float m = hsv->v - chroma/2; | |
rgb[0] = (byte) brightness*(r+m); | |
rgb[1] = (byte) brightness*(g+m); | |
rgb[2] = (byte) brightness*(b+m); | |
} | |
byte lights[STRIP_LENGTH][3]; | |
struct hsv *interpolate(struct hsv *start, struct hsv *target, | |
int width, int remaining) { | |
float proportion = 1.0 * remaining/width; | |
static hsv r; | |
hsv *result = &r; | |
result->h = start->h*(proportion) + target->h*(1-proportion); | |
result->s = start->s*(proportion) + target->s*(1-proportion); | |
result->v = start->v*(proportion) + target->v*(1-proportion); | |
return result; | |
} | |
void set_strip(struct loc targets[]) { | |
struct loc *target = targets; | |
int i = target->offset; | |
struct hsv * prev_color = &(target->color); | |
while(i< STRIP_LENGTH) { | |
target++; | |
int target_index = (target+1)->offset; | |
if((target->offset > STRIP_LENGTH) || (target->offset < 0)) { | |
/* wrap around */ | |
target = targets; | |
target_index = target->offset + STRIP_LENGTH; | |
} else { | |
target_index = target->offset; | |
} | |
int distance = target_index - i; | |
while(i<= target_index) { | |
hsv *c = interpolate(prev_color, &(target->color), | |
distance, target_index - i); | |
set_from_hsv(lights[i % STRIP_LENGTH], c); | |
i++; | |
} | |
} | |
} | |
int rotated(int i) { | |
return ((int)floor(zero) + i + STRIP_LENGTH) % STRIP_LENGTH; | |
} | |
void setup() { | |
Serial.begin(115200); | |
while (!Serial) {;} | |
Serial.println("HEY "); | |
setup_wifi(); | |
client.setServer(MQTT_SERVER, 1883); | |
client.setCallback(mqtt_receive_cb); | |
strip.begin(); | |
set_strip(initial_config); | |
strip.show(); | |
} | |
void loop() { | |
float dt = 0.01; | |
if (!client.connected()) reconnect(); | |
client.loop(); | |
delay(dt * 1000); | |
zero = (zero + dt*rotation_speed + STRIP_LENGTH) ; | |
while(zero > (1.0* STRIP_LENGTH)) zero -= STRIP_LENGTH; | |
for(int i = 0; i< STRIP_LENGTH; i++) { | |
byte *col = lights[rotated(i)]; | |
strip.setPixelColor(i, strip.Color(col[0], col[1], col[2])); | |
} | |
strip.show(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment