#include "FastLED.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16,2);
const CRGB colTempCoolBlue = CRGB(68, 131, 255);
const CRGB colTempBlueHeat = CRGB(50, 228, 255);
const CRGB colTempViolet = CRGB(228, 115, 234);
const CRGB colTempOrange = CRGB(255, 154, 4);
const CRGB colTempYellow = CRGB(255, 234, 7);
const int throttleAfterBurnStart = 75;
#define FASTLED_ALLOW_INTERRUPTS 0 // Used for ESP8266.
#define THROTTLE_CHANNEL A0
#define LED_PIN 2
#define BRIGHTNESS 255
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS 80
uint8_t heatindex = 0;
uint8_t throttle = 0;
uint8_t lastThrottleSetting = 0;
uint16_t skipPallette = 0;
struct CRGB leds[NUM_LEDS];
#define MAX_DIMENSION 255
uint8_t colorLoop = 0;
uint8_t noise[MAX_DIMENSION];
// The 16 bit version of our coordinates
static uint16_t x;
static uint16_t y;
static uint16_t z;
uint16_t speed = 20; // speed is set dynamically once we've started up 1 to 60 fast
uint16_t scale = 50;
byte wavesample[NUM_LEDS] ;
// NB: In right hand diagram the LED Zero is at 12 o'clock
// Crossfade current palette slowly toward the target palette
//
// Each time that nblendPaletteTowardPalette is called, small changes
// are made to currentPalette to bring it closer to matching targetPalette.
// You can control how many changes are made in each call:
// - the default of 24 is a good balance
// - meaningful values are 1-48. 1=veeeeeeeery slow, 48=quickest
// - "0" means do not change the currentPalette at all; freeze
uint8_t maxBlendChanges = 24;
TBlendType currentBlending;
CRGBPalette16 myBasePalette( CRGB::Black);
CRGBPalette16 myHeatMapPal;
CRGBPalette16 myNoisePal;
double pallFract;
// If the channel is off, return the default value
int readChannel(int channelInput, int minLimit, int maxLimit, int defaultValue){
int ch = analogRead(channelInput);
int upperSignalLimit = 1023; //1023
return map(ch, 0, upperSignalLimit, minLimit, maxLimit);
}
void visualizeSlider(int paintToIndex) {
if (paintToIndex > NUM_LEDS) paintToIndex = NUM_LEDS;
for(int i = 0; i < paintToIndex; i++){
leds[i] = CRGB (255, 255, 255);
}
}
void setup() {
initializeLCDScreen();
SetUpPallettes();
currentBlending = LINEARBLEND;
Serial.begin(9600);//full speed but can be any other speed
// put your setup code here, to run once:
LEDS.clear();
LEDS.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds,NUM_LEDS);
LEDS.setBrightness(BRIGHTNESS);
pinMode(THROTTLE_CHANNEL, INPUT);
pallFract = 255/NUM_LEDS;
skipPallette = ceil(255/NUM_LEDS);
fill_palette(leds, NUM_LEDS, 0, skipPallette, myBasePalette, 250, LINEARBLEND);
// Noise
// Initialize our coordinates to some random values
x = random16();
y = random16();
z = random16();
//Serial.println("setup complete");
} // setup()
void loop() {
throttle = readChannel(THROTTLE_CHANNEL, 0, 254, 0);
fract8 blendAmount = 0;
int rangeStart = 0;
int rangeEnd = 0;
if (throttle < throttleAfterBurnStart ) {
rangeStart = 0;
rangeEnd = 0;
}
else {
rangeStart = throttleAfterBurnStart;
rangeEnd = 255;
}
int colorPalIndex = map(throttle, rangeStart, rangeEnd, 0, 240);
int colorBri = map(throttle, rangeStart, rangeEnd, 120, 250);
FillLEDsFromPaletteColors(colorPalIndex, colorBri);
if (lastThrottleSetting != throttle) {
lcd.clear();
lcd.print("Throttel:");
lcd.println(throttle);
lcd.setCursor(0, 1);
lcd.print("colidx:");
lcd.println(colorPalIndex);
lastThrottleSetting = throttle;
}
//if (throttle > throttleAfterBurnStart ) {
// fillnoise8();
// convert the noise data to colors in the LED array using the current palette
addNoiseToLEDs(colorPalIndex, colorBri);
//}
//else {
// Fade back to blue then black
//}
// blur1d (leds, NUM_LEDS, 14);
//visualizeSlider(rangePos);
LEDS.show(); // Display the LED's at every loop cycle.
} // loop()
//
void FillLEDsFromPaletteColors( uint8_t colorIndex, uint8_t brightness)
{
for( int i = 0; i < NUM_LEDS; i++) {
// use sin wave to create variance
// float angle = radians(i); i 0 to 360 // Converts degrees to radians.
//brightness = (255 / 2) + (255 / 2) * sin(angle); // Generates points on a sign wave.
//analogWrite(led, brightness);
// one wave
int newcolorIndex = colorIndex + wavesample[i];
if (newcolorIndex > 240) newcolorIndex = 240;
int newBrightness = brightness + wavesample[i];
if (newBrightness > 255) newBrightness = 255;
leds[i] = ColorFromPalette( myHeatMapPal, newcolorIndex, newBrightness, LINEARBLEND);
}
}
void addNoiseToLEDs(int colorPalIndex, int colorBri)
{
int t = millis() / 20;
uint8_t x = 0;
int noiseScale = 15; // bigger number smaller detail
for (int i = 0; i < NUM_LEDS; i++) {
uint8_t noise = inoise8(i * noiseScale + x, t); // 50 to 190 ish
uint8_t newIndexMod = map(noise, 50, 190, -50, +50);
uint8_t newBrightnessMod = map(noise, 50, 190, -40, +40);
//leds[i] = CHSV(hue, 255, 255);
int newIndex = colorPalIndex + newIndexMod;
if (newIndex < 0 ) {
newIndex = 0;
}
else if(newIndex > 240) {
newIndex = 240;
}
int newBrightness = colorBri + newBrightnessMod;
if (newBrightness < 0 ) {
newBrightness = 0;
}
else if(newBrightness > 255) {
newBrightness = 255;
}
CRGB closeColor = ColorFromPalette( myHeatMapPal, newIndex, newBrightness, LINEARBLEND);
leds[i] = blend(leds[i], closeColor, 50);
//leds[i] = closeColor;
}
}
void SetUpPallettes() {
//from https://forum.makerforums.info/t/hi-is-it-possible-to-define-a-gradient-palette-at-runtime-the-define-gradient-palette-uses-the/63339/4
SetupHeatMapPallette();
makeWaves();
}
void SetupHeatMapPallette () {
byte bytes[24];
int bytePos = 0;
bytes[bytePos] = 0;
for(int i = 0; i< 3; i++) {
bytes[i+1] = colTempCoolBlue[i];
}
bytePos+= 4;
bytes[bytePos] = 70;
for(int i = 0; i< 3; i++) {
bytes[i+1+bytePos] = colTempBlueHeat[i];
}
bytePos+= 4;
bytes[bytePos] = 140;
for(int i = 0; i< 3; i++) {
bytes[i+1+bytePos] = colTempViolet[i];
}
bytePos+= 4;
bytes[bytePos] = 180;
for(int i = 0; i< 3; i++) {
bytes[i+1+bytePos] = colTempOrange[i];
}
bytePos+= 4;
bytes[bytePos] = 254;
for(int i = 0; i< 3; i++) {
bytes[i+1+bytePos] = colTempYellow[i];
}
bytePos+= 4;
bytes[bytePos] = 255;
for(int i = 0; i< 3; i++) {
bytes[i+1+bytePos] = colTempYellow[i];
}
myHeatMapPal.loadDynamicGradientPalette(bytes);
}
void makeWaves() {
int waveHeight = 20;
int wavelength = 40;
for (int n = 0; n < NUM_LEDS; n++)
{
int wavePos = n % NUM_LEDS;
float angle = radians(map(wavePos, 0, NUM_LEDS / wavelength , 0, 359));
wavesample[n] = ((waveHeight) + (waveHeight) * sin(angle));
}
}
void initializeLCDScreen() {
lcd.begin(0x27, 16,2);
lcd.backlight();
lcd.print("Intializing");
}