Octagon Display Arduino Sketch

Includes and Definitions

/* Octagon.ino 11/11/2023 This is for the colorful octagonal acrylic slab

  with a groove containing 72 WS2812B neo-pixels.

  It is intended to be used as a stand for a plant or a dish.

  Since there are holes in it and the Adafruit 32u4 3v, 8 MHz ItsyBitsy microcontroller

  is underneath, do not spill water on it.

  The power connector is 5.5x2.1 coax , +ve center,7.5 - 20V, 10W

*/


#include <FastLED.h>

#include <EEPROM.h>


#define potPort A0

#define incPort 2

#define decPort 3

#define LED_PIN     5

#define NUM_LEDS    72

#define BRIGHTNESS  64

#define LED_TYPE    WS2812B

#define COLOR_ORDER GRB

#define NUM_MODES 11          //Thanks to the ColorPalette example in FastLED

#define DOUBLECLICK 800


CRGB leds[NUM_LEDS];


uint8_t displayMode;

bool debugFlag = false;

long doubleClickDelay;        //Prevents a second mode step on release.

int potVal;


CRGBPalette16 currentPalette;

TBlendType    currentBlending;


extern CRGBPalette16 myRedWhiteBluePalette;

extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

Interrupt Handlers

// *********************** Interrupt Handlers *************************

//The mode, which selects the current pallette, is changed by a 3-way momentary switch.


void incSwHardler(void) {

  if ((millis() - doubleClickDelay) > DOUBLECLICK) {

    displayMode++;

    if (displayMode >= NUM_MODES) {

      displayMode = 0;

    }

    debugFlag = true;

    EEPROM.write(0, displayMode);

  }

  doubleClickDelay = millis();

}


void decSwHardler(void) {

  if ((millis() - doubleClickDelay) > DOUBLECLICK) {

    if (displayMode == 0) {

      displayMode = NUM_MODES - 1;

    }

    else {

      displayMode--;

    }

    debugFlag = true;

    EEPROM.write(0, displayMode);

  }

  doubleClickDelay = millis();

}

Palette Definitions

// *********************** Palette Definitions *************************


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;


}


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 );

}


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

};

Display Functions

// *********************** Palette Utilities *************************


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;

  }

}


// This function fills the palette with totally random colors.

void SetupNightimePalette() 

{

  for ( int i = 0; i < 16; ++i) {

    currentPalette[i] = CHSV(potVal, 255, (512-potVal));

  }

}


int ChangePalettePeriodically()

{

int mult = 1000;

  if ( displayMode ==  0)  {

    currentPalette = RainbowColors_p;

    currentBlending = LINEARBLEND;

    mult = 400;

  }

  if ( displayMode == 1)  {

    currentPalette = RainbowStripeColors_p;

    currentBlending = NOBLEND;

    mult = 1800;

  }

  if ( displayMode == 2)  {

    currentPalette = RainbowStripeColors_p;

    currentBlending = LINEARBLEND;

  }

  if ( displayMode == 3)  {

    SetupPurpleAndGreenPalette();

    currentBlending = LINEARBLEND;

    mult = 300;

  }

  if ( displayMode == 4)  {

   SetupNightimePalette();

    currentBlending = LINEARBLEND;

  }

  if ( displayMode == 5)  {

    SetupBlackAndWhiteStripedPalette();

    currentBlending = NOBLEND;

    mult = 400;

  }

  if ( displayMode == 6)  {

    SetupBlackAndWhiteStripedPalette();

    currentBlending = LINEARBLEND;

    mult = 400;

  }

  if ( displayMode == 7)  {

    currentPalette = CloudColors_p;

    currentBlending = LINEARBLEND;

    mult = 250;

  }

  if ( displayMode == 8)  {

    currentPalette = PartyColors_p;

    currentBlending = LINEARBLEND;

    mult = 200;

  }

  if ( displayMode == 9)  {

    currentPalette = myRedWhiteBluePalette_p;

    currentBlending = NOBLEND;

  }

  if ( displayMode == 10)  {

    currentPalette = myRedWhiteBluePalette_p;

    currentBlending = LINEARBLEND;

  }

  return mult;

}

Setup and Loop

// *********************** Setup and Loop *************************


void setup() {

  Serial.begin(9600);

  pinMode(incPort, INPUT);

  pinMode(decPort, INPUT);

  pinMode(LED_PIN , OUTPUT);

  delay(300);

  displayMode = EEPROM.read(0);

  attachInterrupt(digitalPinToInterrupt(incPort), incSwHardler, FALLING);

  attachInterrupt(digitalPinToInterrupt(decPort), decSwHardler, FALLING);

  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

  FastLED.setBrightness(  BRIGHTNESS );


  currentPalette = RainbowColors_p;

  currentBlending = LINEARBLEND;

}


void loop() {

  bool clockwise = false;

  int updatesPerSecond = 12;

  int multiplier = 1000;


  // A potentiometer provides speed and direction of rotation control

  potVal = analogRead(potPort);

  if (potVal > 524) {

    clockwise = true;

    updatesPerSecond = potVal - 512;

  }

  if (potVal < 500) {

    updatesPerSecond =  512 - potVal;

  }


  if (debugFlag) {

    Serial.print("displayMode = ");

    Serial.print(displayMode);

    Serial.print(",pot = ");

    Serial.println(potVal);

    debugFlag = false;

  }


  multiplier = ChangePalettePeriodically(); // Selects current pallette indexed by mode


  static uint8_t startIndex = 0;  // Controls rotation

  if (clockwise) {

    startIndex = startIndex + 1; /* motion speed */

  }

  else {

    startIndex = startIndex - 1;

  }

  FillLEDsFromPaletteColors( startIndex);


  FastLED.show();

  FastLED.delay(multiplier / updatesPerSecond);

}