108 lines
4.4 KiB
Arduino
108 lines
4.4 KiB
Arduino
|
/* Plasma
|
||
|
*
|
||
|
* By: Andrew Tuline
|
||
|
*
|
||
|
* Date: July, 2017
|
||
|
*
|
||
|
* This demonstrates 2D sinusoids in 1D using 16 bit math.
|
||
|
*
|
||
|
* It runs at about 450 fps on an Arduino Nano with 60 APA102's. That would be FAST.
|
||
|
*
|
||
|
*
|
||
|
* References:
|
||
|
*
|
||
|
* https://www.bidouille.org/prog/plasma
|
||
|
* http://lodev.org/cgtutor/plasma.html
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
// Use qsuba for smooth pixel colouring and qsubd for non-smooth pixel colouring
|
||
|
#define qsubd(x, b) ((x>b)?b:0) // Digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value.
|
||
|
#define qsuba(x, b) ((x>b)?x-b:0) // Analog Unsigned subtraction macro. if result <0, then => 0
|
||
|
|
||
|
#include "FastLED.h" // FastLED library. Preferably the latest copy of FastLED 2.1.
|
||
|
|
||
|
#if FASTLED_VERSION < 3001000
|
||
|
#error "Requires FastLED 3.1 or later; check github for latest code."
|
||
|
#endif
|
||
|
|
||
|
// Fixed definitions cannot change on the fly.
|
||
|
#define LED_DT 12 // Serial data pin for WS2812 or WS2801.
|
||
|
#define LED_CK 11 // Serial clock pin for WS2801 or APA102.
|
||
|
#define COLOR_ORDER BGR // Are they GRB for WS2812 and GBR for APA102
|
||
|
#define LED_TYPE APA102 // What kind of strip are you using? WS2812, APA102. . .
|
||
|
#define NUM_LEDS 60 // Number of LED's.
|
||
|
|
||
|
|
||
|
uint8_t max_bright = 255; // Overall brightness definition. It can be changed on the fly.
|
||
|
|
||
|
struct CRGB leds[NUM_LEDS]; // Initialize our LED array.
|
||
|
|
||
|
|
||
|
CRGBPalette16 currentPalette; // Palette definitions
|
||
|
CRGBPalette16 targetPalette;
|
||
|
TBlendType currentBlending = LINEARBLEND;
|
||
|
|
||
|
|
||
|
|
||
|
void setup() {
|
||
|
|
||
|
Serial.begin(57600); // Initialize serial port for debugging.
|
||
|
delay(1000); // Soft startup to ease the flow of electrons.
|
||
|
|
||
|
LEDS.addLeds<LED_TYPE, LED_DT, LED_CK, COLOR_ORDER>(leds, NUM_LEDS); //WS2801 and APA102
|
||
|
// LEDS.addLeds<LED_TYPE, LED_DT,COLOR_ORDER>(leds, NUM_LEDS); // WS2812
|
||
|
|
||
|
FastLED.setBrightness(max_bright);
|
||
|
|
||
|
set_max_power_in_volts_and_milliamps(5, 500); // FastLED Power management set at 5V, 500mA.
|
||
|
|
||
|
currentPalette = OceanColors_p;
|
||
|
|
||
|
} // setup()
|
||
|
|
||
|
|
||
|
|
||
|
void loop () {
|
||
|
|
||
|
EVERY_N_MILLISECONDS(50) { // FastLED based non-blocking delay to update/display the sequence.
|
||
|
plasma();
|
||
|
}
|
||
|
|
||
|
EVERY_N_MILLISECONDS(1000) {
|
||
|
Serial.println(LEDS.getFPS()); // Optional check of our fps.
|
||
|
}
|
||
|
|
||
|
EVERY_N_MILLISECONDS(100) {
|
||
|
uint8_t maxChanges = 24;
|
||
|
nblendPaletteTowardPalette(currentPalette, targetPalette, maxChanges); // AWESOME palette blending capability.
|
||
|
}
|
||
|
|
||
|
|
||
|
EVERY_N_SECONDS(5) { // Change the target palette to a random one every 5 seconds.
|
||
|
uint8_t baseC = random8(); // You can use this as a baseline colour if you want similar hues in the next line.
|
||
|
targetPalette = CRGBPalette16(CHSV(baseC+random8(32), 192, random8(128,255)), CHSV(baseC+random8(32), 255, random8(128,255)), CHSV(baseC+random8(32), 192, random8(128,255)), CHSV(baseC+random8(32), 255, random8(128,255)));
|
||
|
}
|
||
|
|
||
|
FastLED.show();
|
||
|
|
||
|
} // loop()
|
||
|
|
||
|
|
||
|
|
||
|
void plasma() { // This is the heart of this program. Sure is short. . . and fast.
|
||
|
|
||
|
int thisPhase = beatsin8(6,-64,64); // Setting phase change for a couple of waves.
|
||
|
int thatPhase = beatsin8(7,-64,64);
|
||
|
|
||
|
for (int k=0; k<NUM_LEDS; k++) { // For each of the LED's in the strand, set a brightness based on a wave as follows:
|
||
|
|
||
|
int colorIndex = cubicwave8((k*23)+thisPhase)/2 + cos8((k*15)+thatPhase)/2; // Create a wave and add a phase change and add another wave with its own phase change.. Hey, you can even change the frequencies if you wish.
|
||
|
int thisBright = qsuba(colorIndex, beatsin8(7,0,96)); // qsub gives it a bit of 'black' dead space by setting sets a minimum value. If colorIndex < current value of beatsin8(), then bright = 0. Otherwise, bright = colorIndex..
|
||
|
|
||
|
leds[k] = ColorFromPalette(currentPalette, colorIndex, thisBright, currentBlending); // Let's now add the foreground colour.
|
||
|
}
|
||
|
|
||
|
} // plasma()
|