Added different modes. For now there are AM_CORNERS and AM_NODES.
This commit is contained in:
parent
fdf357a3a1
commit
77eaea81d1
@ -13,7 +13,11 @@
|
|||||||
// Examples, assuming EDGES_PER_PART == 3:
|
// Examples, assuming EDGES_PER_PART == 3:
|
||||||
// Example: Nodes arranged in a circle: {1, 2, 2, 2, 2}
|
// Example: Nodes arranged in a circle: {1, 2, 2, 2, 2}
|
||||||
// Example: Nodes arranged in a line: {1, 2, 1, 2, 1, 2}
|
// Example: Nodes arranged in a line: {1, 2, 1, 2, 1, 2}
|
||||||
#define NODE_COUNT 3
|
#define NODE_COUNT 5
|
||||||
#define LAYOUT {2, 1}
|
#define LAYOUT {2, 1, 1, 2}
|
||||||
|
|
||||||
#define LED_COUNT NODE_COUNT * CORNERS_PER_PART * LEDS_PER_CORNER
|
#define LED_COUNT NODE_COUNT * CORNERS_PER_PART * LEDS_PER_CORNER
|
||||||
|
|
||||||
|
#define SPEEDUP 1
|
||||||
|
|
||||||
|
//#define TEST_MODE
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <FastLED.h>
|
#include "my_fastled.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "edge.h"
|
#include "edge.h"
|
||||||
@ -18,12 +18,18 @@ class Corner {
|
|||||||
bool effect_running = false;
|
bool effect_running = false;
|
||||||
uint8_t color_blend_state = 255;
|
uint8_t color_blend_state = 255;
|
||||||
uint16_t effect_id;
|
uint16_t effect_id;
|
||||||
bool loop();
|
uint8_t effect_speed;
|
||||||
|
//bool loop();
|
||||||
void draw();
|
void draw();
|
||||||
void blend_to(CRGB color, uint16_t effect_id=0);
|
void blend_to(CRGB color, uint16_t effect_id=0, uint8_t effect_speed=0);
|
||||||
void add_led(uint16_t led_id);
|
void add_led(uint16_t led_id);
|
||||||
void merge_leds(Corner* c);
|
void merge_leds(Corner* c);
|
||||||
|
void step();
|
||||||
|
void infect(uint8_t short_level, uint8_t long_level);
|
||||||
|
bool is_finished();
|
||||||
|
void set_color(CRGB color);
|
||||||
|
bool reached_level(uint8_t level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void infect(std::vector<Corner*>* neighbours);
|
void _infect(std::vector<Corner*>* neighbours);
|
||||||
};
|
};
|
4
include/my_fastled.h
Normal file
4
include/my_fastled.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define FASTLED_INTERNAL
|
||||||
|
#include <FastLED.h>
|
@ -13,4 +13,10 @@ class Node {
|
|||||||
Corner* _corners[CORNERS_PER_PART];
|
Corner* _corners[CORNERS_PER_PART];
|
||||||
Node(uint16_t number);
|
Node(uint16_t number);
|
||||||
Node* create_neighbour(uint8_t edge);
|
Node* create_neighbour(uint8_t edge);
|
||||||
|
|
||||||
|
void blend_to(CRGB color, uint16_t effect_id=0, uint8_t effect_speed=0);
|
||||||
|
void set_color(CRGB color);
|
||||||
|
void infect(uint8_t level);
|
||||||
|
void step();
|
||||||
|
void draw();
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <FastLED.h>
|
#include "my_fastled.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -8,8 +8,13 @@
|
|||||||
#include "corner.h"
|
#include "corner.h"
|
||||||
|
|
||||||
|
|
||||||
extern std::list<Node*> nodes;
|
extern std::vector<Node*> nodes;
|
||||||
extern std::list<Edge*> edges;
|
extern std::list<Edge*> edges;
|
||||||
extern std::vector<Corner*> corners;
|
extern std::vector<Corner*> corners;
|
||||||
|
|
||||||
extern CRGB leds[LED_COUNT];
|
extern CRGB leds[LED_COUNT];
|
||||||
|
|
||||||
|
enum AnimationMode {
|
||||||
|
AM_CORNERS,
|
||||||
|
AM_NODES
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <FastLED.h>
|
#include "my_fastled.h"
|
||||||
|
|
||||||
#define LOG(...) Serial.printf(__VA_ARGS__)
|
#define LOG(...) Serial.printf(__VA_ARGS__)
|
||||||
#define LOGln(...) Serial.printf(__VA_ARGS__); Serial.println()
|
#define LOGln(...) Serial.printf(__VA_ARGS__); Serial.println()
|
||||||
|
@ -12,59 +12,66 @@ void Corner::draw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Corner::infect(std::vector<Corner*>* neighbours) {
|
void Corner::_infect(std::vector<Corner*>* neighbours) {
|
||||||
for(Corner* c : *neighbours) {
|
for(Corner* c : *neighbours) {
|
||||||
if (c==nullptr) continue;
|
if (c==nullptr) continue;
|
||||||
c->blend_to(this->target_color, this->effect_id);
|
c->blend_to(this->target_color, this->effect_id, effect_speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Corner::loop() {
|
void Corner::step() {
|
||||||
if (this->color_blend_state < 255) {
|
if (this->color_blend_state < 255) {
|
||||||
this->color = blend(this->source_color, this->target_color, color_blend_state);
|
this->color = blend(this->source_color, this->target_color, color_blend_state);
|
||||||
color_blend_state++;
|
this->color_blend_state = (this->color_blend_state + effect_speed > 255) ? 255 : this->color_blend_state + effect_speed;
|
||||||
|
if (this->color_blend_state==255) {
|
||||||
|
this->color = this->target_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (color_blend_state == 200) {
|
void Corner::infect(uint8_t infect_short_level, uint8_t infect_long_level) {
|
||||||
|
if (reached_level(infect_short_level)) {
|
||||||
|
_infect(&_short_neighbours);
|
||||||
|
}
|
||||||
|
if (reached_level(infect_long_level)) {
|
||||||
|
_infect(&_long_neighbours);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Corner::reached_level(uint8_t level) {
|
||||||
|
uint8_t old_cbs = color_blend_state >= effect_speed ? color_blend_state - effect_speed : 0;
|
||||||
|
return (old_cbs < level && color_blend_state >= level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*bool Corner::loop() {
|
||||||
|
if (this->color_blend_state < 255) {
|
||||||
|
this->color = blend(this->source_color, this->target_color, color_blend_state);
|
||||||
|
if (255 - color_blend_state >= effect_speed) {
|
||||||
|
color_blend_state += effect_speed;
|
||||||
|
} else {
|
||||||
|
color_blend_state = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color_blend_state >= 200 && color_blend_state-effect_speed<200) {
|
||||||
infect(&_long_neighbours);
|
infect(&_long_neighbours);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color_blend_state==75) {
|
if (color_blend_state>=75 && color_blend_state-effect_speed<75) {
|
||||||
infect(&_short_neighbours);
|
infect(&_short_neighbours);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (color_blend_state==255) {
|
if (color_blend_state==255) {
|
||||||
this->color = this->target_color;
|
this->color = this->target_color;
|
||||||
}
|
}
|
||||||
/* LOGln("I am %p and have %d long neighbours:", this, _long_neighbours.size());
|
|
||||||
for(Corner* c1 : _long_neighbours) {
|
|
||||||
if (c1==nullptr) continue;
|
|
||||||
c1->blend_to(this->target_color, this->effect_id);
|
|
||||||
|
|
||||||
LOGln("c1: cbs:%d, target_color.r:%d", c1->color_blend_state, c1->target_color.r);
|
|
||||||
}
|
|
||||||
LOGln("long neighbours done.");
|
|
||||||
//LOGln("Address of my short neighbours: %p", &_short_neighbours);
|
|
||||||
//delay(10);
|
|
||||||
LOGln("I am %p and have %d short neighbours:", this, _short_neighbours.size());
|
|
||||||
for(Corner* c2 : _short_neighbours) {
|
|
||||||
if (c2==nullptr) continue;
|
|
||||||
LOGln("c2: %p", c2);
|
|
||||||
c2->blend_to(this->target_color, this->effect_id);
|
|
||||||
|
|
||||||
LOGln("c2: cbs:%d, target_color.r:%d", c2->color_blend_state, c2->target_color.r);
|
|
||||||
}
|
|
||||||
LOGln("short neighbours done.");
|
|
||||||
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->draw();
|
this->draw();
|
||||||
|
|
||||||
return color_blend_state < 255;
|
return color_blend_state < 255;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void Corner::blend_to(CRGB target, uint16_t eid) {
|
void Corner::blend_to(CRGB target, uint16_t eid, uint8_t effect_speed) {
|
||||||
LOGln("blendTo called. Corner: %p, target: %d,%d,%d, eid: %d, 'old' effect_id: %d", this, target.r, target.g, target.b, eid, effect_id);
|
LOGln("blendTo called. Corner: %p, target: %d,%d,%d, eid: %d, 'old' effect_id: %d, speed: %d", this, target.r, target.g, target.b, eid, effect_id, effect_speed);
|
||||||
if (eid==0) {
|
if (eid==0) {
|
||||||
this->effect_id = random16();
|
this->effect_id = random16();
|
||||||
LOGln("Set effect_id to %d", this->effect_id);
|
LOGln("Set effect_id to %d", this->effect_id);
|
||||||
@ -75,6 +82,11 @@ void Corner::blend_to(CRGB target, uint16_t eid) {
|
|||||||
}
|
}
|
||||||
this->effect_id = eid;
|
this->effect_id = eid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (effect_speed==0) {
|
||||||
|
effect_speed = random8(3) + 1;
|
||||||
|
}
|
||||||
|
this->effect_speed = effect_speed;
|
||||||
|
|
||||||
this->source_color = this->color;
|
this->source_color = this->color;
|
||||||
this->target_color = target;
|
this->target_color = target;
|
||||||
@ -89,4 +101,13 @@ void Corner::merge_leds(Corner* c) {
|
|||||||
for(uint16_t led : c->_leds) {
|
for(uint16_t led : c->_leds) {
|
||||||
_leds.push_back(led);
|
_leds.push_back(led);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Corner::is_finished() {
|
||||||
|
return color_blend_state < 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Corner::set_color(CRGB color) {
|
||||||
|
this->color = color;
|
||||||
|
this->color_blend_state = 255;
|
||||||
}
|
}
|
98
src/main.cpp
98
src/main.cpp
@ -1,5 +1,6 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <FastLED.h>
|
#include <ESP8266WiFi.h>
|
||||||
|
#include "my_fastled.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
@ -7,12 +8,18 @@
|
|||||||
#include "corner.h"
|
#include "corner.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
|
|
||||||
std::list<Node*> nodes;
|
std::vector<Node*> nodes;
|
||||||
std::list<Edge*> edges;
|
std::list<Edge*> edges;
|
||||||
std::vector<Corner*> corners;
|
std::vector<Corner*> corners;
|
||||||
|
|
||||||
CRGB leds[LED_COUNT];
|
CRGB leds[LED_COUNT];
|
||||||
|
|
||||||
|
AnimationMode mode = AM_CORNERS;
|
||||||
|
|
||||||
|
#ifdef TEST_MODE
|
||||||
|
uint8_t base_hue = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool looping;
|
bool looping;
|
||||||
|
|
||||||
void setup_layout() {
|
void setup_layout() {
|
||||||
@ -33,12 +40,10 @@ void setup_layout() {
|
|||||||
edges.push_back(edge);
|
edges.push_back(edge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*for(Corner* corner: node->corners) {
|
LOGln("Node %p:", node);
|
||||||
auto c = std::find(corners.begin(), corners.end(), corner);
|
for(Node* n : node->neighbours) {
|
||||||
if (c == corners.end()) {
|
LOGln(" %p", n);
|
||||||
corners.push_back(corner);
|
}
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Corner* corner: corners) {
|
for(Corner* corner: corners) {
|
||||||
@ -64,35 +69,80 @@ void setup_fastled() {
|
|||||||
FastLED.addLeds<WS2812B, 5, GRB>(leds, LEDS_PER_CORNER * CORNERS_PER_PART * NODE_COUNT).setCorrection(TypicalLEDStrip);
|
FastLED.addLeds<WS2812B, 5, GRB>(leds, LEDS_PER_CORNER * CORNERS_PER_PART * NODE_COUNT).setCorrection(TypicalLEDStrip);
|
||||||
LOGln("LEDs: %3d", LED_COUNT);
|
LOGln("LEDs: %3d", LED_COUNT);
|
||||||
FastLED.setBrightness(255);
|
FastLED.setBrightness(255);
|
||||||
|
FastLED.setDither(DISABLE_DITHER);
|
||||||
set_all_leds(CRGB::Black);
|
set_all_leds(CRGB::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setup_wifi() {
|
||||||
|
LOGln("Starting WiFi scan for RNG initialization...");
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.disconnect();
|
||||||
|
uint16_t seed = 0;
|
||||||
|
int n = WiFi.scanNetworks();
|
||||||
|
LOGln("%d WiFi networks found", n);
|
||||||
|
for(int i=0; i<n; i++) {
|
||||||
|
LOGln(" %s, %d dB", WiFi.SSID(i).c_str(), WiFi.RSSI(i));
|
||||||
|
seed = (seed << 2) | (WiFi.RSSI(i) & 0x03);
|
||||||
|
}
|
||||||
|
LOGln("WiFi scan done. Generated seed is 0x%04x", seed);
|
||||||
|
random16_set_seed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(74880);
|
Serial.begin(74880);
|
||||||
LOGln("ESPleaf starting.");
|
LOGln("ESPleaf starting.");
|
||||||
|
|
||||||
setup_layout();
|
setup_layout();
|
||||||
setup_fastled();
|
setup_fastled();
|
||||||
|
setup_wifi();
|
||||||
|
|
||||||
|
#ifdef TEST_MODE
|
||||||
|
LOGln("TEST_MODE is active!");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// put your main code here, to run repeatedly:
|
#ifdef TEST_MODE
|
||||||
EVERY_N_MILLISECONDS(20) {
|
EVERY_N_MILLISECONDS(20) {
|
||||||
looping = false;
|
int i=0;
|
||||||
for(Corner* corner: corners) {
|
for(Node* node : nodes) {
|
||||||
looping = corner->loop() || looping;
|
CHSV color(base_hue + 150*i, 255, 255);
|
||||||
|
for(int j=0; j<CORNERS_PER_PART*LEDS_PER_CORNER; j++) {
|
||||||
|
leds[i*CORNERS_PER_PART*LEDS_PER_CORNER+j] = color;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
base_hue += 1;
|
||||||
}
|
}
|
||||||
FastLED.show();
|
#else
|
||||||
|
// Normal mode
|
||||||
|
EVERY_N_MILLISECONDS(40 / SPEEDUP) {
|
||||||
|
looping = false;
|
||||||
|
|
||||||
/*if (!looping) {
|
if (mode == AM_CORNERS) {
|
||||||
LOGln("corners.size(): %d", corners.size());
|
for(Corner* corner: corners) {
|
||||||
uint16_t cid = random16(corners.size());
|
corner->step();
|
||||||
LOGln("cid: %d", cid);
|
corner->infect(75, 200);
|
||||||
Corner* start = corners[cid];
|
looping |= !corner->is_finished();
|
||||||
start->blend_to(CHSV(random8(), 255, 255));
|
corner->draw();
|
||||||
}*/
|
}
|
||||||
if (random8()==42) {
|
|
||||||
corners[random16(corners.size())]->blend_to(CHSV(random8(), 255, 255));
|
if (random8(128)==0) {
|
||||||
|
corners[random16(corners.size())]->blend_to(CHSV(random8(), 255, 255));
|
||||||
|
}
|
||||||
|
} else if (mode == AM_NODES) {
|
||||||
|
for(Node* node : nodes) {
|
||||||
|
node->step();
|
||||||
|
node->infect(128);
|
||||||
|
node->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random8(128)==0) {
|
||||||
|
nodes[random8(nodes.size())]->blend_to(CHSV(random8(), 255, 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
FastLED.show();
|
||||||
}
|
}
|
37
src/node.cpp
37
src/node.cpp
@ -1,5 +1,6 @@
|
|||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "prototypes.h"
|
#include "prototypes.h"
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
Node::Node(uint16_t number) {
|
Node::Node(uint16_t number) {
|
||||||
_number = number;
|
_number = number;
|
||||||
@ -53,4 +54,40 @@ Node* Node::create_neighbour(uint8_t edge) {
|
|||||||
node->corners[CORNERS_PER_PART-1] = c;
|
node->corners[CORNERS_PER_PART-1] = c;
|
||||||
*/
|
*/
|
||||||
return node;
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::blend_to(CRGB color, uint16_t effect_id, uint8_t effect_speed) {
|
||||||
|
LOGln("Node::blend_to called. this:%p", this);
|
||||||
|
if (effect_speed == 0) effect_speed = random8(2)+1;
|
||||||
|
if (effect_id == 0) effect_id = random16();
|
||||||
|
for(Corner* corner : this->_corners) {
|
||||||
|
corner->blend_to(color, effect_id, effect_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::step() {
|
||||||
|
for (Corner* corner : this->_corners) {
|
||||||
|
corner->step();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::draw() {
|
||||||
|
for (Corner* corner : this->_corners) {
|
||||||
|
corner->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::set_color(CRGB color) {
|
||||||
|
for(Corner* corner : this->_corners) {
|
||||||
|
corner->set_color(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::infect(uint8_t level) {
|
||||||
|
if (this->_corners[0]->reached_level(level)) {
|
||||||
|
for (Node* neighbour : neighbours) {
|
||||||
|
if (neighbour == nullptr) continue;
|
||||||
|
neighbour->blend_to(_corners[0]->target_color, _corners[0]->effect_id, _corners[0]->effect_speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user