imported from "final" folder
This commit is contained in:
607
.pio/libdeps/esp01_1m/FastLED/examples/Chromancer/Chromancer.ino
Normal file
607
.pio/libdeps/esp01_1m/FastLED/examples/Chromancer/Chromancer.ino
Normal file
@@ -0,0 +1,607 @@
|
||||
/// @file Chromancer.ino
|
||||
/// @brief Hexagonal LED display visualization
|
||||
/// @example Chromancer.ino
|
||||
///
|
||||
/// This sketch is fully compatible with the FastLED web compiler. To use it do the following:
|
||||
/// 1. Install Fastled: `pip install fastled`
|
||||
/// 2. cd into this examples page.
|
||||
/// 3. Run the FastLED web compiler at root: `fastled`
|
||||
/// 4. When the compiler is done a web page will open.
|
||||
|
||||
/*
|
||||
Original Source: https://github.com/ZackFreedman/Chromance
|
||||
GaryWoo's Video: https://www.youtube.com/watch?v=-nSCtxa2Kp0
|
||||
GaryWoo's LedMap: https://gist.github.com/Garywoo/b6cd1ea90cb5e17cc60b01ae68a2b770
|
||||
GaryWoo's presets: https://gist.github.com/Garywoo/82fa67c6e1f9529dc16a01dd97d05d58
|
||||
Chromance wall hexagon source (emotion controlled w/ EmotiBit)
|
||||
Partially cribbed from the DotStar example
|
||||
I smooshed in the ESP32 BasicOTA sketch, too
|
||||
|
||||
(C) Voidstar Lab 2021
|
||||
*/
|
||||
|
||||
#include "fl/sketch_macros.h"
|
||||
#include "fl/warn.h"
|
||||
|
||||
#if !SKETCH_HAS_LOTS_OF_MEMORY
|
||||
// Platform does not have enough memory
|
||||
// Other platforms have weird issues. Will revisit this later.
|
||||
#include <Arduino.h>
|
||||
|
||||
void setup() {
|
||||
// Use Serial.println instead of FL_WARN to prevent optimization away
|
||||
Serial.begin(115200);
|
||||
Serial.println("Chromancer.ino: setup() - Platform has insufficient memory for full demo");
|
||||
}
|
||||
void loop() {
|
||||
// Use Serial.println instead of FL_WARN to prevent optimization away
|
||||
Serial.println("Chromancer.ino: loop() - Platform has insufficient memory for full demo");
|
||||
delay(1000); // Prevent rapid printing
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
#include <FastLED.h>
|
||||
|
||||
#include "fl/screenmap.h"
|
||||
#include "fl/math_macros.h"
|
||||
#include "fl/json.h"
|
||||
#include "fl/ui.h"
|
||||
#include "fl/map.h"
|
||||
|
||||
#include "fl/str.h"
|
||||
|
||||
#include "./screenmap.json.h"
|
||||
#include "./mapping.h"
|
||||
#include "./ripple.h"
|
||||
#include "./detail.h"
|
||||
|
||||
using namespace fl;
|
||||
|
||||
enum {
|
||||
BlackStrip = 0,
|
||||
GreenStrip = 1,
|
||||
RedStrip = 2,
|
||||
BlueStrip = 3,
|
||||
};
|
||||
|
||||
|
||||
// Strips are different lengths because I am a dumb
|
||||
|
||||
constexpr int lengths[] = {
|
||||
154, // Black strip
|
||||
168, // Green strip
|
||||
84, // Red strip
|
||||
154 // Blue strip
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// non emscripten uses separate arrays for each strip. Eventually emscripten
|
||||
// should support this as well but right now we don't
|
||||
CRGB leds0[lengths[BlackStrip]] = {};
|
||||
CRGB leds1[lengths[GreenStrip]] = {};
|
||||
CRGB leds2[lengths[RedStrip]] = {}; // Red
|
||||
CRGB leds3[lengths[BlueStrip]] = {};
|
||||
CRGB *leds[] = {leds0, leds1, leds2, leds3};
|
||||
|
||||
|
||||
byte ledColors[40][14][3]; // LED buffer - each ripple writes to this, then we
|
||||
// write this to the strips
|
||||
//float decay = 0.97; // Multiply all LED's by this amount each tick to create
|
||||
// fancy fading tails
|
||||
|
||||
UISlider sliderDecay("decay", .97f, .8, 1.0, .01);
|
||||
|
||||
// These ripples are endlessly reused so we don't need to do any memory
|
||||
// management
|
||||
#define numberOfRipples 30
|
||||
Ripple ripples[numberOfRipples] = {
|
||||
Ripple(0), Ripple(1), Ripple(2), Ripple(3), Ripple(4), Ripple(5),
|
||||
Ripple(6), Ripple(7), Ripple(8), Ripple(9), Ripple(10), Ripple(11),
|
||||
Ripple(12), Ripple(13), Ripple(14), Ripple(15), Ripple(16), Ripple(17),
|
||||
Ripple(18), Ripple(19), Ripple(20), Ripple(21), Ripple(22), Ripple(23),
|
||||
Ripple(24), Ripple(25), Ripple(26), Ripple(27), Ripple(28), Ripple(29),
|
||||
};
|
||||
|
||||
// Biometric detection and interpretation
|
||||
// IR (heartbeat) is used to fire outward ripples
|
||||
float lastIrReading; // When our heart pumps, reflected IR drops sharply
|
||||
float highestIrReading; // These vars let us detect this drop
|
||||
unsigned long
|
||||
lastHeartbeat; // Track last heartbeat so we can detect noise/disconnections
|
||||
#define heartbeatLockout \
|
||||
500 // Heartbeats that happen within this many milliseconds are ignored
|
||||
#define heartbeatDelta 300 // Drop in reflected IR that constitutes a heartbeat
|
||||
|
||||
// Heartbeat color ripples are proportional to skin temperature
|
||||
#define lowTemperature 33.0 // Resting temperature
|
||||
#define highTemperature 37.0 // Really fired up
|
||||
float lastKnownTemperature =
|
||||
(lowTemperature + highTemperature) /
|
||||
2.0; // Carries skin temperature from temperature callback to IR callback
|
||||
|
||||
// EDA code was too unreliable and was cut.
|
||||
// TODO: Rebuild EDA code
|
||||
|
||||
// Gyroscope is used to reject data if you're moving too much
|
||||
#define gyroAlpha 0.9 // Exponential smoothing constant
|
||||
#define gyroThreshold \
|
||||
300 // Minimum angular velocity total (X+Y+Z) that disqualifies readings
|
||||
float gyroX, gyroY, gyroZ;
|
||||
|
||||
// If you don't have an EmotiBit or don't feel like wearing it, that's OK
|
||||
// We'll fire automatic pulses
|
||||
#define randomPulsesEnabled true // Fire random rainbow pulses from random nodes
|
||||
#define cubePulsesEnabled true // Draw cubes at random nodes
|
||||
UICheckbox starburstPulsesEnabled("Starburst Pulses", true);
|
||||
UICheckbox simulatedBiometricsEnabled("Simulated Biometrics", true);
|
||||
|
||||
#define autoPulseTimeout \
|
||||
5000 // If no heartbeat is received in this many ms, begin firing
|
||||
// random/simulated pulses
|
||||
#define randomPulseTime 2000 // Fire a random pulse every (this many) ms
|
||||
unsigned long lastRandomPulse;
|
||||
byte lastAutoPulseNode = 255;
|
||||
|
||||
byte numberOfAutoPulseTypes =
|
||||
randomPulsesEnabled + cubePulsesEnabled + int(starburstPulsesEnabled);
|
||||
byte currentAutoPulseType = 255;
|
||||
#define autoPulseChangeTime 30000
|
||||
unsigned long lastAutoPulseChange;
|
||||
|
||||
#define simulatedHeartbeatBaseTime \
|
||||
600 // Fire a simulated heartbeat pulse after at least this many ms
|
||||
#define simulatedHeartbeatVariance \
|
||||
200 // Add random jitter to simulated heartbeat
|
||||
#define simulatedEdaBaseTime 1000 // Same, but for inward EDA pulses
|
||||
#define simulatedEdaVariance 10000
|
||||
unsigned long nextSimulatedHeartbeat;
|
||||
unsigned long nextSimulatedEda;
|
||||
|
||||
// Helper function to check if a node is on the border
|
||||
bool isNodeOnBorder(byte node) {
|
||||
for (int i = 0; i < numberOfBorderNodes; i++) {
|
||||
if (node == borderNodes[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UITitle title("Chromancer");
|
||||
UIDescription description("Take 6 seconds to boot up. Chromancer is a wall-mounted hexagonal LED display that originally reacted to biometric data from an EmotiBit sensor. It visualizes your heartbeat, skin temperature, and movement in real-time. Chromancer also has a few built-in effects that can be triggered with the push of a button. Enjoy!");
|
||||
UICheckbox allWhite("All White", false);
|
||||
|
||||
UIButton simulatedHeartbeat("Simulated Heartbeat");
|
||||
UIButton triggerStarburst("Trigger Starburst");
|
||||
UIButton triggerRainbowCube("Rainbow Cube");
|
||||
UIButton triggerBorderWave("Border Wave");
|
||||
UIButton triggerSpiral("Spiral Wave");
|
||||
bool wasHeartbeatClicked = false;
|
||||
bool wasStarburstClicked = false;
|
||||
bool wasRainbowCubeClicked = false;
|
||||
bool wasBorderWaveClicked = false;
|
||||
bool wasSpiralClicked = false;
|
||||
|
||||
// Group related UI elements using UIGroup template multi-argument constructor
|
||||
UIGroup effectTriggers("Effect Triggers", simulatedHeartbeat, triggerStarburst, triggerRainbowCube, triggerBorderWave, triggerSpiral);
|
||||
UIGroup automationControls("Automation", starburstPulsesEnabled, simulatedBiometricsEnabled);
|
||||
UIGroup displayControls("Display", sliderDecay, allWhite);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("*** LET'S GOOOOO ***");
|
||||
|
||||
Serial.println("JSON SCREENMAP");
|
||||
Serial.println(JSON_SCREEN_MAP);
|
||||
|
||||
fl::fl_map<fl::string, ScreenMap> segmentMaps;
|
||||
ScreenMap::ParseJson(JSON_SCREEN_MAP, &segmentMaps);
|
||||
|
||||
printf("Parsed %d segment maps\n", int(segmentMaps.size()));
|
||||
for (auto kv : segmentMaps) {
|
||||
Serial.print(kv.first.c_str());
|
||||
Serial.print(" ");
|
||||
Serial.println(kv.second.getLength());
|
||||
}
|
||||
|
||||
|
||||
// ScreenMap screenmaps[4];
|
||||
ScreenMap red, black, green, blue;
|
||||
bool ok = true;
|
||||
|
||||
auto red_it = segmentMaps.find("red_segment");
|
||||
ok = (red_it != segmentMaps.end()) && ok;
|
||||
if (red_it != segmentMaps.end()) red = red_it->second;
|
||||
|
||||
auto black_it = segmentMaps.find("back_segment");
|
||||
ok = (black_it != segmentMaps.end()) && ok;
|
||||
if (black_it != segmentMaps.end()) black = black_it->second;
|
||||
|
||||
auto green_it = segmentMaps.find("green_segment");
|
||||
ok = (green_it != segmentMaps.end()) && ok;
|
||||
if (green_it != segmentMaps.end()) green = green_it->second;
|
||||
|
||||
auto blue_it = segmentMaps.find("blue_segment");
|
||||
ok = (blue_it != segmentMaps.end()) && ok;
|
||||
if (blue_it != segmentMaps.end()) blue = blue_it->second;
|
||||
if (!ok) {
|
||||
Serial.println("Failed to get all segment maps");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CRGB* red_leds = leds[RedStrip];
|
||||
CRGB* black_leds = leds[BlackStrip];
|
||||
CRGB* green_leds = leds[GreenStrip];
|
||||
CRGB* blue_leds = leds[BlueStrip];
|
||||
|
||||
FastLED.addLeds<WS2812, 2>(black_leds, lengths[BlackStrip]).setScreenMap(black);
|
||||
FastLED.addLeds<WS2812, 3>(green_leds, lengths[GreenStrip]).setScreenMap(green);
|
||||
FastLED.addLeds<WS2812, 1>(red_leds, lengths[RedStrip]).setScreenMap(red);
|
||||
FastLED.addLeds<WS2812, 4>(blue_leds, lengths[BlueStrip]).setScreenMap(blue);
|
||||
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
unsigned long benchmark = millis();
|
||||
FL_UNUSED(benchmark);
|
||||
|
||||
// Fade all dots to create trails
|
||||
for (int strip = 0; strip < 40; strip++) {
|
||||
for (int led = 0; led < 14; led++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ledColors[strip][led][i] *= sliderDecay.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numberOfRipples; i++) {
|
||||
ripples[i].advance(ledColors);
|
||||
}
|
||||
|
||||
for (int segment = 0; segment < 40; segment++) {
|
||||
for (int fromBottom = 0; fromBottom < 14; fromBottom++) {
|
||||
int strip = ledAssignments[segment][0];
|
||||
int led = round(fmap(fromBottom, 0, 13, ledAssignments[segment][2],
|
||||
ledAssignments[segment][1]));
|
||||
leds[strip][led] = CRGB(ledColors[segment][fromBottom][0],
|
||||
ledColors[segment][fromBottom][1],
|
||||
ledColors[segment][fromBottom][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (allWhite) {
|
||||
// for all strips
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < lengths[i]; j++) {
|
||||
leds[i][j] = CRGB::White;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FastLED.show();
|
||||
|
||||
|
||||
// Check if buttons were clicked
|
||||
wasHeartbeatClicked = bool(simulatedHeartbeat);
|
||||
wasStarburstClicked = bool(triggerStarburst);
|
||||
wasRainbowCubeClicked = bool(triggerRainbowCube);
|
||||
wasBorderWaveClicked = bool(triggerBorderWave);
|
||||
wasSpiralClicked = bool(triggerSpiral);
|
||||
|
||||
if (wasSpiralClicked) {
|
||||
// Trigger spiral wave effect from center
|
||||
unsigned int baseColor = random(0xFFFF);
|
||||
byte centerNode = 15; // Center node
|
||||
|
||||
// Create 6 ripples in a spiral pattern
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (nodeConnections[centerNode][i] >= 0) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
centerNode, i,
|
||||
Adafruit_DotStar_ColorHSV(
|
||||
baseColor + (0xFFFF / 6) * i, 255, 255),
|
||||
0.3 + (i * 0.1), // Varying speeds creates spiral effect
|
||||
2000,
|
||||
i % 2 ? alwaysTurnsLeft : alwaysTurnsRight); // Alternating turn directions
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lastHeartbeat = millis();
|
||||
}
|
||||
|
||||
if (wasBorderWaveClicked) {
|
||||
// Trigger immediate border wave effect
|
||||
unsigned int baseColor = random(0xFFFF);
|
||||
|
||||
// Start ripples from each border node in sequence
|
||||
for (int i = 0; i < numberOfBorderNodes; i++) {
|
||||
byte node = borderNodes[i];
|
||||
// Find an inward direction
|
||||
for (int dir = 0; dir < 6; dir++) {
|
||||
if (nodeConnections[node][dir] >= 0 &&
|
||||
!isNodeOnBorder(nodeConnections[node][dir])) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
node, dir,
|
||||
Adafruit_DotStar_ColorHSV(
|
||||
baseColor + (0xFFFF / numberOfBorderNodes) * i,
|
||||
255, 255),
|
||||
.4, 2000, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastHeartbeat = millis();
|
||||
}
|
||||
|
||||
if (wasRainbowCubeClicked) {
|
||||
// Trigger immediate rainbow cube effect
|
||||
int node = cubeNodes[random(numberOfCubeNodes)];
|
||||
unsigned int baseColor = random(0xFFFF);
|
||||
byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (nodeConnections[node][i] >= 0) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
node, i,
|
||||
Adafruit_DotStar_ColorHSV(
|
||||
baseColor + (0xFFFF / 6) * i, 255, 255),
|
||||
.5, 2000, behavior);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lastHeartbeat = millis();
|
||||
}
|
||||
|
||||
if (wasStarburstClicked) {
|
||||
// Trigger immediate starburst effect
|
||||
unsigned int baseColor = random(0xFFFF);
|
||||
byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
starburstNode, i,
|
||||
Adafruit_DotStar_ColorHSV(
|
||||
baseColor + (0xFFFF / 6) * i, 255, 255),
|
||||
.65, 1500, behavior);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastHeartbeat = millis();
|
||||
}
|
||||
|
||||
if (wasHeartbeatClicked) {
|
||||
// Trigger immediate heartbeat effect
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(15, i, 0xEE1111,
|
||||
float(random(100)) / 100.0 * .1 + .4, 1000, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastHeartbeat = millis();
|
||||
}
|
||||
|
||||
if (millis() - lastHeartbeat >= autoPulseTimeout) {
|
||||
// When biometric data is unavailable, visualize at random
|
||||
if (numberOfAutoPulseTypes &&
|
||||
millis() - lastRandomPulse >= randomPulseTime) {
|
||||
unsigned int baseColor = random(0xFFFF);
|
||||
|
||||
if (currentAutoPulseType == 255 ||
|
||||
(numberOfAutoPulseTypes > 1 &&
|
||||
millis() - lastAutoPulseChange >= autoPulseChangeTime)) {
|
||||
byte possiblePulse = 255;
|
||||
while (true) {
|
||||
possiblePulse = random(3);
|
||||
|
||||
if (possiblePulse == currentAutoPulseType)
|
||||
continue;
|
||||
|
||||
switch (possiblePulse) {
|
||||
case 0:
|
||||
if (!randomPulsesEnabled)
|
||||
continue;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (!cubePulsesEnabled)
|
||||
continue;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (!starburstPulsesEnabled)
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
currentAutoPulseType = possiblePulse;
|
||||
lastAutoPulseChange = millis();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (currentAutoPulseType) {
|
||||
case 0: {
|
||||
int node = 0;
|
||||
bool foundStartingNode = false;
|
||||
while (!foundStartingNode) {
|
||||
node = random(25);
|
||||
foundStartingNode = true;
|
||||
for (int i = 0; i < numberOfBorderNodes; i++) {
|
||||
// Don't fire a pulse on one of the outer nodes - it
|
||||
// looks boring
|
||||
if (node == borderNodes[i])
|
||||
foundStartingNode = false;
|
||||
}
|
||||
|
||||
if (node == lastAutoPulseNode)
|
||||
foundStartingNode = false;
|
||||
}
|
||||
|
||||
lastAutoPulseNode = node;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (nodeConnections[node][i] >= 0) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
node, i,
|
||||
// strip0.ColorHSV(baseColor
|
||||
// + (0xFFFF / 6) * i,
|
||||
// 255, 255),
|
||||
Adafruit_DotStar_ColorHSV(baseColor, 255,
|
||||
255),
|
||||
float(random(100)) / 100.0 * .2 + .5, 3000,
|
||||
1);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
int node = cubeNodes[random(numberOfCubeNodes)];
|
||||
|
||||
while (node == lastAutoPulseNode)
|
||||
node = cubeNodes[random(numberOfCubeNodes)];
|
||||
|
||||
lastAutoPulseNode = node;
|
||||
|
||||
byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (nodeConnections[node][i] >= 0) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
node, i,
|
||||
// strip0.ColorHSV(baseColor
|
||||
// + (0xFFFF / 6) * i,
|
||||
// 255, 255),
|
||||
Adafruit_DotStar_ColorHSV(baseColor, 255,
|
||||
255),
|
||||
.5, 2000, behavior);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
|
||||
|
||||
lastAutoPulseNode = starburstNode;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
starburstNode, i,
|
||||
Adafruit_DotStar_ColorHSV(
|
||||
baseColor + (0xFFFF / 6) * i, 255, 255),
|
||||
.65, 1500, behavior);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
lastRandomPulse = millis();
|
||||
}
|
||||
|
||||
if (simulatedBiometricsEnabled) {
|
||||
// Simulated heartbeat
|
||||
if (millis() >= nextSimulatedHeartbeat) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
ripples[j].start(
|
||||
15, i, 0xEE1111,
|
||||
float(random(100)) / 100.0 * .1 + .4, 1000, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextSimulatedHeartbeat = millis() + simulatedHeartbeatBaseTime +
|
||||
random(simulatedHeartbeatVariance);
|
||||
}
|
||||
|
||||
// Simulated EDA ripples
|
||||
if (millis() >= nextSimulatedEda) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int j = 0; j < numberOfRipples; j++) {
|
||||
if (ripples[j].state == dead) {
|
||||
byte targetNode =
|
||||
borderNodes[random(numberOfBorderNodes)];
|
||||
byte direction = 255;
|
||||
|
||||
while (direction == 255) {
|
||||
direction = random(6);
|
||||
if (nodeConnections[targetNode][direction] < 0)
|
||||
direction = 255;
|
||||
}
|
||||
|
||||
ripples[j].start(
|
||||
targetNode, direction, 0x1111EE,
|
||||
float(random(100)) / 100.0 * .5 + 2, 300, 2);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextSimulatedEda = millis() + simulatedEdaBaseTime +
|
||||
random(simulatedEdaVariance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Serial.print("Benchmark: ");
|
||||
// Serial.println(millis() - benchmark);
|
||||
}
|
||||
|
||||
#endif // __AVR__
|
||||
Reference in New Issue
Block a user