HomeMadeGarbage
Published

Neopixel LED EyeBall

I made a eye-ball using LED Tape Neopixel. It blink and pupil is moved to the left and right.

IntermediateFull instructions provided15 hours11,646
Neopixel LED EyeBall

Things used in this project

Hardware components

NeoPixel Ring: WS2812 5050 RGB LED
Adafruit NeoPixel Ring: WS2812 5050 RGB LED
NeoPixel tape: https://www.adafruit.com/product/1506
×1
Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
×1
bend sensor
×1
Resistor 10k ohm
Resistor 10k ohm
×3
Resistor 220 ohm
Resistor 220 ohm
×1
Slide Switch
Slide Switch
1 for power, 2 for mode-switching
×3
Rotary potentiometer (generic)
Rotary potentiometer (generic)
10k ohm
×1
Capacitor 1000 µF
Capacitor 1000 µF
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

block diagram

Code

eyeBall.ino

Arduino
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

#define PIN 6

Adafruit_NeoPixel led = Adafruit_NeoPixel(68, PIN, NEO_GRB + NEO_KHZ800);

int blackNum = 24;
int pupilNum = 12;

int colorMode1[10] = {7,8,15,18,29,38,49,52,59,60};
int colorMode2[2] = {18,49};
int colorMode3[2] = {7,60};
int colorMode4[2] = {8,59};
int brightMode1[15] = {7,8,9,15,18,26,29,38,39,40,49,52,58,59,60};
int brightMode2[3] = {18,26,49};
int brightMode3[3] = {7,40,60};
int brightMode4[3] = {8,39,59};

//Black eye L&R animation
int blackLED[15][24] = {{12,32,35,55,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        {12,13,31,36,54,55,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        {11,13,14,30,37,53,54,56,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        {10,11,14,15,29,38,52,53,56,57,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        { 9,10,11,12,15,16,28,33,34,39,51,52,55,56,57,58,68,68,68,68,68,68,68,68},
                        { 0, 8, 9,10,11,12,13,16,17,27,32,35,40,50,51,54,55,56,57,58,59,67,68,68},
                        { 0, 1, 7, 8, 9,10,13,14,17,18,26,31,36,41,49,50,53,54,57,58,59,60,66,67},
                        { 1, 2, 6, 7, 8, 9,14,15,18,19,25,30,37,42,48,49,52,53,58,59,60,61,65,66},
                        { 2, 3, 5, 6, 7, 8,15,16,19,20,24,29,38,43,47,48,51,52,59,60,61,62,64,65},
                        { 3, 4, 5, 6, 7,16,17,20,21,23,28,39,44,46,47,50,51,60,61,62,63,64,68,68},
                        { 4, 5, 6,17,18,21,22,27,40,45,46,49,50,61,62,63,68,68,68,68,68,68,68,68},
                        { 4, 5,18,19,26,41,48,49,62,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        { 4,19,20,25,42,47,48,63,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        {20,21,24,43,46,47,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
                        {21,23,44,46,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68}};

//pupil L&R animation
int pupilLED[15][12] = {{33,34,68,68,68,68,68,68,68,68,68,68},
                        {32,33,34,35,68,68,68,68,68,68,68,68},
                        {12,31,32,33,34,35,36,55,68,68,68,68},
                        {12,13,30,31,32,33,34,35,36,37,54,55},
                        {13,14,29,30,31,32,35,36,37,38,53,54},
                        {14,15,28,29,30,31,36,37,38,39,52,53},
                        {15,16,27,28,29,30,37,38,39,40,51,52},
                        {16,17,26,27,28,29,38,39,40,41,50,51},
                        {17,18,25,26,27,28,39,40,41,42,49,50},
                        {18,19,24,25,26,27,40,41,42,43,48,49},
                        {19,20,23,24,25,26,41,42,43,44,47,48},
                        {20,21,22,23,24,25,42,43,44,45,46,47},
                        {21,22,23,24,43,44,45,46,68,68,68,68},
                        {22,23,44,45,68,68,68,68,68,68,68,68},
                        {22,45,68,68,68,68,68,68,68,68,68,68}};

//Blink animation
int eyelidMode = 0;
int eyelidNum[8] = {0,4,8,16,24,34,44,56};
int eyelidLED[56] = {64,65,66,67,58,59,60,61,56,57,62,63,49,50,51,52,47,48,53,54,38,39,40,41,46,55,36,37,42,43,26,27,28,29,35,44,24,25,30,31,15,16,17,18,34,45,23,32,13,14,19,20,6,7,8,9};

//Bending sensor for Blink
int sensorPin = A5;
int sensorValue = 0;

/*
opration mode
10: demo
00: color adjustment
11: brightness adjustment (0-127)
01: normal
*/
uint32_t color;
int brightness = 40;
int modePin[2] = {11, 12};
int modeVal = 3;

//10kohm volume for adjustment and L&R animation
int pinVR = A4;
int valVR = 1;
int valVRMap = 0;

int waitState = 0;
int demoCnt = 0;


void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
  #if defined (__AVR_ATtiny85__)
    if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  // End of trinket special code

  Serial.begin(115200);

  pinMode(modePin[0], INPUT_PULLUP);
  pinMode(modePin[1], INPUT_PULLUP);

  led.begin();
  led.setBrightness(brightness); // Initial Brightness 40
  led.show(); // Initialize all pixels to 'off'
  color = led.Color(0, 177, 55); // Initial pupil color
}

void loop() {
  modeVal = modeSel();

  //demo mode
  if (modeVal == 2){
    waitState = 0;
    led.clear();
    led.show();
    
    switch (demoCnt) {
      case 0:
        colorWipe(led.Color(127, 0, 0), 50); // Red
        break;
      case 1:
        colorWipe(led.Color(0, 127, 0), 50); // Green
        break;
      case 2:
        colorWipe(led.Color(0, 0, 127), 50); // Blue
        break;
      case 3:
        theaterChase(led.Color(127, 127, 127), 50); // White
        break;
      case 4:
        theaterChase(led.Color(127, 0, 0), 50); // Red
        break;
      case 5:
        theaterChase(led.Color(0, 0, 127), 50); // Blue
        break;
      case 6:
        rainbow(20);
        break;
      case 7:
        rainbowCycle(20);
        break;
      case 8:
        theaterChaseRainbow(50);
        break;
      case 9:
        demoCnt = 0;
        break;
      }
  }

  //color adjustment mode
  if (modeVal == 0){
    if (waitState == 0) {
      led.clear();
      led.show();
      for(uint16_t i=0; i<10; i++) {
        led.setPixelColor(colorMode1[i], color);
      }
      led.show();
      if (modeSel() != 0){return;}
      delay(800);
      for(uint16_t i=0; i<2; i++) {
        led.setPixelColor(colorMode2[i], 0);
      }
      led.show();
      if (modeSel() != 0){return;}
      delay(400);
      for(uint16_t i=0; i<2; i++) {
        led.setPixelColor(colorMode3[i], 0);
      }
      led.show();
      if (modeSel() != 0){return;}
      delay(400);
      for(uint16_t i=0; i<2; i++) {
        led.setPixelColor(colorMode4[i], 0);
      }
      led.show();
      if (modeSel() != 0){return;}
      delay(400);
      led.clear();
      led.show();
      if (modeSel() != 0){return;}
      delay(400);
      waitState = 1;
    }
    if (modeSel() != 0){return;}
    valVR = analogRead(pinVR);
    valVRMap = map(valVR, 0, 512, 0, 255);
    if (valVRMap > 255) {
      valVRMap = 255;
    }
    if (valVRMap < 0) {
      valVRMap = 0;
    }
    
    color = Wheel(valVRMap);
    blink(0, 7);
  }

  //brightness adjustment mode
  if (modeVal == 3){
    if (waitState == 0) {
      led.clear();
      led.show();
      for(uint16_t i=0; i<15; i++) {
        led.setPixelColor(brightMode1[i], color);
      }
      led.show();
      if (modeSel() != 3){return;}
      delay(800);
      for(uint16_t i=0; i<3; i++) {
        led.setPixelColor(brightMode2[i], 0);
      }
      led.show();
      if (modeSel() != 3){return;}
      delay(400);
      for(uint16_t i=0; i<3; i++) {
        led.setPixelColor(brightMode3[i], 0);
      }
      led.show();
      if (modeSel() != 3){return;}
      delay(400);
      for(uint16_t i=0; i<3; i++) {
        led.setPixelColor(brightMode4[i], 0);
      }
      led.show();
      if (modeSel() != 3){return;}
      delay(400);
      led.clear();
      led.show();
      if (modeSel() != 3){return;}
      delay(400);
      waitState = 1;
    }
    if (modeSel() != 3){return;}
    valVR = analogRead(pinVR);
    valVRMap = map(valVR, 0, 512, 3, 70);
    if (valVRMap > 70) {
      valVRMap = 70;
    }
    if (valVRMap < 0) {
      valVRMap = 0;
    }
    
    Serial.print(valVR);
    Serial.print("\t");
    Serial.println(valVRMap);
    
    brightness = valVRMap;
    led.setBrightness(brightness);
    blink(0, 7);
  }

  //normal mode
  if (modeVal == 1) {
    waitState = 0;

    sensorValue = analogRead(sensorPin);
    eyelidMode = map(sensorValue, 770, 815, 0, 8);
    if (eyelidMode > 8) {
      eyelidMode = 8;
    }
    if (eyelidMode < 0) {
      eyelidMode = 0;
    }

    valVR = analogRead(pinVR);
    valVRMap = map(valVR, 314, 456, 14, 0);
    if (valVRMap > 14) {
      valVRMap = 14;
    }
    if (valVRMap < 0) {
      valVRMap = 0;
    }
    
    blink(eyelidMode, valVRMap);
  }
}

byte modeSel(){
  int i,j=0;
  //Get the mode switches state
  for (i=0; i<2; i++) {
    j = (j << 1) | digitalRead(modePin[i]);   // read each input pin
  }
  return j; //return address
}

void blink(int eyelid, int LR) {
  if (eyelid != 8){
    //Pewter
    for(uint16_t i=0; i<led.numPixels(); i++) {
      led.setPixelColor(i, led.Color(66, 66, 66));
    }
    
    //Black eye
    for(uint16_t i=0; i<blackNum; i++) {
      led.setPixelColor(blackLED[LR][i], color);
    }
    
    //pupil
    for(uint16_t i=0; i<pupilNum; i++) {
      led.setPixelColor(pupilLED[LR][i], led.Color(0, 0, 66));
    }

    //eyelid
    for(int i=0; i < eyelidNum[eyelid]; i++) {
      led.setPixelColor(eyelidLED[i], 0);
    }
  } else if (eyelid == 8){
    led.clear();
  }
  led.show();
}

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

//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 (int i=0; i < led.numPixels(); i=i+3) {
        led.setPixelColor(i+q, c);    //turn every third pixel on
        if (modeSel() != 2){return;}
      }
      led.show();
      delay(wait);
      
      for (int i=0; i < led.numPixels(); i=i+3) {
        led.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
  demoCnt++;
}

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

  for(j=0; j<256; j++) {
    for(i=0; i<led.numPixels(); i++) {
      led.setPixelColor(i, Wheel((i+j) & 255));
      if (modeSel() != 2){return;}
    }
    led.show();
    delay(wait);
  }
  demoCnt++;
}

// 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< led.numPixels(); i++) {
      led.setPixelColor(i, Wheel(((i * 256 / led.numPixels()) + j) & 255));
      if (modeSel() != 2){return;}
    }
    led.show();
    delay(wait);
  }
  demoCnt++;
}

//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 (int i=0; i < led.numPixels(); i=i+3) {
        led.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
        if (modeSel() != 2){return;}
      }
      led.show();
      delay(wait);

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

// 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 led.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return led.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return led.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Credits

HomeMadeGarbage

HomeMadeGarbage

56 projects • 285 followers
We are family. hobby is D.I.Y!!

Comments