Kindle your creativity - FastLED projects on the Arduino platform in 2021 - Wokwi Arduino simulator provides a platform
Kindle your creativity with FastLED projects on the Arduino platform in 2021. Wokwi Arduino simulator provides a platform to simulate online. FastLED Arduino simulator helps you in learning Arduino programming as well as addressable LED programming without a need for real hardware.
This project is a presentation of FastLED Arduino projects simulated for free on the wokwi Arduino simulator. Please give a like it ?. This represents contributions from various people around the globe. As much as possible, I have made sure to attribute the code to the author/publisher and have retained the direct link to the source.
If there are any issues, please direct message me or leave a comment!
If I get 10 likes ??, I will present you another 10 for sure ⚡
Let us begin
LED face on FastLED on Wokwi Arduino simulator
Source: @urish on Wokwi channel from discord (https://discord.com/channels/787627282663211009/787630013658824707)
Wokwi Link: https://wokwi.com/arduino/projects/287950091044520460
Simulation:
#include "FastLED.h"
#include "faces.h"
// Matrix size
#define NUM_ROWS 28
#define NUM_COLS 26
// Define pins
#define DATA_PIN 3
#define BUTTON_0 9
#define BUTTON_1 10
#define BUTTON_2 11
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
#define NUM_LEDS NUM_ROWS * NUM_COLS
CRGB leds[NUM_LEDS];
// Animation controls
byte pressed = 1; // Tracks which face is currently being displayed
bool button0Pressed = false;
bool button1Pressed = false;
bool button2Pressed = false;
void setup() {
pinMode(BUTTON_0, INPUT_PULLUP);
pinMode(BUTTON_1, INPUT_PULLUP);
pinMode(BUTTON_2, INPUT_PULLUP);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
mid(); // Start the display with the forward-facing face
}
void loop() {
// Read the button inputs
button0Pressed = digitalRead(BUTTON_0) == LOW;
button1Pressed = digitalRead(BUTTON_1) == LOW;
button2Pressed = digitalRead(BUTTON_2) == LOW;
// If an input occured AND it's different than the current face, display that face
if (button0Pressed && !(pressed == 0)) {
pressed = 0;
left();
}
if (button1Pressed && !(pressed == 1)) {
pressed = 1;
mid();
}
if (button2Pressed && !(pressed == 2)) {
pressed = 2;
right();
}
// Blink the eyes ocassionally
EVERY_N_MILLISECONDS_I(blinktime, 1000) {
blinking();
// After blinking, return to the previous face
switch (pressed) {
case 0: left(); break;
case 1: mid(); break;
case 2: right(); break;
}
// Set the next blink delay
blinktime.setPeriod( random16(1000, 3000) );
}
}
// Face-related functions:
void mid() {
// Read the forward face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(IdleFace + i);
}
FastLED.show();
}
void left() {
// Read the left face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(LeftFace + i);
}
FastLED.show();
}
void right() {
// Read the right face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(RightFace + i);
}
FastLED.show();
}
void blinking() {
// Pick the appropriate blinking face based on the current facing
switch (pressed) {
case 0: leftB(); break;
case 1: midB(); break;
case 2: rightB(); break;
}
}
void midB() {
// Read the right face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(IdleBlink + i);
}
FastLED.show();
// Hold the blink for 50 milliseconds so the blink is visible
delay(50);
}
void leftB() {
// Read the right face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(LeftBlink + i);
}
FastLED.show();
// Hold the blink for 50 milliseconds so the blink is visible
delay(50);
}
void rightB() {
// Read the right face from PROGMEM, then display it.
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword_near(RightBlink + i);
}
FastLED.show();
// Hold the blink for 50 milliseconds so the blink is visible
delay(50);
}
50 LED ring on Wokwi Arduino simulator
#include <FastLED.h>
#define LED_PIN 3
#define NUM_LEDS 50
#define BRIGHTNESS 255
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define UPDATES_PER_SECOND 100
// This example shows several ways to set up and use 'palettes' of colors
// with FastLED.
//
// These compact palettes provide an easy way to re-colorize your
// animation on the fly, quickly, easily, and with low overhead.
//
// USING palettes is MUCH simpler in practice than in theory, so first just
// run this sketch, and watch the pretty lights as you then read through
// the code. Although this sketch has eight (or more) different color schemes,
// the entire sketch compiles down to about 6.5K on AVR.
//
// FastLED provides a few pre-configured color palettes, and makes it
// extremely easy to make up your own color schemes with palettes.
//
// Some notes on the more abstract 'theory and practice' of
// FastLED compact palettes are at the bottom of this file.
CRGBPalette16 currentPalette;
TBlendType currentBlending;
extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;
void setup() {
delay( 3000 ); // power-up safety delay
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );
currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND;
}
void loop()
{
ChangePalettePeriodically();
static uint8_t startIndex = 0;
startIndex = startIndex + 1; /* motion speed */
FillLEDsFromPaletteColors( startIndex);
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}
void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
uint8_t brightness = 255;
for( int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
}
// There are several different palettes of colors demonstrated here.
//
// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p,
// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p.
//
// Additionally, you can manually define your own color palettes, or you can write
// code that creates color palettes on the fly. All are shown here.
void ChangePalettePeriodically()
{
uint8_t secondHand = (millis() / 1000) % 60;
static uint8_t lastSecond = 99;
if( lastSecond != secondHand) {
lastSecond = secondHand;
if( secondHand == 0) { currentPalette = RainbowColors_p; currentBlending = LINEARBLEND; }
if( secondHand == 10) { currentPalette = RainbowStripeColors_p; currentBlending = NOBLEND; }
if( secondHand == 15) { currentPalette = RainbowStripeColors_p; currentBlending = LINEARBLEND; }
if( secondHand == 20) { SetupPurpleAndGreenPalette(); currentBlending = LINEARBLEND; }
if( secondHand == 25) { SetupTotallyRandomPalette(); currentBlending = LINEARBLEND; }
if( secondHand == 30) { SetupBlackAndWhiteStripedPalette(); currentBlending = NOBLEND; }
if( secondHand == 35) { SetupBlackAndWhiteStripedPalette(); currentBlending = LINEARBLEND; }
if( secondHand == 40) { currentPalette = CloudColors_p; currentBlending = LINEARBLEND; }
if( secondHand == 45) { currentPalette = PartyColors_p; currentBlending = LINEARBLEND; }
if( secondHand == 50) { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND; }
if( secondHand == 55) { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
}
}
// This function fills the palette with totally random colors.
void SetupTotallyRandomPalette()
{
for( int i = 0; i < 16; i++) {
currentPalette[i] = CHSV( random8(), 255, random8());
}
}
// This function sets up a palette of black and white stripes,
// using code. Since the palette is effectively an array of
// sixteen CRGB colors, the various fill_* functions can be used
// to set them up.
void SetupBlackAndWhiteStripedPalette()
{
// 'black out' all 16 palette entries...
fill_solid( currentPalette, 16, CRGB::Black);
// and set every fourth one to white.
currentPalette[0] = CRGB::White;
currentPalette[4] = CRGB::White;
currentPalette[8] = CRGB::White;
currentPalette[12] = CRGB::White;
}
// This function sets up a palette of purple and green stripes.
void SetupPurpleAndGreenPalette()
{
CRGB purple = CHSV( HUE_PURPLE, 255, 255);
CRGB green = CHSV( HUE_GREEN, 255, 255);
CRGB black = CRGB::Black;
currentPalette = CRGBPalette16(
green, green, black, black,
purple, purple, black, black,
green, green, black, black,
purple, purple, black, black );
}
// This example shows how to set up a static color palette
// which is stored in PROGMEM (flash), which is almost always more
// plentiful than RAM. A static PROGMEM palette like this
// takes up 64 bytes of flash.
const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
{
CRGB::Red,
CRGB::Gray, // 'white' is too bright compared to red and blue
CRGB::Blue,
CRGB::Black,
CRGB::Red,
CRGB::Gray,
CRGB::Blue,
CRGB::Black,
CRGB::Red,
CRGB::Red,
CRGB::Gray,
CRGB::Gray,
CRGB::Blue,
CRGB::Blue,
CRGB::Black,
CRGB::Black
};
// Additional notes on FastLED compact palettes:
//
// Normally, in computer graphics, the palette (or "color lookup table")
// has 256 entries, each containing a specific 24-bit RGB color. You can then
// index into the color palette using a simple 8-bit (one byte) value.
// A 256-entry color palette takes up 768 bytes of RAM, which on Arduino
// is quite possibly "too many" bytes.
//
// FastLED does offer traditional 256-element palettes, for setups that
// can afford the 768-byte cost in RAM.
//
// However, FastLED also offers a compact alternative. FastLED offers
// palettes that store 16 distinct entries, but can be accessed AS IF
// they actually have 256 entries; this is accomplished by interpolating
// between the 16 explicit entries to create fifteen intermediate palette
// entries between each pair.
//
// So for example, if you set the first two explicit entries of a compact
// palette to Green (0,255,0) and Blue (0,0,255), and then retrieved
// the first sixteen entries from the virtual palette (of 256), you'd get
// Green, followed by a smooth gradient from green-to-blue, and then Blue.
FastLED beautiful project on Wokwi Arduino simulator
#include <FastLED.h>
#define PIN 5
#define NUM_LEDS 256
CRGB leds[NUM_LEDS];
byte effect = 1;
void setup() {
Serial.begin(9600);
Serial.println("Initializing...");
FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
}
void loop() {
if (effect > 5) {
effect = 1;
}
Serial.print("Effect: ");
Serial.println(effect);
switch (effect) {
case 1: {
// CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
cylonBounce(0xff, 0x00, 0x00, 4, 10, 10);
break;
}
case 2: {
// colorWipe - Color (red, green, blue), speed delay
colorWipe(0xff, 0x00, 0x00, 10);
colorWipe(0x00, 0x00, 0x00, 10);
break;
}
case 3: {
// FadeInOut - Color (red, green. blue)
fadeInOut(0xff, 0x00, 0x00); // red
break;
}
case 4: {
// Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
strobe(0xff, 0x00, 0x00, 10, 50, 1000);
break;
}
case 5: {
// rainbowCycle - speed delay
rainbowCycle(10);
break;
}
}
effect++;
}
void fadeInOut(byte red, byte green, byte blue) {
float r, g, b;
for (int k = 0; k < 256; k = k + 1) {
r = (k / 256.0) * red;
g = (k / 256.0) * green;
b = (k / 256.0) * blue;
setAll(r, g, b);
showStrip();
}
for (int k = 255; k >= 0; k = k - 2) {
r = (k / 256.0) * red;
g = (k / 256.0) * green;
b = (k / 256.0) * blue;
setAll(r, g, b);
showStrip();
}
}
void strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) {
for (int j = 0; j < StrobeCount; j++) {
setAll(red, green, blue);
showStrip();
delay(FlashDelay);
setAll(0, 0, 0);
showStrip();
delay(FlashDelay);
}
delay(EndPause);
}
void cylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
for (int i = 0; i < NUM_LEDS - EyeSize - 2; i++) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
for (int i = NUM_LEDS - EyeSize - 2; i > 0; i--) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
}
void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
setPixel(i, red, green, blue);
showStrip();
delay(SpeedDelay);
}
}
void rainbowCycle(int SpeedDelay) {
byte *c;
uint16_t i, j;
for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
for (i = 0; i < NUM_LEDS; i++) {
c = wheel(((i * 256 / NUM_LEDS) + j) & 255);
setPixel(i, *c, *(c + 1), *(c + 2));
}
showStrip();
delay(SpeedDelay);
}
}
// Used by rainbowCycle
byte * wheel(byte WheelPos) {
static byte c[3];
if (WheelPos < 85) {
c[0] = WheelPos * 3;
c[1] = 255 - WheelPos * 3;
c[2] = 0;
} else if (WheelPos < 170) {
WheelPos -= 85;
c[0] = 255 - WheelPos * 3;
c[1] = 0;
c[2] = WheelPos * 3;
} else {
WheelPos -= 170;
c[0] = 0;
c[1] = WheelPos * 3;
c[2] = 255 - WheelPos * 3;
}
return c;
}
// Apply LED color changes
void showStrip() {
FastLED.show();
}
// Set a LED color
void setPixel(int Pixel, byte red, byte green, byte blue) {
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
}
// Set all LEDs to a given color and apply it
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
FastLED project snake game on Wokwi Arduino simulator
#include <FastLED.h>
#include "Snake.h"
#define NUM_LEDS 135
#define LEDS_PER_ROW 15
#define DATA_PIN 6
#define SPEAKER_PIN 8
#define BTN_LEFT 2
#define BTN_RIGHT 4
#define BTN_UP 5
#define BTN_DOWN 3
#define NOTE_G3 196
#define NOTE_C4 262
#define NOTE_C5 523
#define NOTE_E4 330
#define NOTE_G4 392
#define NOTE_G5 784
// Initialize the snake field with x=15, y=9, delay=10 ticks
Snake snakeGame(15, 9, 10);
CRGB leds[NUM_LEDS];
unsigned long timerTone = 0;
unsigned long timerReset = 0;
unsigned long timerRefresh = 0;
unsigned long timerMoveTone = 0;
unsigned long timerSnakeRose = 0;
bool isMoveTone = false;
bool isGameReset = false;
bool isMoveToneStop = false;
bool isSnakeRose = false;
bool isSnakeRoseEnd = false;
int lastSnakeLenght = 0;
uint8_t direction = 0;
uint8_t lastDirection = 0;
void setup() {
pinMode(BTN_LEFT, INPUT_PULLUP);
pinMode(BTN_RIGHT, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
snakeGame.setBodyColor(255, 0, 255); // Optionally set the color of the snakeparts
snakeGame.setFoodColor(0, 60, 125); // Optionally set the color of the food
snakeGame.setHeadColor(225, 20, 60); // Optionally set the color of the snakeparts
lastSnakeLenght = snakeGame.getSnakeLenght();
delay(1000);
FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
}
void inputEvent() {
if (digitalRead(BTN_LEFT) == LOW) {
snakeGame.goLeft(); // Snake will go left on the next move
isMoveTone = true;
direction = LEFT;
}
if (digitalRead(BTN_RIGHT) == LOW) {
snakeGame.goRight(); // Snake will go right on the next move
isMoveTone = true;
direction = RIGHT;
}
if (digitalRead(BTN_UP) == LOW) {
snakeGame.goUp(); // Snake will go up on the next move
isMoveTone = true;
direction = UP;
}
if (digitalRead(BTN_DOWN) == LOW) {
snakeGame.goDown(); // Snake will go down on the next move
isMoveTone = true;
direction = DOWN;
}
// Checks whether the snake has changed position
if (isMoveTone && (direction != lastDirection)) {
isMoveTone = false;
isMoveToneStop = true;
lastDirection = direction;
tone(SPEAKER_PIN, NOTE_G4);
timerMoveTone = millis();
}
if ((isMoveToneStop) && ((millis() - timerMoveTone) >= 30)) {
isMoveToneStop = false;
noTone(SPEAKER_PIN);
}
}
byte setPixel(byte x, byte y, byte r, byte g, byte b)
{
byte ledID = NUM_LEDS - (y * LEDS_PER_ROW) - x - 1 ;
leds[ledID].setRGB(r, g, b);
return ledID;
}
void changeRGBtoGBR()
{
for (int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++)
{
leds[whiteLed].setRGB(leds[whiteLed].g, leds[whiteLed].b, leds[whiteLed].r);
}
}
void clearScreen()
{
for (int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed++)
{
leds[whiteLed].setRGB( 3, 3, 3);
}
}
void loop()
{
inputEvent();
if (!snakeGame.wasGameReset() && (millis() - timerRefresh > 30)) {
timerRefresh = millis();
// This needs to be updated every frame
Snake::pixel* snakeLimbs = snakeGame.getSnakeLimbs();
Snake::pixel* snakeFood = snakeGame.getFoodPositions();
clearScreen();
setPixel(snakeFood[0].posX, 8 - snakeFood[0].posY, snakeFood[0].pixelColor.r, snakeFood[0].pixelColor.g, snakeFood[0].pixelColor.b); // display the food
for (int i = 0; i < snakeGame.getSnakeLenght(); i++)
{
// Display the snake, my setpixel method has x=0, y=0 at the top left, but the library has it at bottom left, so I invert the Y-Axis:
setPixel(snakeLimbs[i].posX, 8 - snakeLimbs[i].posY, snakeLimbs[i].pixelColor.r, snakeLimbs[i].pixelColor.g, snakeLimbs[i].pixelColor.b);
}
if (lastSnakeLenght != snakeGame.getSnakeLenght()) {
lastSnakeLenght = snakeGame.getSnakeLenght();
isSnakeRose = true;
tone(SPEAKER_PIN, NOTE_G4);
timerSnakeRose = millis();
}
FastLED.show();
snakeGame.tick(); // Main loop for the snake library
}
if ((isSnakeRose) && (millis() - timerSnakeRose) >= 30) {
isSnakeRose = false;
tone(SPEAKER_PIN, NOTE_G5);
isSnakeRoseEnd = true;
timerSnakeRose = millis();
}
if ((isSnakeRoseEnd) && (millis() - timerSnakeRose) >= 30) {
isSnakeRoseEnd = false;
noTone(SPEAKER_PIN);
}
// If the snake bit itself or the wall, flash a little
if (snakeGame.wasGameReset()) {
changeRGBtoGBR();
FastLED.show();
isGameReset = true;
tone(SPEAKER_PIN, NOTE_G3);
timerReset = millis();
}
if ((isGameReset) && (millis() - timerReset) >= 200) {
isGameReset = false;
noTone(SPEAKER_PIN);
}
}
FastLED analog fire clock project on Wokwi Arduino simulator
#include <FastLED.h>
#include <LiquidCrystal_I2C.h>
#include <stdio.h>
#include <Wire.h>
// thanks to Emmett Lathrop Brown
#define ENABLE_FLUX_CAPACITOR 0
// RTC module at address 0x68
#define DS1307_ADDRESS 0x68
// LCD module at address 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
uint8_t clear = 0x00;
#define WIDTH 32
#define HEIGHT 32
#define NUM_LEDS ((WIDTH) * (HEIGHT))
CRGB leds[NUM_LEDS + 1];
byte heat[WIDTH][HEIGHT];
byte *heat1d = (byte *) heat;
uint16_t XY(const uint8_t x, const uint8_t y) {
if (x >= WIDTH) return NUM_LEDS;
if (y >= HEIGHT) return NUM_LEDS;
// if (y & 1)
// return (y + 1) * WIDTH - 1 - x;
// else
return y * WIDTH + x;
}
#include "wuLineAA.h"
struct DS1307_tm {
union {
struct {
uint8_t seconds, minutes, hours;
uint8_t wday, mday, month, year;
};
uint8_t raw[7];
};
} tm;
void ds1307_read() {
// Read the values (date and time) of the DS1307 module
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(clear);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 0x07);
for (uint8_t i = 0; i < 7; i++)
tm.raw[i] = bcdToDec(Wire.read());
}
void setup()
{
FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS);
Wire.begin();
Serial.begin(9600);
lcd.begin (16, 2);
lcd.backlight();
// Use a line below to customize a date and time
// sec, min, hour, wday, mday, month, year % 100
// setDateTime(50, 59, 23, 7, 28, 2, 21);
// setDateTime(00, 29, 04, 4, 21, 2, 15);
// setDateTime(00, 46, 07, 4, 21, 2, 15);
// setDateTime(00, 20, 01, 7, 26, 10, 85);
ds1307_read();
}
void loop()
{
if (ENABLE_FLUX_CAPACITOR) {
tm.seconds += ENABLE_FLUX_CAPACITOR;
while (tm.seconds >= 60) ++tm.minutes, tm.seconds -= 60;
while (tm.minutes >= 60) ++tm.hours, tm.minutes -= 60;
while (tm.hours >= 24) ++tm.mday, ++tm.wday, tm.hours -= 24;
while (tm.wday >= 8) tm.wday -= 7;
while (tm.mday > 31) ++tm.month, tm.mday = 1; // i'm sure this is correct :p
while (tm.month > 12) ++tm.year, tm.month = 1;
ledclock(tm.hours, tm.minutes, tm.seconds);
} else
ds1307_read();
// update LEDs regularly
ledclock(tm.hours, tm.minutes, tm.seconds);
// update LCD once per second
static uint8_t last_seconds = 255;
if (last_seconds == tm.seconds)
return;
last_seconds = tm.seconds;
// flash the time separator
char time_sep = ':';
if (tm.seconds & 1)
time_sep = ' ';
// format the first line into a temporary buffer
char strbuf[17];
snprintf(strbuf, 17, "%02d%c%02d%c%02d",
tm.hours, time_sep, tm.minutes, time_sep, tm.seconds);
lcd.setCursor(4, 0);
lcd.print(strbuf);
// update 2nd line only when it changes
static uint8_t last_wday = 255;
if (last_wday == tm.wday)
return;
last_wday = tm.wday;
// format the second line
const char day_str[] = "NulSunMonTueWedThuFriSat";
uint16_t year = 2000 + tm.year;
if (year > 2038)
year -= 100;
snprintf(strbuf, 17, "%4d-%02d-%02d @@@",
year, tm.month, tm.mday);
memcpy(strbuf + 11, day_str + tm.wday * 3, 3);
lcd.setCursor(1, 1);
lcd.print(strbuf);
}
// Set the date and time of the DS1307
void setDateTime(uint8_t seconds, uint8_t minutes, uint8_t hours,
uint8_t wday, uint8_t mday, uint8_t month, uint8_t year)
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(clear); // Write clear, so that it can receive data
// The lines below write in the CI the date and time values
// that were placed in the variables above
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(wday));
Wire.write(decToBcd(mday));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(clear);
Wire.endTransmission();
}
uint8_t decToBcd(uint8_t value)
{
// Converts the decimal number to BCD
return ((value / 10 * 16) + (value % 10));
}
uint8_t bcdToDec(uint8_t value)
{
// Converts from BCD to decimal
return ((value / 16 * 10) + (value % 16));
}
// LED matrix analogue clock
void wuVectorAA(const uint16_t x, const uint16_t y, const uint16_t length, const uint16_t theta, CRGB *col) {
int16_t dx, dy;
dx = ((int32_t)cos16(theta) * length) / 32768;
dy = ((int32_t)sin16(theta) * length) / 32768;
wuLineAA(x, y, x + dx, y + dy, col);
}
void wuVectorAA8(const uint16_t x, const uint16_t y, const uint16_t length, const uint16_t theta) {
int16_t dx, dy;
dx = ((int32_t)cos16(theta) * length) / 32768;
dy = ((int32_t)sin16(theta) * length) / 32768;
wuLineAA8(x, y, x + dx, y + dy);
}
void ledclock(const uint8_t &hours, const uint8_t &minutes, const uint8_t &seconds) {
// FastLED.clear();
// everything is fixed-point, with 8-bits of fraction
uint16_t centrex = WIDTH * 128 - 128;
uint16_t centrey = HEIGHT * 128 - 128;
uint16_t length = WIDTH * 128;
uint16_t base_theta = 65536 * 3 / 4;
// second hand with sweep action
uint16_t theta = seconds * 65536 / 60;
static uint16_t sweep_theta = theta;
int32_t diff = theta - sweep_theta;
if (diff < 0)
diff += 65536;
sweep_theta += (diff + 8) / 16;
wuVectorAA8(centrex, centrey, length, base_theta + sweep_theta);
// minute hand
theta = (theta + minutes * 65536) / 60;
uint16_t min_theta = theta;
wuVectorAA8(centrex, centrey, length * 7 / 8, base_theta + theta);
// hour hand
theta = (theta + (hours % 12) * 65536) / 12;
wuVectorAA8(centrex, centrey, length * 3 /4, base_theta + theta);
for (int16_t i = NUM_LEDS; i--; )
leds[i] = HeatColor(heat1d[i]);
CRGB col = 0x0;
wuVectorAA(centrex, centrey, length, base_theta + sweep_theta, &col);
wuVectorAA(centrex, centrey, length * 7 / 8, base_theta + min_theta, &col);
wuVectorAA(centrex, centrey, length * 3 / 4, base_theta + theta, &col);
FastLED.show();
Fire2012(random(192));
}
void Fire2012(uint8_t activity) {
for (uint8_t h = 0; h < WIDTH; h++) {
// Step 1. Cool down every cell a little
for ( uint8_t i = 0; i < HEIGHT; i++) {
heat[i][h] = qsub8( heat[i][h], random8(33));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
uint8_t hleft = h > 0 ? (h - 1) : 0;
uint8_t hright = h < WIDTH - 1 ? (h + 1) : WIDTH - 1;
for ( uint8_t k = 0 ; k < HEIGHT - 1; k++) {
heat[k][h] = (heat[k][h]
+ heat[k + 1][hleft]
+ heat[k + 1][h]
+ heat[k + 1][hright] ) / 4;
}
if ( random8() < activity ) {
heat[HEIGHT - 1][h] = qadd8( heat[HEIGHT - 1][h], random8(activity));
}
}
}
FastLED fire on bars project on Wokwi Arduino simulator
#include "FastLED.h"
// Matrix size
#define HEIGHT 16
#define WIDTH 16
#define NUM_LEDS WIDTH * HEIGHT
#define MATRIX_TYPE 1
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];
//// ----------------------------- Sinusoid ------------------------------
//(c)Stefan Petrick https://gist.github.com/StefanPetrick/dc666c1b4851d5fb8139b73719b70149
//https://editor.soulmatelights.com/gallery/587
//upd by Stepko
bool loadingFlag = true;
uint8_t speed = 155;
uint8_t scale = 55;
uint8_t amplitude = 255;
int8_t type = 0; //0-3 original/>3 other versions
static float fmap(const float x, const float in_min, const float in_max, const float out_min, const float out_max) {
return (out_max - out_min) * (x - in_min) / (in_max - in_min) + out_min;
}
const int8_t semiHeightMajor = HEIGHT / 2 + (HEIGHT % 2);
const int8_t semiWidthMajor = WIDTH / 2 + (WIDTH % 2);
float e_s3_speed;
float e_s3_size;
float _scale;
void Sinusoid() {
if (loadingFlag) {
e_s3_speed = 0.004 * speed + 0.015; // speed of the movement along the Lissajous curves
e_s3_size = fmap(amplitude, 1, 255, 3, 9); // amplitude of the curves
_scale = fmap(scale, 1, 255, 0.1, 3);
loadingFlag = false;
}
float time_shift = millis();
switch (type) {
case 0://Sinusoid I
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
CRGB color;
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
data = v;
leds[XY(x, y)].b = data;
}
}
break;
case 1://it's not sinusoid II
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (sin(float(0.001 * time_shift * e_s3_speed)) + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (sin(float(0.0025 * time_shift * e_s3_speed)) + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
data = v;
leds[XY(x, y)].g = data;
}
} break;
case 2://Sinusoid III
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
data = v;
leds[XY(x, y)].g = data;
}
} break;
case 3://Sinusoid IV
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 4: //changed by stepko //anaglyph sinusoid
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 5: //changed by stepko //colored sinusoid
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.025 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 6: //changed by stepko //sinusoid in net
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].g = data;
v = 127 * (1 + sinf (_scale * x * 10 + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * y * 10 + float(0.011 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].r = data;
}
}
break;
case 7: //changed by stepko //spiral
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 8: //changed by stepko //blobs
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
}
}
void setup() {
//Serial.begin(250000);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(2, INPUT_PULLUP);
}
void loop() {
bool buttonPressed = digitalRead(2) == LOW;
Sinusoid();
if (buttonPressed) {
if (type >= 8) {
type = 0;
} else {
type += 1;
}
FastLED.clear();
delay(100);
} else {
FastLED.show();
FastLED.delay(1000 / 60);
}
} //loop
uint16_t XY (uint8_t x, uint8_t y) {
return (y * WIDTH + x);
}
FastLED clock black and white analog project on Wokwi Arduino simulator
#include <FastLED.h>
#include <LiquidCrystal_I2C.h>
#include <stdio.h>
#include <Wire.h>
// thanks to Emmett Lathrop Brown
#define ENABLE_FLUX_CAPACITOR 0
// RTC module at address 0x68
#define DS1307_ADDRESS 0x68
// LCD module at address 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
uint8_t clear = 0x00;
#define WIDTH 32
#define HEIGHT 32
#define NUM_LEDS ((WIDTH) * (HEIGHT))
CRGB leds[NUM_LEDS + 1];
uint16_t XY(const uint8_t x, const uint8_t y) {
if (x >= WIDTH) return NUM_LEDS;
if (y >= HEIGHT) return NUM_LEDS;
// if (y & 1)
// return (y + 1) * WIDTH - 1 - x;
// else
return y * WIDTH + x;
}
#include "wuLineAA.h"
struct DS1307_tm {
union {
struct {
uint8_t seconds, minutes, hours;
uint8_t wday, mday, month, year;
};
uint8_t raw[7];
};
} tm;
void ds1307_read() {
// Read the values (date and time) of the DS1307 module
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(clear);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 0x07);
for (uint8_t i = 0; i < 7; i++)
tm.raw[i] = bcdToDec(Wire.read());
}
void setup()
{
FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS);
Wire.begin();
Serial.begin(9600);
lcd.begin (16, 2);
lcd.backlight();
// Use a line below to customize a date and time
// sec, min, hour, wday, mday, month, year % 100
// setDateTime(50, 59, 23, 7, 28, 2, 21);
// setDateTime(00, 29, 04, 4, 21, 2, 15);
// setDateTime(00, 46, 07, 4, 21, 2, 15);
// setDateTime(00, 20, 01, 7, 26, 10, 85);
ds1307_read();
}
void loop()
{
if (ENABLE_FLUX_CAPACITOR) {
tm.seconds += ENABLE_FLUX_CAPACITOR;
while (tm.seconds >= 60) ++tm.minutes, tm.seconds -= 60;
while (tm.minutes >= 60) ++tm.hours, tm.minutes -= 60;
while (tm.hours >= 24) ++tm.mday, ++tm.wday, tm.hours -= 24;
while (tm.wday >= 8) tm.wday -= 7;
while (tm.mday > 31) ++tm.month, tm.mday = 1; // i'm sure this is correct :p
while (tm.month > 12) ++tm.year, tm.month = 1;
ledclock(tm.hours, tm.minutes, tm.seconds);
} else
ds1307_read();
// update LEDs regularly
ledclock(tm.hours, tm.minutes, tm.seconds);
// update LCD once per second
static uint8_t last_seconds = 255;
if (last_seconds == tm.seconds)
return;
last_seconds = tm.seconds;
// flash the time separator
char time_sep = ':';
if (tm.seconds & 1)
time_sep = ' ';
// format the first line into a temporary buffer
char strbuf[17];
snprintf(strbuf, 17, "%02d%c%02d%c%02d",
tm.hours, time_sep, tm.minutes, time_sep, tm.seconds);
lcd.setCursor(4, 0);
lcd.print(strbuf);
// update 2nd line only when it changes
static uint8_t last_wday = 255;
if (last_wday == tm.wday)
return;
last_wday = tm.wday;
// format the second line
const char day_str[] = "NulSunMonTueWedThuFriSat";
uint16_t year = 2000 + tm.year;
if (year > 2038)
year -= 100;
snprintf(strbuf, 17, "%4d-%02d-%02d @@@",
year, tm.month, tm.mday);
memcpy(strbuf + 11, day_str + tm.wday * 3, 3);
lcd.setCursor(1, 1);
lcd.print(strbuf);
}
// Set the date and time of the DS1307
void setDateTime(uint8_t seconds, uint8_t minutes, uint8_t hours,
uint8_t wday, uint8_t mday, uint8_t month, uint8_t year)
{
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(clear); // Write clear, so that it can receive data
// The lines below write in the CI the date and time values
// that were placed in the variables above
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(wday));
Wire.write(decToBcd(mday));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(clear);
Wire.endTransmission();
}
uint8_t decToBcd(uint8_t value)
{
// Converts the decimal number to BCD
return ((value / 10 * 16) + (value % 10));
}
uint8_t bcdToDec(uint8_t value)
{
// Converts from BCD to decimal
return ((value / 16 * 10) + (value % 16));
}
// LED matrix analogue clock
void wuVectorAA(const uint16_t x, const uint16_t y, const uint16_t length, const uint16_t theta, CRGB *col) {
int16_t dx, dy;
dx = ((int32_t)cos16(theta) * length) / 32768;
dy = ((int32_t)sin16(theta) * length) / 32768;
wuLineAA(x, y, x + dx, y + dy, col);
}
void ledclock(const uint8_t &hours, const uint8_t &minutes, const uint8_t &seconds) {
FastLED.clear();
// fill_rainbow(leds, NUM_LEDS, 0, 1);
CRGB c = 0xffffff;
// everything is fixed-point, with 8-bits of fraction
uint16_t centrex = WIDTH * 128 - 128;
uint16_t centrey = HEIGHT * 128 - 128;
uint16_t length = WIDTH * 128;
uint16_t base_theta = 65536 * 3 / 4;
// second hand with sweep action
uint16_t theta = seconds * 65536 / 60;
static uint16_t sweep_theta = theta;
int32_t diff = theta - sweep_theta;
if (diff < 0)
diff += 65536;
sweep_theta += (diff + 8) / 16;
wuVectorAA(centrex, centrey, length, base_theta + sweep_theta, &c);
// minute hand
length = length * 7 / 8;
theta = (theta + minutes * 65536) / 60;
wuVectorAA(centrex, centrey, length, base_theta + theta, &c);
// hour hand
length = length * 3 / 4;
theta = (theta + (hours % 12) * 65536) / 12;
wuVectorAA(centrex, centrey, length, base_theta + theta, &c);
FastLED.show();
}
FastLED water project on Wokwi Arduino simulator
#include "FastLED.h"
// Matrix size
#define NUM_ROWS 16
#define NUM_COLS 16
#define WIDTH NUM_COLS
#define HEIGHT NUM_ROWS
#define NUM_LEDS NUM_ROWS * NUM_COLS
#define MATRIX_TYPE 1
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];
//Drop
//@stepko
#define Sat (255)
#define Hue (150)
byte type;
#define WIDTH NUM_COLS
#define HEIGHT NUM_ROWS
void fillAll(CRGB color) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = color;
}
}
void drawPixelXY(uint8_t x, uint8_t y, CRGB color)
{
if (x < 0 || x > (WIDTH - 1) || y < 0 || y > (HEIGHT - 1)) return;
uint32_t thisPixel = XY((uint8_t)x, (uint8_t)y);
leds[thisPixel] = color;
}
bool loadingFlag = true;
CRGBPalette16 currentPalette(PartyColors_p);
uint8_t colorLoop = 1;
uint8_t ihue = 0;
uint8_t hue;
CRGB color;
void N(){
for (byte y = 0; y < NUM_ROWS; y++) {
for (byte x = 0; x < NUM_COLS; x++) {
//uint16_t pixelHue = inoise16 ((uint32_t)x*5000, (uint32_t)y*5000+ms*10,ms*20);
uint8_t pixelHue8 = inoise8 (x*30,y*30,millis()/16);
leds[XY(x, y)] = ColorFromPalette(currentPalette, pixelHue8);}
}blur2d(leds,NUM_COLS, NUM_ROWS, 32 );}
void PoolNoise()
{
if (loadingFlag)
{loadingFlag = false;
hue = Hue;
}
fill_solid( currentPalette, 16, CHSV(hue,Sat,230));
currentPalette[10] = CHSV(hue,Sat-60,255);
currentPalette[9] = CHSV(hue,255-Sat,210);
currentPalette[8] = CHSV(hue,255-Sat,210);
currentPalette[7] = CHSV(hue,Sat-60,255);
if(Hue == 1){
hue++;}
blur2d(leds, NUM_COLS, NUM_ROWS, 100);
N();
}
void drawCircle(int x0, int y0, int radius, const CRGB &color) {
int a = radius, b = 0;
int radiusError = 1 - a;
if (radius == 0) {
drawPixelXY(x0, y0, color);
return;
}
while (a >= b) {
drawPixelXY(a + x0, b + y0, color);
drawPixelXY(b + x0, a + y0, color);
drawPixelXY(-a + x0, b + y0, color);
drawPixelXY(-b + x0, a + y0, color);
drawPixelXY(-a + x0, -b + y0, color);
drawPixelXY(-b + x0, -a + y0, color);
drawPixelXY(a + x0, -b + y0, color);
drawPixelXY(b + x0, -a + y0, color);
b++;
if (radiusError < 0)
radiusError += 2 * b + 1;
else
{
a--;
radiusError += 2 * (b - a + 1);
}
}
}
int rad[(HEIGHT+WIDTH)/8];
byte posx[(HEIGHT+WIDTH)/8],posy[(HEIGHT+WIDTH)/8];
void drop() {
if (loadingFlag)
{ loadingFlag = false;
hue = Hue;
for (int i = 0; i < ((HEIGHT + WIDTH) / 8) - 1; i++)
{
posx[i] = random(WIDTH);
posy[i] = random(HEIGHT);
rad[i] = random(-1, (HEIGHT + WIDTH) / 2);
}
}
fill_solid( currentPalette, 16, CHSV(hue, Sat, 230));
currentPalette[10] = CHSV(hue, Sat - 60, 255);
currentPalette[9] = CHSV(hue, 255 - Sat, 210);
currentPalette[8] = CHSV(hue, 255 - Sat, 210);
currentPalette[7] = CHSV(hue, Sat - 60, 255);
fillAll(ColorFromPalette(currentPalette, 1));
for (uint8_t i = 0; i < ((HEIGHT + WIDTH) / 8) - 1; i++)
{
drawCircle(posx[i], posy[i], rad[i], ColorFromPalette(currentPalette, (256 / 16) * 8.5 - rad[i]));
drawCircle(posx[i], posy[i], rad[i] - 1, ColorFromPalette(currentPalette, (256 / 16) * 7.5 - rad[i]));
if (rad[i] >= (HEIGHT + WIDTH) / 2) {
rad[i] = -1;
posx[i] = random(WIDTH);
posy[i] = random(HEIGHT);
}
else
rad[i]++;
}
if (Hue == 0)
hue++;
blur2d(leds, NUM_COLS, NUM_ROWS, 32 );
}
void draw() {
switch (type) {
case 0: PoolNoise(); break;
case 1: drop(); break;
}
}
void setup() {
//Serial.begin(250000);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(2, INPUT_PULLUP);
}
void loop() {
bool buttonPressed = digitalRead(2) == LOW;
draw();
if (buttonPressed) {
if (type >= 1) {
type = 0;
} else {
type += 1;
}
FastLED.clear();
loadingFlag = true;
delay(100);
} else {
FastLED.show();
FastLED.delay(1000 / 60);
}
//static int frame = 0;
//if (frame++ % 32 == 0)
// Serial.println(FastLED.getFPS());
} //loop
uint16_t XY (uint8_t x, uint8_t y) {
return (y * NUM_COLS + x);
}
FastLED Fibonacci pattern FastLED Arduino project
#import<FastLED.h>
#define NUM_COLS 20
#define NUM_ROWS 20
#define NUM_LEDS 256
CRGB leds [256+1];
void setup()
{LEDS.addLeds<WS2812,3,GRB>(leds,256);}
void loop() {
uint16_t ms = millis();
for (byte j = 0; j < NUM_ROWS; j++) {
for (byte i = 0; i < NUM_COLS; i++) {
leds[XY_fibon(i, j)] = CHSV(i*8+j*8+ms/16,255,255); // with palette
}
}
FastLED.show();
}
uint16_t XY_fibon(byte x, byte y) {
static const uint16_t FibonPlanarTable[]={
256, 256, 256, 256, 256, 256, 256, 256, 247, 213, 234, 255, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 239, 205, 226, 192, 256, 179, 200, 221, 242, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 218, 184, 256, 171, 137, 158, 124, 145, 166, 187, 208, 229, 256, 256, 256, 256,
256, 256, 256, 252, 197, 163, 150, 116, 256, 103, 256, 111, 132, 153, 174, 195, 250, 256, 256, 256,
256, 256, 231, 176, 142, 256, 129, 95, 82, 69, 90, 77, 98, 119, 140, 161, 216, 237, 256, 256,
256, 244, 210, 155, 121, 108, 74, 61, 48, 256, 56, 256, 64, 85, 106, 127, 182, 203, 256, 256,
256, 223, 189, 134, 100, 87, 53, 40, 27, 35, 256, 43, 51, 72, 93, 114, 148, 169, 224, 256,
256, 202, 168, 113, 79, 66, 256, 32, 19, 14, 22, 30, 38, 59, 80, 256, 135, 256, 190, 245,
236, 181, 147, 92, 256, 58, 45, 256, 11, 6, 9, 17, 25, 46, 256, 101, 256, 156, 256, 211,
215, 160, 126, 256, 71, 256, 37, 24, 3, 256, 1, 4, 12, 33, 67, 256, 122, 256, 177, 232,
249, 194, 139, 105, 256, 50, 29, 16, 8, 0, 2, 7, 20, 41, 54, 88, 256, 143, 198, 253,
228, 173, 256, 118, 84, 63, 42, 21, 13, 5, 256, 15, 28, 256, 62, 75, 109, 164, 219, 256,
256, 207, 152, 256, 97, 76, 55, 34, 26, 18, 10, 23, 36, 49, 83, 96, 130, 185, 240, 256,
256, 241, 186, 131, 110, 89, 68, 47, 256, 39, 31, 44, 57, 70, 104, 117, 151, 206, 256, 256,
256, 256, 220, 165, 144, 256, 256, 256, 60, 256, 52, 65, 78, 91, 125, 138, 172, 227, 256, 256,
256, 256, 254, 199, 178, 123, 102, 81, 94, 73, 86, 256, 99, 112, 146, 159, 193, 248, 256, 256,
256, 256, 256, 233, 212, 157, 136, 115, 128, 107, 256, 120, 133, 167, 256, 180, 214, 256, 256, 256,
256, 256, 256, 256, 256, 191, 170, 149, 256, 162, 141, 154, 188, 256, 201, 235, 256, 256, 256, 256,
256, 256, 256, 256, 256, 246, 225, 204, 183, 196, 175, 209, 256, 222, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 238, 217, 251, 230, 256, 243, 256, 256, 256, 256, 256, 256, 256 };
return (FibonPlanarTable[y*20+x]);
}
FastLED Heart on Fire pattern FastLED Arduino project
//Heart bumpmap
//fastled 16x16 matrix demo
//Yaroslaw Turbin 29.12.2020
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://wokwi.com/arduino/projects/286414164431208972
//non commercial use
#include "FastLED.h"
// Matrix size
#define NUM_ROWS 16
#define NUM_COLS 16
#define NUM_LEDS NUM_ROWS * NUM_COLS
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];
CRGB chsvLut[256];
#define bumpsize 18 //bumpsize is bigger leds by 1 witn each side
int8_t bump[bumpsize*bumpsize] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x12, 0x18, 0x13, 0x09, 0x0a, 0x15, 0x18, 0x12, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0b, 0x1e, 0x26, 0x2c, 0x30, 0x2f, 0x30, 0x30, 0x2c, 0x26, 0x1b, 0x0b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x17, 0x26, 0x32, 0x39, 0x3e, 0x41, 0x42, 0x3e, 0x39, 0x31, 0x26, 0x15, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x1c, 0x2d, 0x39, 0x3f, 0x43, 0x47, 0x47, 0x44, 0x3f, 0x37, 0x2d, 0x1a, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x2e, 0x38, 0x41, 0x47, 0x46, 0x46, 0x45, 0x40, 0x38, 0x2c, 0x16, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09, 0x26, 0x36, 0x3e, 0x43, 0x46, 0x46, 0x42, 0x3f, 0x35, 0x25, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0b, 0x28, 0x38, 0x3e, 0x41, 0x42, 0x3f, 0x37, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x2c, 0x38, 0x3c, 0x3c, 0x37, 0x2a, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x2d, 0x34, 0x34, 0x2c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x11, 0x2b, 0x29, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
generateCHSVlut();
}
void generateCHSVlut(){
for (int j= 0; j<256; j++)
// chsvLut[j]=CHSV(100,255,j); //for one color
chsvLut[j] = HeatColor(j/1.4); //256 pallette color
}
void Bumpmap(int8_t lightx, int8_t lighty){
int col;
int yindex=bumpsize+1;
int8_t vly=lighty;
for (int y = 0; y < NUM_ROWS; y++) {
++vly;
int8_t vlx=lightx;
for (int x = 0; x < NUM_COLS; x++) {
++vlx;
int8_t nx=bump[x+yindex+1]-bump[x+yindex-1];
int8_t ny=bump[x+yindex+bumpsize]-bump[x+yindex-bumpsize];
byte difx=abs8(vlx*6-nx);
byte dify=abs8(vly*6-ny);
int temp = difx*difx+dify*dify; //to do: if number of height <=16 its possible to make lut table [16][16] with precalculate
// col = 255-(temp>>5); // its faster and more contrast)
col = temp? 255-sqrt16(temp)*3 : 255; //more realistic light
if (col<0) col=0;
leds[XY(x,y)] = chsvLut[col]; //thx satubarosu ))
}
yindex+=bumpsize;
}
}
void loop() {
#define BumpmapSpeed 30
int8_t lightX = 1- beatsin8(BumpmapSpeed,1,17,64);
int8_t lightY = 1- beatsin8(BumpmapSpeed-10,1,17);
Bumpmap(lightX, lightY);
FastLED.show();
}
uint16_t XY (uint8_t x, uint8_t y) { return (y * NUM_COLS + x);} //simple function to find led number in led matrix,
//change this to your routine
//or generate XY function for your matrix there:
//https://macetech.github.io/FastLED-XY-Map-Generator/
FastLED animation on FastLED Arduino project - wokwi Arduino simulator
/* Arduino 256 RGB LEDs Matrix Animation Frame
* Using WS2812 LED Strips
Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
#include <avr/pgmspace.h> // Needed to store stuff in Flash using PROGMEM
#include "FastLED.h" // Fastled library to control the LEDs
// How many leds are connected?
#define NUM_LEDS 256
// Define the Data Pin
#define DATA_PIN 3 // Connected to the data pin of the first LED strip
// Define the array of leds
CRGB leds[NUM_LEDS];
// Create the array of retro arcade characters and store it in Flash memory
const long DigDug01[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000,
0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000,
0x000000, 0x000000, 0x000000, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0xff0000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff0000, 0xff0000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x0066cc, 0x0066cc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0xff0000, 0xff0000, 0xff0000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0x000000,
0x000000, 0x000000, 0xff0000, 0xff0000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0xff0000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
const long DigDug02[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000,
0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x0066cc, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000,
0x000000, 0x000000, 0x000000, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0xff0000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff0000, 0xff0000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x0066cc, 0x0066cc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0xff0000, 0xff0000, 0xff0000, 0x0066cc, 0x0066cc, 0x0066cc, 0x0066cc, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0x000000,
0x000000, 0x000000, 0xff0000, 0xff0000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0x0066cc, 0x0066cc, 0x0066cc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xcccccc, 0xcccccc, 0xcccccc, 0xcccccc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
const long Qbert01[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xffffcc, 0xffffcc, 0xff0033, 0xffffcc, 0xffffcc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0xff0033, 0xff0033,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff0033,
0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0x000000, 0xff0033, 0xff0033, 0x000033, 0x000033, 0xff6600, 0x000000,
0x000000, 0xff0033, 0x000033, 0x000033, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0x000000
};
const long Qbert02[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xffffff, 0xffffff, 0xff0033, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0xff0033, 0x000000,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff0033,
0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000, 0xff6600, 0x000000,
0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0x000000
};
const long BombJack01[] PROGMEM =
{
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x0099ff, 0x333366, 0x333366,
0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0xffffff, 0xffffff, 0x0099ff, 0xffffff, 0xffffff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0xffffff, 0x000000, 0x0099ff, 0x000000, 0xffffff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x0099ff, 0xffffff, 0x000000, 0x0099ff, 0x000000, 0xffffff, 0x0099ff, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0xffffff, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0xffffff, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0x000000, 0xff0000, 0x000000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0x333366, 0x333366,
0x333366, 0x000000, 0x000000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0x000000, 0x000000, 0x333366, 0x333366,
0x333366, 0x333366, 0x000000, 0x000000, 0xffffff, 0x0099ff, 0x0099ff, 0x0099ff, 0xffff00, 0x0099ff, 0x0099ff, 0x0099ff, 0xffffff, 0x000000, 0x000000, 0x333366,
0x333366, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0x333366, 0x333366,
0x333366, 0x333366, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0x333366,
0x333366, 0x333366, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xffffff, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x000000, 0x000000, 0x000000, 0x333366, 0x000000, 0x000000, 0x000000, 0x333366, 0x333366, 0x333366, 0x333366
};
const long BombJack02[] PROGMEM =
{
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x0099ff, 0x333366, 0x333366,
0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0x0099ff, 0xffffff, 0x000000, 0x0099ff, 0x000000, 0xffffff, 0x0099ff, 0x0099ff, 0x0099ff, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x0099ff, 0x0099ff, 0xffffff, 0x000000, 0x0099ff, 0x000000, 0xffffff, 0x0099ff, 0x0099ff, 0x333366, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0x000000, 0x000000, 0x333366, 0x0099ff, 0xffffff, 0xffffff, 0xffcc99, 0xffffff, 0xffffff, 0x0099ff, 0x333366, 0x000000, 0x000000, 0x333366,
0x333366, 0x000000, 0x000000, 0xff0000, 0xffcc99, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xffcc99, 0xff0000, 0x000000, 0x000000, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0xff0000, 0xff0000, 0xffffff, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0xffcc99, 0xffffff, 0xff0000, 0xff0000, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xffffff, 0x333366, 0x333366, 0x333366,
0x333366, 0x333366, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0x000000, 0xff0000, 0x000000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0x333366, 0x333366,
0x333366, 0x333366, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0x333366, 0x333366,
0x333366, 0x333366, 0xffffff, 0xffffff, 0xffffff, 0x0099ff, 0x0099ff, 0x0099ff, 0xffff00, 0x0099ff, 0x0099ff, 0x0099ff, 0xffffff, 0xffffff, 0xffffff, 0x333366,
0x333366, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0x333366,
0x333366, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xff0000, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
0x333366, 0x333366, 0x333366, 0xffffff, 0xffffff, 0xff0000, 0xff0000, 0xffffff, 0xff0000, 0xff0000, 0xffffff, 0x333366, 0xffffff, 0xffffff, 0x333366, 0x333366,
0x333366, 0x333366, 0x333366, 0x333366, 0x333366, 0x000000, 0x000000, 0x000000, 0x333366, 0x000000, 0x000000, 0x000000, 0x333366, 0x333366, 0x333366, 0x333366
};
void setup() {
FastLED.addLeds<NEOPIXEL,DATA_PIN>(leds, NUM_LEDS); // Init of the Fastled library
FastLED.setBrightness(255);
}
void loop() {
// Put Qbert first frame
for(int passtime = 0; passtime < 8; passtime++) { // Display it 8 times
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Qbert01[i])); // Read array from Flash
}
FastLED.show();
delay(500);
// Put Qbert second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Qbert02[i]));
}
FastLED.show();
delay(500);
}
// Put DigDug first frame
for(int passtime = 0; passtime < 8; passtime++) {
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(DigDug01[i]));
}
FastLED.show();
delay(250);
// Put DigDug second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(DigDug02[i]));
}
FastLED.show();
delay(250);
}
// Put BombJack first frame
for(int passtime = 0; passtime < 8; passtime++) {
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(BombJack01[i]));
}
FastLED.show();
delay(400);
// Put BombJack second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(BombJack02[i]));
}
FastLED.show();
delay(400);
}
}
FastLED Ring on FastLED Arduino project - wokwi Arduino simulator
#include <FastLED.h>
#include <Wire.h>
#include <Time.h>
#include "DS3231.h"
// This is not time, it is divided millis()
#define seconds() ((unsigned long)millis()/1000)
#define minutes() ((unsigned int)seconds()/60)
#define hours() ((unsigned int)minutes()/60)
#define DATA_PIN 8
#define NUM_LEDS 81
#define BRIGHTNESS 255
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
#define UPDATES_PER_SECOND 20
CRGBPalette16 myPal = RainbowColors_p;
// CloudColors_p
// LavaColors_p
// OceanColors_p
// ForestColors_p
// RainbowColors_p
// RainbowStripeColors_p
// PartyColors_p
// HeatColors_p
time_t t;
int i;
void setup() {
// delay(2000); // POWER UP
adjustTime();
Serial.begin(9600);
// Wire.begin(); // Serial
// // DS3231
// readDS3231time(&t_sec, &t_min, &t_hr, &t_wd, &t_dy, &t_mon, &t_yr);
// setTime(t_hr, t_min, t_sec, t_dy, t_mon, 2000 + t_yr);
// set the initial time here:
// if (yr < 1) {
// // DS3231 seconds, minutes, hours, wday, date, month, year
// setDS3231time( 0, 27, 23, 7, 12, 6, 16);
// }
t = now();
// DEBUG
Serial.print("Date/Time: ");
Serial.print(day(t), DEC); Serial.print(".");
Serial.print(month(t), DEC); Serial.print(".");
Serial.print(year(t) - 2000, DEC); Serial.print(" ");
Serial.print(hour(t), DEC); Serial.print(":");
Serial.print(minute(t), DEC); Serial.println(".");
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
// JUST TO SEE POSITIONS:
// for (int i=0; i<NUM_LEDS ; i++ ) {
// leds[i] = ColorFromPalette (myPal,i*255/NUM_LEDS,255);
// FastLED.delay(10);
// }
// FastLED.delay(1000);
}
/**
**
*******/
void loop() {
int a = millis();
static long last_a;
static int left_inside_index;
static int right_inside_index;
static uint8_t color_index;
// inside circle 0-16 and 40-56
if (last_a < millis()-100) {
last_a = millis();
left_inside_index += left_inside_index >= 16 ? -left_inside_index : random16(2);
// right_inside_index += right_inside_index >= 40 ? -random16(2) : 16;
right_inside_index = left_inside_index + 40;
}
color_index = abs( (millis()%7200) * (double)255/3600 -255 );
for( i = 0 ; i< NUM_LEDS ; i++ ) {
leds[i] = ColorFromPalette(myPal,color_index,255);
}
// for (i = 0 ; i< (NUM_LEDS-1)/2 ; i++) {
// leds[i] = CRGB::Gray;
// }
// for (i = (NUM_LEDS-1)/2 ; i< (NUM_LEDS-1) ; i++ ) {
// leds[i] = CRGB::Gray;
// }
// Eyeballs
for (i = 0 ; i< 16 ; i++) {
leds[i] = 0;
}
for (i = 40 ; i< 56 ; i++) {
leds[i] = 0;
}
leds[ left_inside_index ] = CRGB::Yellow;
leds[ right_inside_index ] = CRGB::Yellow;
// NOSE
leds[NUM_LEDS-1] = CRGB::Red;
FastLED.delay(1000/UPDATES_PER_SECOND);
}
// Update time from sensor.
void adjustTime() {
byte t_sec, t_min, t_hr, t_wd, t_dy, t_mon, t_yr;
Wire.begin();
// DS3231
readDS3231time(&t_sec, &t_min, &t_hr, &t_wd, &t_dy, &t_mon, &t_yr);
setTime(t_hr, t_min, t_sec, t_dy, t_mon, 2000 + t_yr);
Wire.end();
}
FastLED matrix project dot matrix 16x16 on wokwi Arduino simulator
// Here's one last, really fun one from Mark Kriegsman
// https://gist.github.com/kriegsman/5adca44e14ad025e6d3b
#include <FastLED.h>
#define DATA_PIN 3
#define LED_COLS 16
#define LED_ROWS 16
#define BRIGHTNESS 255
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS LED_ROWS * LED_COLS
#define UPDATES_PER_SECOND 60
// Define the array of leds
CRGB leds[NUM_LEDS];
void setup() {
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
}
uint16_t XY(uint8_t x, uint8_t y) {
return (y * LED_ROWS + x);
}
// Code above draw() only runs once, to set up our variables
uint32_t hue = 0;
const uint8_t kMatrixWidth = LED_COLS;
const uint8_t kMatrixHeight = LED_ROWS;
const uint8_t kBorderWidth = 2;
void draw() {
// Apply some blurring to whatever's already on the matrix
// Note that we never actually clear the matrix, we just constantly
// blur it repeatedly. Since the blurring is 'lossy', there's
// an automatic trend toward black -- by design.
uint8_t blurAmount = 20; // beatsin8(2, 10, 255);
blur2d(leds, kMatrixWidth, kMatrixHeight, blurAmount);
// Use two out-of-sync sine waves
uint8_t i = beatsin8(27, kBorderWidth, kMatrixHeight - kBorderWidth);
uint8_t j = beatsin8(41, kBorderWidth, kMatrixWidth - kBorderWidth);
// Also calculate some reflections
uint8_t ni = (kMatrixWidth - 1) - i;
uint8_t nj = (kMatrixWidth - 1) - j;
// The color of each point shifts over time, each at a different speed.
uint16_t ms = millis();
leds[XY(i, j)] += CHSV(ms / 11, 200, 255);
leds[XY(j, i)] += CHSV(ms / 13, 200, 255);
leds[XY(ni, nj)] += CHSV(ms / 17, 200, 255);
leds[XY(nj, ni)] += CHSV(ms / 29, 200, 255);
leds[XY(i, nj)] += CHSV(ms / 37, 200, 255);
leds[XY(ni, j)] += CHSV(ms / 41, 200, 255);
FastLED.show();
FastLED.delay(1000 / UPDATES_PER_SECOND);
}
void loop() {
draw();
}
FastLED Arduino project Sinusoid on wokwi Arduino simulator
#include "FastLED.h"
// Matrix size
#define HEIGHT 16
#define WIDTH 16
#define NUM_LEDS WIDTH * HEIGHT
#define MATRIX_TYPE 1
// LEDs pin
#define DATA_PIN 3
// LED brightness
#define BRIGHTNESS 255
// Define the array of leds
CRGB leds[NUM_LEDS];
//// ----------------------------- Sinusoid ------------------------------
//(c)Stefan Petrick https://gist.github.com/StefanPetrick/dc666c1b4851d5fb8139b73719b70149
//https://editor.soulmatelights.com/gallery/587
//upd by Stepko
bool loadingFlag = true;
uint8_t speed = 155;
uint8_t scale = 55;
uint8_t amplitude = 255;
int8_t type = 0; //0-3 original/>3 other versions
static float fmap(const float x, const float in_min, const float in_max, const float out_min, const float out_max) {
return (out_max - out_min) * (x - in_min) / (in_max - in_min) + out_min;
}
const int8_t semiHeightMajor = HEIGHT / 2 + (HEIGHT % 2);
const int8_t semiWidthMajor = WIDTH / 2 + (WIDTH % 2);
float e_s3_speed;
float e_s3_size;
float _scale;
void Sinusoid() {
if (loadingFlag) {
e_s3_speed = 0.004 * speed + 0.015; // speed of the movement along the Lissajous curves
e_s3_size = fmap(amplitude, 1, 255, 3, 9); // amplitude of the curves
_scale = fmap(scale, 1, 255, 0.1, 3);
loadingFlag = false;
}
float time_shift = millis();
switch (type) {
case 0://Sinusoid I
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
CRGB color;
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
data = v;
leds[XY(x, y)].b = data;
}
}
break;
case 1://it's not sinusoid II
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (sin(float(0.001 * time_shift * e_s3_speed)) + sinf ( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (sin(float(0.0025 * time_shift * e_s3_speed)) + sinf( _scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
data = v;
leds[XY(x, y)].g = data;
}
} break;
case 2://Sinusoid III
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) )));
data = v;
leds[XY(x, y)].g = data;
}
} break;
case 3://Sinusoid IV
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 4: //changed by stepko //anaglyph sinusoid
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 5: //changed by stepko //colored sinusoid
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].r = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.01 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) + float(0.025 * time_shift * e_s3_speed))));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 6: //changed by stepko //sinusoid in net
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (_scale * sqrtf ( ((cx * cx) + (cy * cy)) ) ));
uint8_t data = v;
leds[XY(x, y)].g = data;
v = 127 * (1 + sinf (_scale * x * 10 + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
v = 127 * (1 + sinf (_scale * y * 10 + float(0.011 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].r = data;
}
}
break;
case 7: //changed by stepko //spiral
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 127 * (1 + sinf (3 * atan2(cy, cx) + _scale * hypot(cy, cx) + float(0.01 * time_shift * e_s3_speed)));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
case 8: //changed by stepko //blobs
for (uint8_t y = 0; y < HEIGHT; y++) {
for (uint8_t x = 0; x < WIDTH; x++) {
float cx = y + float(e_s3_size * (sinf (float(e_s3_speed * 0.003 * time_shift)) ) ) - semiHeightMajor; // the 8 centers the middle on a 16x16
float cy = x + float(e_s3_size * (cosf (float(e_s3_speed * 0.0022 * time_shift)) ) ) - semiWidthMajor;
float v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
uint8_t data = v;
leds[XY(x, y)].r = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0021 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.002 * time_shift)) ) ) - semiWidthMajor;
v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
data = v;
leds[XY(x, y)].b = data;
cx = x + float(e_s3_size * (sinf (e_s3_speed * float(0.0041 * time_shift)) ) ) - semiHeightMajor;
cy = y + float(e_s3_size * (cosf (e_s3_speed * float(0.0052 * time_shift)) ) ) - semiWidthMajor;
v = 30 * (max(0, -hypot(cx, cy) + _scale * 2.5));
data = v;
leds[XY(x, y)].g = data;
}
}
break;
}
}
void setup() {
//Serial.begin(250000);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
pinMode(2, INPUT_PULLUP);
}
void loop() {
bool buttonPressed = digitalRead(2) == LOW;
Sinusoid();
if (buttonPressed) {
if (type >= 8) {
type = 0;
} else {
type += 1;
}
FastLED.clear();
delay(100);
} else {
FastLED.show();
FastLED.delay(1000 / 60);
}
} //loop
uint16_t XY (uint8_t x, uint8_t y) {
return (y * WIDTH + x);
}
FastLED Arduino project Lumi crossfader on wokwi Arduino simulator
/*
Adapted from sutaburosu's AA_lines.ino code. Many thanks!
*/
#include <FastLED.h>
#define WIDTH 64
#define HEIGHT 16
#define CANVAS_HEIGHT 64
#define RASTER_SPACING 4
#define NUM_LEDS (WIDTH * HEIGHT)
CRGB leds[NUM_LEDS + 1];
CRGBPalette16 rainbowPalette = {
0xFF0000, 0x7F0000, 0xAB5500, 0x552A00, 0xABAB00, 0x555500, 0x00FF00, 0x007F00,
0x00AB55, 0x00552A, 0x0000FF, 0x00007F, 0x5500AB, 0x2A0055, 0xAB0055, 0x55002A
};
CRGBPalette16 greenStripe = {
0x00FF00, 0x00FF00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
CRGBPalette16 yellowStripe = {
0xFFFF00, 0xFFFF00, 0xFFFF00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
CRGBPalette16 fadeFactorPalette = {
0xAA0000, 0xAA0000, 0xAA0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
CRGBPalette16 redStripe = {
0xFF0000, 0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
DEFINE_GRADIENT_PALETTE( AndyGIlmore2 ) {
0, 111, 82, 126,
37, 111, 82, 126,
74, 148, 136, 170,
97, 186, 191, 213,
120, 220, 222, 234,
126, 254, 254, 255,
133, 210, 160, 174,
157, 167, 67, 93,
181, 124, 34, 48,
218, 80, 0, 3,
255, 80, 0, 3};
DEFINE_GRADIENT_PALETTE( Andy_GIlmore_2_gp ) {
0, 12, 0, 1,
36, 12, 0, 1,
73, 39, 3, 3,
98, 84, 13, 20,
122, 153, 91, 98,
128, 252,252,255,
135, 173,187,205,
158, 112,135,162,
181, 61, 63, 92,
218, 29, 21, 43,
255, 29, 21, 43};
boolean _twist = false;
void setup()
{
FastLED.addLeds<NEOPIXEL, 3>(leds, NUM_LEDS);
Serial.begin(115200);
}
// This is probably not good programming, idk.
#define ENABLE_CROSSFADE true
#define DISABLE_CROSSFADE false
#define ANIM_FOREGROUND true
#define ANIM_BACKGROUND false
void loop()
{
// parameter values are 0-255
sup(95,110,3,Andy_GIlmore_2_gp, LINEARBLEND,ANIM_BACKGROUND,DISABLE_CROSSFADE);
sup(150,150,8,redStripe, LINEARBLEND,ANIM_FOREGROUND,DISABLE_CROSSFADE);
FastLED.show();
}
uint16_t XY(uint8_t x, uint8_t y) {
if (x >= WIDTH) return NUM_LEDS;
if (y >= HEIGHT) return NUM_LEDS;
return y * WIDTH + x;
}
void crossfade(CRGB *a, const CRGB *b, uint8_t amount) {
uint8_t rev = 255 - amount;
a->red = (a->red * amount + b->red * rev) >> 8;
a->green = (a->green * amount + b->green * rev) >> 8;
a->blue = (a->blue * amount + b->blue * rev) >> 8;
}
void qaddColors(CRGB *a, const CRGB *b) {
a->red = qadd8(a->red,b->red);
a->green = qadd8(a->green,b->green);
a->blue = qadd8(a->blue,b->blue);
}
// With thanks to Steve Dommett; github.com/sutaburosu
void sup(uint8_t rotationSpeed, uint8_t translationSpeed, uint8_t lineWidth, CRGBPalette16 palette, TBlendType blendType, boolean foreground, boolean enableCrossfade) {
uint32_t yHueDelta ;
uint32_t xHueDelta ;
static uint32_t lastMillis = 16383; // int16_t 32767/2 (for rotationspeed=0 test)
float rotationSpeedFloat = fmap((float)rotationSpeed,(float)0,(float)255,-6.0,6.0); // Between -6 and 6
int16_t mappedTranslationSpeed = map(translationSpeed,0,255,-2<<12,2<<12); // Between -2^13 - 2^13 (higher is too fast)
uint32_t ms = millis();
if( rotationSpeedFloat != 0 ) {
yHueDelta = (int32_t)sin16((int16_t)round(ms * rotationSpeedFloat)) * lineWidth;
xHueDelta = (int32_t)cos16((int16_t)round(ms * rotationSpeedFloat)) * lineWidth;
lastMillis = ms;
} else {
yHueDelta = (int32_t)sin16(lastMillis) * lineWidth;
xHueDelta = (int32_t)cos16(lastMillis) * lineWidth;
}
int32_t startHue = ms * mappedTranslationSpeed;
int32_t lineStartHue = startHue - (CANVAS_HEIGHT + 2) / 2 * yHueDelta;
int16_t yd2 = sin16(ms * 3) / 4;
int16_t xd2 = sin16(ms * 7) / 4;
for (byte y = 0; y < CANVAS_HEIGHT; y++) {
uint32_t pixelHue = lineStartHue - (WIDTH + 2) / 2 * xHueDelta;
uint32_t xhd = xHueDelta;
lineStartHue += yHueDelta;
if( _twist ) { yHueDelta += yd2; }
for (byte x = 0; x < WIDTH; x++) {
if( y % RASTER_SPACING == 0 ) {
int ledsY = y/RASTER_SPACING;
if( foreground ) {
if( enableCrossfade ) {
CRGB fadeFactor = ColorFromPaletteExtended(fadeFactorPalette, pixelHue >> 7, 255, LINEARBLEND);
uint8_t this_fade = 255 - fadeFactor.red;
crossfade(&leds[XY(x, ledsY)], &palette[0], this_fade);
} else {
CRGB color2 = ColorFromPaletteExtended(palette, pixelHue >> 7, 255, LINEARBLEND);
qaddColors(&leds[XY(x, ledsY)], &color2);
}
} else {
leds[XY(x, ledsY)] = ColorFromPaletteExtended(palette, pixelHue >> 7, 255, blendType);
}
}
if( _twist ) { xhd += xd2; }
pixelHue += xHueDelta;
}
}
}
// from: https://github.com/FastLED/FastLED/pull/202
CRGB ColorFromPaletteExtended(const CRGBPalette16& pal, uint16_t index, uint8_t brightness, TBlendType blendType) {
// Extract the four most significant bits of the index as a palette index.
uint8_t index_4bit = (index >> 12);
// Calculate the 8-bit offset from the palette index.
uint8_t offset = (uint8_t)(index >> 4);
// Get the palette entry from the 4-bit index
const CRGB* entry = &(pal[0]) + index_4bit;
uint8_t red1 = entry->red;
uint8_t green1 = entry->green;
uint8_t blue1 = entry->blue;
uint8_t blend = offset && (blendType != NOBLEND);
if (blend) {
if (index_4bit == 15) {
entry = &(pal[0]);
} else {
entry++;
}
// Calculate the scaling factor and scaled values for the lower palette value.
uint8_t f1 = 255 - offset;
red1 = scale8_LEAVING_R1_DIRTY(red1, f1);
green1 = scale8_LEAVING_R1_DIRTY(green1, f1);
blue1 = scale8_LEAVING_R1_DIRTY(blue1, f1);
// Calculate the scaled values for the neighbouring palette value.
uint8_t red2 = entry->red;
uint8_t green2 = entry->green;
uint8_t blue2 = entry->blue;
red2 = scale8_LEAVING_R1_DIRTY(red2, offset);
green2 = scale8_LEAVING_R1_DIRTY(green2, offset);
blue2 = scale8_LEAVING_R1_DIRTY(blue2, offset);
cleanup_R1();
// These sums can't overflow, so no qadd8 needed.
red1 += red2;
green1 += green2;
blue1 += blue2;
}
if (brightness != 255) {
// nscale8x3_video(red1, green1, blue1, brightness);
nscale8x3(red1, green1, blue1, brightness);
}
return CRGB(red1, green1, blue1);
}
float fmap(float x, float a, float b, float c, float d)
{
float f=x/(b-a)*(d-c)+c;
return f;
}
FastLED Arduino project 'scintillating_heatshrink' on wokwi Arduino simulator
// originally from:
// https://github.com/sutaburosu/scintillating_heatshrink/
#include <Arduino.h>
#include <FastLED.h>
#include <stdint.h>
#include <avr/pgmspace.h>
#include "heatshrink_config.h"
#include "heatshrink_decoder.h"
enum XY_matrix_config { SERPENTINE = 1, ROWMAJOR = 2, FLIPMAJOR = 4, FLIPMINOR = 8 };
// MAX_MILLIWATTS can only be changed at compile-time. Use 0 to disable limit.
// Brightness can be changed at runtime via serial with 'b' and 'B'
#define MAX_MILLIWATTS 0
#define BRIGHTNESS 255
#define LED_PIN 2
#define COLOR_ORDER GRB
#define CHIPSET WS2812B
#define kMatrixWidth 16
#define kMatrixHeight 16
#define XY_MATRIX (ROWMAJOR)
#define NUM_LEDS ((kMatrixWidth) * (kMatrixHeight))
#define SERIAL_UI 1 // if 1, can be controlled via keypresses in PuTTY
#define FADEIN_FRAMES 32 // how long to reach full brightness when powered on
#define MS_GOAL 20 // to try maintain 1000 / 20ms == 50 frames per second
#define GIF2H_MAX_PALETTE_ENTRIES 140 // RAM is always tight on ATmega328...
#define GIF2H_NUM_PIXELS NUM_LEDS // all images must be the same size as the matrix
CRGB leds[NUM_LEDS];
CRGBPalette16 currentPalette;
uint16_t XY(uint8_t x, uint8_t y) {
uint8_t major, minor, sz_major, sz_minor;
if (x >= kMatrixWidth || y >= kMatrixHeight)
return NUM_LEDS;
if (XY_MATRIX & ROWMAJOR)
major = x, minor = y, sz_major = kMatrixWidth, sz_minor = kMatrixHeight;
else
major = y, minor = x, sz_major = kMatrixHeight, sz_minor = kMatrixWidth;
if (XY_MATRIX & FLIPMINOR)
minor = sz_minor - 1 - minor;
if ((XY_MATRIX & FLIPMAJOR) ^ (minor & 1 && (XY_MATRIX & SERPENTINE)))
major = sz_major - 1 - major;
return (uint16_t) minor * sz_major + major;
}
#if FASTLED_USE_PROGMEM == 1
#define FL_PGM_READ_PTR_NEAR(x) (pgm_read_ptr_near(x))
#else
#if !defined(FL_PGM_READ_PTR_NEAR)
#define FL_PGM_READ_PTR_NEAR(addr) ({typeof(addr) _addr = (addr); *(void * const *)(_addr); })
#endif
#if !defined(memcpy_P)
#define memcpy_P(dest, src, n) memcpy(dest, src, n)
#endif
#endif
// Stuff from FastLED pull requests and gists that will hopefully be merged one day
// Blend one CRGB color toward another CRGB color by a given amount.
// Blending is linear, and done in the RGB color space.
// These functions modify 'cur' in place.
// https://gist.github.com/kriegsman/d0a5ed3c8f38c64adcb4837dafb6e690
CRGB fadeTowardColour(CRGB& cur, const CRGB& target, uint8_t amount) {
nblendU8TowardU8(cur.red, target.red, amount);
nblendU8TowardU8(cur.green, target.green, amount);
nblendU8TowardU8(cur.blue, target.blue, amount);
return cur;
}
CRGB fadeTowardColour_video(CRGB& cur, const CRGB& target, uint8_t amount) {
nblendU8TowardU8_video(cur.red, target.red, amount);
nblendU8TowardU8_video(cur.green, target.green, amount);
nblendU8TowardU8_video(cur.blue, target.blue, amount);
return cur;
}
// Helper function that blends one uint8_t toward another by a given amount
void nblendU8TowardU8(uint8_t& cur, const uint8_t target, uint8_t amount) {
if (cur == target) return;
if (cur < target ) {
uint8_t delta = target - cur;
delta = scale8(delta, amount);
cur += delta;
} else {
uint8_t delta = cur - target;
delta = scale8(delta, amount);
cur -= delta;
}
}
void nblendU8TowardU8_video(uint8_t& cur, const uint8_t target, uint8_t amount) {
if (cur == target) return;
if (cur < target ) {
uint8_t delta = target - cur;
delta = scale8_video(delta, amount);
cur += delta;
} else {
uint8_t delta = cur - target;
delta = scale8_video(delta, amount);
cur -= delta;
}
}
// FastLED uses 4-bit interpolation. 8-bit looks far less janky.
// https://github.com/FastLED/FastLED/pull/202
CRGB ColorFromPaletteExtended(const CRGBPalette16& pal, uint16_t index, uint8_t brightness, TBlendType blendType) {
// Extract the four most significant bits of the index as a palette index.
uint8_t index_4bit = (index >> 12);
// Calculate the 8-bit offset from the palette index.
uint8_t offset = (uint8_t)(index >> 4);
// Get the palette entry from the 4-bit index
const CRGB* entry = &(pal[0]) + index_4bit;
uint8_t red1 = entry->red;
uint8_t green1 = entry->green;
uint8_t blue1 = entry->blue;
uint8_t blend = offset && (blendType != NOBLEND);
if (blend) {
if (index_4bit == 15) {
entry = &(pal[0]);
} else {
entry++;
}
// Calculate the scaling factor and scaled values for the lower palette value.
uint8_t f1 = 255 - offset;
red1 = scale8_LEAVING_R1_DIRTY(red1, f1);
green1 = scale8_LEAVING_R1_DIRTY(green1, f1);
blue1 = scale8_LEAVING_R1_DIRTY(blue1, f1);
// Calculate the scaled values for the neighbouring palette value.
uint8_t red2 = entry->red;
uint8_t green2 = entry->green;
uint8_t blue2 = entry->blue;
red2 = scale8_LEAVING_R1_DIRTY(red2, offset);
green2 = scale8_LEAVING_R1_DIRTY(green2, offset);
blue2 = scale8_LEAVING_R1_DIRTY(blue2, offset);
cleanup_R1();
// These sums can't overflow, so no qadd8 needed.
red1 += red2;
green1 += green2;
blue1 += blue2;
}
if (brightness != 255) {
// nscale8x3_video(red1, green1, blue1, brightness);
nscale8x3(red1, green1, blue1, brightness);
}
return CRGB(red1, green1, blue1);
}
CRGB ColorFromPaletteExtended(const CRGBPalette32& pal, uint16_t index, uint8_t brightness, TBlendType blendType) {
// Extract the five most significant bits of the index as a palette index.
uint8_t index_5bit = (index >> 11);
// Calculate the 8-bit offset from the palette index.
uint8_t offset = (uint8_t)(index >> 3);
// Get the palette entry from the 5-bit index
const CRGB* entry = &(pal[0]) + index_5bit;
uint8_t red1 = entry->red;
uint8_t green1 = entry->green;
uint8_t blue1 = entry->blue;
uint8_t blend = offset && (blendType != NOBLEND);
if (blend) {
if (index_5bit == 31) {
entry = &(pal[0]);
} else {
entry++;
}
// Calculate the scaling factor and scaled values for the lower palette value.
uint8_t f1 = 255 - offset;
red1 = scale8_LEAVING_R1_DIRTY(red1, f1);
green1 = scale8_LEAVING_R1_DIRTY(green1, f1);
blue1 = scale8_LEAVING_R1_DIRTY(blue1, f1);
// Calculate the scaled values for the neighbouring palette value.
uint8_t red2 = entry->red;
uint8_t green2 = entry->green;
uint8_t blue2 = entry->blue;
red2 = scale8_LEAVING_R1_DIRTY(red2, offset);
green2 = scale8_LEAVING_R1_DIRTY(green2, offset);
blue2 = scale8_LEAVING_R1_DIRTY(blue2, offset);
cleanup_R1();
// These sums can't overflow, so no qadd8 needed.
red1 += red2;
green1 += green2;
blue1 += blue2;
}
if (brightness != 255) {
// nscale8x3_video(red1, green1, blue1, brightness);
nscale8x3(red1, green1, blue1, brightness);
}
return CRGB(red1, green1, blue1);
}
typedef struct HSprite {
uint16_t datasize;
uint16_t frames;
uint16_t duration;
uint8_t flags;
uint8_t palette_entries;
CRGB palette[];
uint8_t hs_data[];
} HSprite;
#include "gifs.h"
FL_PROGMEM extern const HSprite *const hsprite_list[] = {
(HSprite*) &HSpr_35disk,
(HSprite*) &HSpr_load,
(HSprite*) &HSpr_vn,
(HSprite*) &HSpr_unionflag16,
(HSprite*) &HSpr_eu,
(HSprite*) &HSpr_ghost,
(HSprite*) &HSpr_scheisse,
(HSprite*) &HSpr_devil_nod,
(HSprite*) &HSpr_kputrummis,
(HSprite*) &HSpr_rjb,
(HSprite*) &HSpr_owl,
(HSprite*) &HSpr_twylogo,
(HSprite*) &HSpr_gear,
(HSprite*) &HSpr_16x16_oric,
(HSprite*) &HSpr_zx_k_ref,
(HSprite*) &HSpr_invader,
(HSprite*) &HSpr_c64,
(HSprite*) &HSpr_amigaroll_trs,
(HSprite*) &HSpr_joystick,
(HSprite*) &HSpr_slime,
(HSprite*) &HSpr_DigDug16x16,
(HSprite*) &HSpr_octorokblue,
(HSprite*) &HSpr_ptititi,
(HSprite*) &HSpr_burgertime,
(HSprite*) &HSpr_pouet_avatar_poi_charly_walk2,
(HSprite*) &HSpr_rockhell,
(HSprite*) &HSpr_pouet_avatar_mario,
(HSprite*) &HSpr_kirby_run,
(HSprite*) &HSpr_bub,
(HSprite*) &HSpr_sirlord,
(HSprite*) &HSpr_plane,
(HSprite*) &HSpr_fire,
(HSprite*) &HSpr_bird16,
(HSprite*) &HSpr_mspacman,
(HSprite*) &HSpr_ghost3,
(HSprite*) &HSpr_batman2,
(HSprite*) &HSpr_lemming,
(HSprite*) &HSpr_mwk,
(HSprite*) &HSpr_gwain2,
(HSprite*) &HSpr_scoopexrulez,
(HSprite*) &HSpr_8bit_avatar,
};
#define HSPRITES_N (sizeof(hsprite_list) / sizeof(hsprite_list[0]))
typedef struct {
uint8_t xw, yw, xd, yd;
int16_t xdd, ydd, bcd;
} RainbowSmoothiePreset;
typedef struct {
uint32_t frame = 0;
uint32_t millis = 0;
uint8_t effect = 2;
uint8_t palette_n = 1;
uint8_t alpha_fade = 64;
uint8_t brightness = BRIGHTNESS;
uint8_t rs_preset_n = 0;
TBlendType currentBlending = LINEARBLEND;
uint8_t extendedmixing = 1;
RainbowSmoothiePreset rs;
} Config;
Config cfg;
// /*__attribute__ ((section(".noinit")))*/ uint8_t * nv_preset;
void setup() {
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setCorrection(UncorrectedColor);
FastLED.setTemperature(UncorrectedTemperature);
FastLED.setDither(DISABLE_DITHER);
// FastLED.setMaxRefreshRate(400);
if (MAX_MILLIWATTS > 0) FastLED.setMaxPowerInMilliWatts(MAX_MILLIWATTS);
if (SERIAL_UI == 1) {
Serial.begin(250000);
halp();
}
pinMode(LED_BUILTIN, OUTPUT);
inc_palette(0);
inc_rs_preset(0);
}
#define MAX_EFFECTS 3
void loop() {
uint8_t effect = cfg.effect + 1;
if (effect & 1) rainbow_smoothie();
if (effect & 2) scintillating_heatshrink();
if (SERIAL_UI == 1) poll_serial();
if (cfg.frame <= FADEIN_FRAMES)
FastLED.setBrightness(scale8(cfg.brightness, (cfg.frame * 255) / FADEIN_FRAMES));
// cap the frame rate and indicate idle time via the built-in LED
cfg.frame++;
uint32_t frame_time = millis() - cfg.millis; // wraparound safe
int32_t pause = MS_GOAL - frame_time;
// if (pause < 0 && SERIAL_UI == 1) { Serial.print(-pause); Serial.println("ms late"); }
digitalWrite(LED_BUILTIN, HIGH);
if (pause > 0) delay(pause);
digitalWrite(LED_BUILTIN, LOW);
cfg.millis = millis();
FastLED.show();
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
void poll_serial() {
if (Serial.available() <= 0)
return;
int input = Serial.read();
switch (input) {
case 'e':
cfg.effect = addmod8(cfg.effect, 1, MAX_EFFECTS);
break;
case 'f':
cfg.alpha_fade = qsub8(cfg.alpha_fade, 1);
break;
case 'F':
cfg.alpha_fade = qadd8(cfg.alpha_fade, 1);
break;
case '{':
cfg.currentBlending = LINEARBLEND;
break;
case '}':
cfg.currentBlending = NOBLEND;
break;
case '[':
cfg.extendedmixing = 1;
break;
case ']':
cfg.extendedmixing = 0;
break;
case 'p':
inc_palette(1);
break;
case '~':
inc_rs_preset(1);
break;
case 'B':
cfg.brightness = qadd8(cfg.brightness, 1);
FastLED.setBrightness(cfg.brightness);
break;
case 'b':
cfg.brightness = qsub8(cfg.brightness, 1);
FastLED.setBrightness(cfg.brightness);
break;
case 'd':
FastLED.setDither(DISABLE_DITHER);
break;
case 'D':
FastLED.setDither(BINARY_DITHER);
break;
case ',':
cfg.rs.bcd -= 64;
break;
case '<':
cfg.rs.bcd -= 256;
break;
case '.':
cfg.rs.bcd += 64;
break;
case '>':
cfg.rs.bcd += 256;
break;
case '#':
randomise_rainbowsmoothie();
break;
case 13:
print_params();
break;
case 10:
break;
default:
Serial.println(F("?"));
}
}
void halp() {
Serial.println(F(" #\trandomise rainbow smoothie\r\n"
" ~\tchoose next preset for rainbow smoothie\r\n"
" <enter>\tprint parameters\r\n"
" e\tswitch to next Effect\r\n"
" p\tswitch to next palette\r\n"
" {}\tturn extended palette blending on/off\r\n"
" []\tturn linear palette blending on/off\r\n"
" ,.<>\tchange colour cycling rate\r\n"
" bB\tbrightness down/up\r\n"
" dD\tbinary dither off/on\r\n"
" fF\tdecrease/increase fade out rate\r\n"));
}
void print_params() {
Serial.println(F("bright\tfade\txw\tyw\txd\tyd\txdd\tydd\tbcd\tFPS"));
Serial.print(cfg.brightness); Serial.print("\t");
Serial.print(cfg.alpha_fade); Serial.print("\t");
Serial.print(cfg.rs.xw); Serial.print("\t");
Serial.print(cfg.rs.yw); Serial.print("\t");
Serial.print(cfg.rs.xd); Serial.print("\t");
Serial.print(cfg.rs.yd); Serial.print("\t");
Serial.print(cfg.rs.xdd); Serial.print("\t");
Serial.print(cfg.rs.ydd); Serial.print("\t");
Serial.print(cfg.rs.bcd); Serial.print("\t");
Serial.println(FastLED.getFPS());
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// FL_PROGMEM extern const TProgmemPalette16 myRedWhiteBluePalette_p = {
// CRGB::Red, CRGB::Gray, CRGB::Blue, CRGB::Black,
// CRGB::Red, CRGB::Gray, CRGB::Blue, CRGB::Black,
// CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray,
// CRGB::Blue, CRGB::Blue, CRGB::Black, CRGB::Black
// };
// FL_PROGMEM extern const TProgmemPalette16 myBlackWhitePalette_p = {
// CRGB::Black, CRGB::Black, CRGB::White, CRGB::Grey,
// CRGB::Black, CRGB::Black, CRGB::White, CRGB::Grey,
// CRGB::Black, CRGB::Black, CRGB::White, CRGB::Grey,
// CRGB::Black, CRGB::Black, CRGB::White, CRGB::Grey,
// };
FL_PROGMEM extern const TProgmemRGBPalette16 RainbowStripeColors2_p = {
0xFF0000, 0x7F0000, 0xAB5500, 0x552A00,
0xABAB00, 0x555500, 0x00FF00, 0x007F00,
0x00AB55, 0x00552A, 0x0000FF, 0x00007F,
0x5500AB, 0x2A0055, 0xAB0055, 0x55002A
};
// DEFINE_GRADIENT_PALETTE(froth616_gp) {
// // http://soliton.vm.bytemark.co.uk/pub/cpt-city/fractint/base/tn/froth616.png.index.html
// // Size: 116 bytes of program space.
// 0, 247, 0,247,
// 17, 75, 0, 79,
// 33, 247, 0, 0,
// 51, 75, 0, 0,
// 68, 247,248, 0,
// 84, 75, 91, 0,
// 102, 0,248, 0,
// 119, 0, 91, 0,
// 135, 0, 0,247,
// 153, 0, 0, 79,
// 170, 0,248,247,
// 186, 0, 91, 79,
// 204, 0, 0, 0,
// 237, 0, 0, 0,
// 255, 247,248,247};
FL_PROGMEM extern const TProgmemRGBPalette16 *const palettes16[] = {
&RainbowColors_p, &RainbowStripeColors_p, &RainbowStripeColors2_p,
// &HeatColors_p, &CloudColors_p, &LavaColors_p, &OceanColors_p,
// &ForestColors_p, &PartyColors_p,
// &myRedWhiteBluePalette_p, &myBlackWhitePalette_p
};
#define RGB16PALETTES (sizeof(palettes16) / sizeof(palettes16[0]))
FL_PROGMEM extern const TProgmemRGBGradientPalettePtr palettesGrad[] = {
// froth616_gp,
};
#define RGBGRADPALETTES (sizeof(palettesGrad) / sizeof(TProgmemRGBGradientPalettePtr))
void inc_palette(uint8_t n) {
uint8_t total_palettes = RGB16PALETTES + RGBGRADPALETTES;
cfg.palette_n = n = addmod8(cfg.palette_n, n, total_palettes);
if (n < RGBGRADPALETTES) {
currentPalette = (TProgmemRGBGradientPalettePtr) FL_PGM_READ_PTR_NEAR(&palettesGrad[n]);
return;
}
n -= RGBGRADPALETTES;
if (n < RGB16PALETTES) {
currentPalette = *(TProgmemRGBPalette16 *) FL_PGM_READ_PTR_NEAR(&palettes16[n]);
return;
}
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
FL_PROGMEM const RainbowSmoothiePreset rs_presets[] = {
//xw yw xd yd xdd ydd bcd
{ 4, 3, 80, 208, 15327, -3010, 27000},
// { 4, 4, 14, 14, 6514, -16076, 16384},
{ 1, 1, 34, 86, -7661, 30835, 9600},
// { 7, 12, 105, 46, 5563, 5313,-10240},
// {19, 19, 200, 237, 20142, 14656, -2857},
// {20, 6, 116, 33, -8683, -10095, -4633},
// { 4, 3, 16, 48, 15347, 6636, 3331},
// { 5, 10, 2, 44, -7661, 30835, -2414},
// { 3, 3, 64, 231, 8691, 7618, 3795},
// { 7, 5, 36, 111, 25249, 4738, -1283},
// { 4, 8, 255, 255, -32767, -32690, -6234},
// { 2, 5, 173, 103, -18586, 14361, 3788},
};
#define MAX_RS_PRESETS (sizeof(rs_presets) / sizeof(RainbowSmoothiePreset))
void inc_rs_preset(uint8_t n) {
cfg.rs_preset_n = addmod8(cfg.rs_preset_n, n, MAX_RS_PRESETS);
uint8_t* src = (uint8_t *) &rs_presets[cfg.rs_preset_n];
uint8_t* dst = (uint8_t *) &cfg.rs;
memcpy_P(dst, src, sizeof(cfg.rs));
}
void rainbow_smoothie() {
uint32_t startHue = cfg.frame * cfg.rs.bcd;
uint32_t yHueDelta = ((uint32_t)sin16(cfg.frame * cfg.rs.xd) * cfg.rs.xw);
uint32_t xHueDelta = ((uint32_t)cos16(cfg.frame * cfg.rs.yd) * cfg.rs.yw);
uint32_t lineStartHue = startHue - (kMatrixHeight / 2) * yHueDelta;
uint32_t yd2 = cfg.rs.ydd * 2048;
uint32_t xd2 = cfg.rs.xdd * 2048;
for (byte y = 0; y < kMatrixHeight; y++) {
lineStartHue += yHueDelta;
yHueDelta += yd2;
uint32_t pixelHue = lineStartHue - (kMatrixWidth / 2) * xHueDelta;
uint32_t xhd = xHueDelta;
for (byte x = 0; x < kMatrixWidth; x++) {
pixelHue += xhd;
xhd += xd2;
if (cfg.extendedmixing == 1) {
leds[XY(x, y)] = ColorFromPaletteExtended(currentPalette, pixelHue >> 7, 255, cfg.currentBlending);
} else {
leds[XY(x, y)] = ColorFromPalette(currentPalette, pixelHue >> 15, 255, cfg.currentBlending);
}
}
}
}
void randomise_rainbowsmoothie() {
random16_add_entropy(random());
cfg.rs.bcd = random16(16383) - 8192;
cfg.rs.xd = random8();
cfg.rs.yd = random8();
cfg.rs.xdd = random16() - 32768;
cfg.rs.ydd = random16() - 32768;
cfg.rs.xw = random8(24);
cfg.rs.yw = random8(24);
}
struct hstatus {
uint32_t last_millis;
heatshrink_decoder hsd;
size_t heatsunk;
uint16_t frame;
uint8_t hs_spr_n = -1;
uint8_t loops;
CRGB palette[GIF2H_MAX_PALETTE_ENTRIES];
} hstatus;
// HStatus hstatus;
void heatshrunk_sprite_reset(struct hstatus * status, uint8_t hs_spr_n) {
// decompress the palette and leave the decompressor ready to emit pixels
status->hs_spr_n = hs_spr_n;
status->heatsunk = 0;
status->frame = 0;
HSprite *spr_ptr = (HSprite *) FL_PGM_READ_PTR_NEAR(&hsprite_list[hs_spr_n]);
// uint16_t datasize = FL_PGM_READ_WORD_NEAR(&spr_ptr->datasize);
uint8_t palette_entries = FL_PGM_READ_BYTE_NEAR(&spr_ptr->palette_entries);
// set heatshrink's window buffer position, so the pixels end up aligned with the start of the buffer
heatshrink_decoder_reset(&status->hsd);
status->hsd.head_index -= palette_entries * sizeof(CRGB);
uint8_t *dst = (uint8_t *) &status->palette;
uint16_t remaining = palette_entries * sizeof(CRGB);
size_t count = 0;
while (remaining) {
heatshrink_decoder_sinkP(&status->hsd, &spr_ptr->hs_data[status->heatsunk],
HEATSHRINK_STATIC_INPUT_BUFFER_SIZE, &count);
status->heatsunk += count;
HSD_poll_res pres;
do {
pres = heatshrink_decoder_poll(&status->hsd, dst, remaining, &count);
dst += count;
remaining -= count;
} while ((pres == HSDR_POLL_MORE) && remaining);
}
}
void heatshrunk_sprite_prepare(struct hstatus * status, uint8_t hs_spr_n) {
HSprite *spr_ptr = (HSprite *) FL_PGM_READ_PTR_NEAR(&hsprite_list[hs_spr_n]);
uint16_t datasize = FL_PGM_READ_WORD_NEAR(&spr_ptr->datasize);
uint16_t frames = FL_PGM_READ_WORD_NEAR(&spr_ptr->frames);
uint16_t duration = FL_PGM_READ_WORD_NEAR(&spr_ptr->duration);
// uint8_t flags = FL_PGM_READ_BYTE_NEAR(&spr_ptr->flags);
if (hs_spr_n != status->hs_spr_n) {
// a different sprite has been selected; force a reset
status->frame = frames;
status->loops = 0;
duration = 0;
}
// time to decompress the next frame?
if ((cfg.millis - status->last_millis) < duration) return;
if (frames == 1 && status->loops != 0) return;
// need to loop/reset first?
if (status->frame >= frames) {
heatshrunk_sprite_reset(status, hs_spr_n);
status->loops += 1;
}
status->frame++;
status->last_millis = cfg.millis;
size_t count = 0;
uint16_t remaining = GIF2H_NUM_PIXELS;
while (remaining) {
if (status->heatsunk < datasize) {
heatshrink_decoder_sinkP(&status->hsd, &spr_ptr->hs_data[status->heatsunk],
datasize - status->heatsunk, &count);
status->heatsunk += count;
}
HSD_poll_res pres;
do {
pres = heatshrink_decoder_poll(&status->hsd, 0, remaining, &count);
remaining -= count;
} while ((pres == HSDR_POLL_MORE) && remaining);
if (0 && (status->heatsunk >= datasize)) {
heatshrink_decoder_finish(&status->hsd); // not strictly needed when using static buffers
}
}
}
void heatshrunk_sprite_plot(int8_t xstart, int8_t ystart, struct hstatus * status, const uint8_t fade_speed) {
CRGB *pal = (CRGB *) status->palette;
uint8_t *pixels = status->hsd.buffers + HEATSHRINK_STATIC_INPUT_BUFFER_SIZE;
// plot each sprite pixel modulo the size of the matrix, i.e. wrap the image
for (uint8_t y = 0; y < kMatrixHeight; y++) {
for (uint8_t x = 0; x < kMatrixWidth; x++) {
uint16_t led_index = XY(addmod8(x, xstart, kMatrixWidth),
addmod8(y, ystart, kMatrixHeight));
uint8_t palette_index = *pixels++;
if (palette_index > 0 && cfg.effect != 1) {
// non-0 palette entry; copy the palette entry to the LED
leds[led_index] = pal[palette_index];
} else {
// palette entry 0 is the mask; fade this LED to the mask colour (black usually)
fadeTowardColour(leds[led_index], pal[palette_index], fade_speed);
}
}
}
}
void scintillating_heatshrink() {
static uint8_t spr_n = 0;
static uint32_t last_spr_change = 0;
if ((hstatus.loops > 0) && (cfg.millis - last_spr_change > 2500)) {
last_spr_change = cfg.millis;
spr_n = addmod8(spr_n, 1, HSPRITES_N);
}
heatshrunk_sprite_prepare(&hstatus, spr_n);
heatshrunk_sprite_plot(0 /*- (cos8(cfg.frame & 0x7f) >> 3)*/, 0, &hstatus, cfg.alpha_fade);
}
A bit about Wokwi Arduino Simulator
Arduino simulators help cut the learning time. They help in presenting your project to others very easily. You can easily share the code with others. Hardware hurdles such as hardware not available, or faulty USB cables etc won't slowdown you. Also, it will save time and money especially when you experiment with your code and projects. The simulator from wokwi comes with all the benefits.
you can visit https://wokwi.com to learn Arduino faster and free!