Jeremy Gilbert
Published © MIT

Tic-Tac-LED Explorer

Awesome Bluetooth-controlled bottle of Tic Tacs with every color under the sun, powered by Light Blue Bean.

IntermediateShowcase (no instructions)3 hours1,063
Tic-Tac-LED Explorer

Things used in this project

Hardware components

LightBlue Bean
Punch Through LightBlue Bean
×1
Adafruit Neopixel Strands
×1
Adafruit Level Converter
×1
Adafruit LiPo Backpack
×1
Polulu 5V Step up
×1
Adafruit Lipo
×1

Story

Read more

Schematics

Schematic

Code

lbb_tictac_v1d.ino

Arduino
Controller for the light blue bean
#include <Adafruit_NeoPixel.h>
#include <PinChangeInt.h> 

// 7,5,7 = 19

#define NEO_PIN 4
#define BUCKENABLE_PIN 2
#define BUTTON_PIN 1

#define INACTIVETIMER 60000
#define FADETIME 5000

#define MAXBRIGHTNESS 70

/*

  Pins 2 and 3 are the normal interrupt pins, not available on LBB

AVR            LBB    Arduino
PD6 AIN0       D0     D6
PB1 oc1a    -> D1     D9
pb2 ss oc1b    D2     D10
pb3 mosi oc2   D3     D11
pb4 miso       D4     D12
pb5 sck        D5     D13

*/
#define BUF_SIZE 64
char buffer[BUF_SIZE] = {0};

// Sandbox control IDs
const char MSG_XYPAD_X = 8;
const char MSG_XYPAD_Y = 9;
const char MSG_XYPAD_Z = 11;
const char MSG_PAGEA_SLIDER_0 = 0;
const char MSG_PAGEA_SLIDER_1 = 2;


char brightness = 30;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(19, NEO_PIN, NEO_GRB + NEO_KHZ800);



boolean powerState = 0;

void powerDown()
{
  if ( powerState == 1 )
  {
    if( brightness > MAXBRIGHTNESS )
      brightness = MAXBRIGHTNESS;
    strip.setBrightness( brightness );
    for (uint16_t i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
    }
    strip.show();
    delay(5);

    digitalWrite( BUCKENABLE_PIN, LOW );

    powerState = 0;
  }
  Bean.setLed(0, 0, 0);
}

void powerUp()
{
  if ( powerState == 0 )
  {
    digitalWrite( BUCKENABLE_PIN, HIGH );
    delay(10); // Delay for the power source to stabilize

    for (uint16_t i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, strip.Color(0, 0, 0));
    }
      if( brightness > MAXBRIGHTNESS )
      brightness = MAXBRIGHTNESS;
    strip.setBrightness( brightness );
    strip.show();
    powerState = 1;
    Bean.setLed(0, 255, 0);
  }
}

void pinChanged() {
   Bean.setLed(255, 0, 0);
   Bean.sleep(5);
   Bean.setLed(0, 0, 0);
}

void setup()
{
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

attachPinChangeInterrupt(BUTTON_PIN, pinChanged, CHANGE);

  Bean.enableWakeOnConnect(true);
  pinMode( BUTTON_PIN, INPUT );
  pinMode( BUCKENABLE_PIN, OUTPUT );
  digitalWrite( BUCKENABLE_PIN, HIGH );
 digitalWrite( BUTTON_PIN, HIGH );
  powerUp();

  Serial.begin( 57600 );
  Serial.setTimeout(5);
}

char red;
char blue;
char green;

unsigned long lastInteraction = 0;

void renderBasic()
{

  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(red, green, blue));
  }
  strip.show();

}

boolean lastButtonState = 0;


boolean fadeActive;

void loop()
{
  boolean connected = Bean.getConnectionState();


  if( !digitalRead( BUTTON_PIN ) )
  {
      lastButtonState = 1;
  }
  else
  {
     if( lastButtonState == 1 )
     {
        // simple rainbow
      powerUp();
        rainbowCycle(1);
      lastInteraction = millis();
     }

     lastButtonState = 0;
  }

  if (connected)
  {
    int length = Serial.readBytes(buffer, BUF_SIZE);
    if (length > 0) {
      powerUp();
      lastInteraction = millis();

      // Iterate over sandbox messages by processing groups of two bytes.
      for (char i = 0; i < length - 1; i += 2) {

        if (buffer[i] == '1') {
          red = 40;
          blue = 255;
          green = 10;
          renderBasic();


        } else if (buffer[i] == 'y') {
            red = 255;
          blue = 0;
          green = 255;
          renderBasic();
        }else if (buffer[i] == MSG_XYPAD_X) {
            red = buffer[i + 1];
            renderBasic();


          }
          else if (buffer[i] == MSG_XYPAD_Y) {
            blue = buffer[i + 1];
            renderBasic();


          }
          else if (buffer[i] == MSG_XYPAD_Z) {
            green = buffer[i + 1];
            renderBasic();


          }
          else if (buffer[i] == MSG_PAGEA_SLIDER_0) {
            brightness = buffer[i + 1];
              if( brightness > MAXBRIGHTNESS )
      brightness = MAXBRIGHTNESS;
            strip.setBrightness(brightness);
            strip.show();
          }
                 else if (buffer[i] == MSG_PAGEA_SLIDER_1) {
            int j = buffer[i + 1];
  for (int x = 0; x < strip.numPixels(); x++) {
      strip.setPixelColor(x, Wheel(((x * 256 / strip.numPixels()) + j) & 255));
    }
            strip.show();
          }
      }
    }

//
//    unsigned long now = millis();
//    if ( (now - lastInteraction) > INACTIVETIMER )
//    {
//      //fadeActive = 1;
//      //char newBSetting = int( 1.0 * brightness * (1.0 * (now - lastInteraction - INACTIVETIMER) / FADETIME) );
//
//      //strip.setBrightness( newBSetting );
//      // strip.show();
//
//    }
//    else
//    {
//      if ( fadeActive )
//      {
//        fadeActive = 0;
//        strip.setBrightness( brightness );
//        strip.show();
//      }
//
//
//    }

  }
  else {


    unsigned long now = millis();
    if ( (now - lastInteraction) > INACTIVETIMER )
    {
      powerDown();
      // Sleep forever or until the Bean wakes up by being connected to
      Bean.sleep(0xFFFFFFFF);
    }
  }

  //
  //  // Some example procedures showing how to display to the pixels:
  //  colorWipe(strip.Color(255, 0, 0), 50); // Red
  //  colorWipe(strip.Color(0, 255, 0), 50); // Green
  //  colorWipe(strip.Color(0, 0, 255), 50); // Blue
  ////colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW
  //  // Send a theater pixel chase in...
  //  theaterChase(strip.Color(127, 127, 127), 50); // White
  //  theaterChase(strip.Color(127, 0, 0), 50); // Red
  //  theaterChase(strip.Color(0, 0, 127), 50); // Blue
  //
  //  rainbow(20);
  //  rainbowCycle(20);
  //  theaterChaseRainbow(50);
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Credits

Jeremy Gilbert

Jeremy Gilbert

1 project • 0 followers
weekend hacker.

Comments