Reach for the stars

The final fabrication of the "Reach for the stars" project, with the LEDs all lightened up in blue
"Reach for the stars" final model

REACH FOR THE STARS

"Reach for the Stars" is a visualized focus timer that enables user to focus on their tasks by displaying four different constellations based on the time phase. My personal interest in constellations enables me to be motivated with my own goals whenever I see them, therefore is a very personal tool for me to focus on my academic assignments.

IMG_5254_1.mp4
Photo of slide potentiometer and rotary encoder nailed on to the top of the main box of final fabrication
Rotary Encoder and Slide potentiometer in place
Partial arrangement of NeoPixels forming a constellation pattern on a screen
The NeoPixels lined up in place on a circular screen
Image showing the completed final project set up in my personal workspace, fully lightened up in red color.
Final project actually present in my workspace

Process Images

A cardboard prototype design with normal LEDs, circular screen, and a box assembled together
Initial prototype of the design made with cardboard (Hello Aidan!)
Running test code in NeoPixel libraries to verify the functionality of all LEDs on the first attempt, shown by green NeoPixels showing off one by one
Running of the test code in NeoPixel libraries to see if all the LEDs are functioning in first attempt
Laser-cut parts of the initial fabrication, with red text indicating areas for dimension editing
Parts of the initial fabrication after laser cutting with red texts to edit dimensions of some aspects of the fabrication
Testing NeoPixel libraries with a different wiring configuration during the second attempt, this time with white LEDs and different configuration
Running of the test code in NeoPixel libraries, wired in a different way in second attempt

The design process for this project began with the creation of an initial prototype using cardboard as the primary material. This served as a tangible starting point, allowing me to visualize and refine the concept. Moving forward, I transitioned from the cardboard prototype to the actual final project fabrication. Using laser cutting, various components were meticulously crafted throughout numerous attempts, as you can see in the second photo with specific elements marked in red to indicate areas requiring dimension adjustments. With the physical structures taking shape, I turned my attention to the crucial functionality of the project. All other components that I have included such as slide potentiometers and rotary encoders did not specifically need extra layers of precision, therefore was an easy process to fabricate and install. However, as the NeoPixel libraries came into play, the functionalities of NeoPixel LEDs took a laborious and long process to execute. The first attempt served as a baseline, and I was satisfied to observe that all the LEDs were functioning as expected, however the wires were fragile enough to break in middle of the critique day. Thus, I decided to rewire the NeoPixel LEDs in a different configuration and resources for a second test run. This adjustment allowed me to fine-tune the lighting effects and explore alternative design possibilities. By iterating and refining our project through these meticulous steps, I was able to transform an initial idea into a well-crafted and functional work of art, embodying both creativity and precision. 

Discussion

One of the responses I received from the critique itself was that the idea was very creative and it was disappointing to see the execution not possible in the actual critique (I agree very much). Another comment I received is that they could see my passion in the overall project. This was really appreciating because I hoped that the audience could at least see my effort in the overall failed attempt at the execution. However, regardless of these great comments from my peers, I don’t really quite appreciate the way my project was made. I do not appreciate how dirty the wiring is, or the material I've used to achieve this kind of look. Although the idea in my head was a very ambitious one, the more and more I worked on the fabrication itself, the project took a turn in a way that I did not anticipate. There are a lot more aspects that I don’t appreciate about it, and I would take this opportunity to say that I have a lot more to learn about in the upcoming weeks. Through this project, I painfully learned that fabrication is not so easy. Although I’ve always had a very high confidence in terms of creating things aesthetically as an art student, I have come to realize that fabrication in terms of ‘design technology’ is a different field that I should study more about. I spent a significant amount of time soldering the wires instead of coding, which was a big surprise on my end because I have so much less confidence AND experience in coding. Overall this project itself was just a huge learning experience; I’ve learned about what I’m incapable / capable of, and learned so much more about the tools that I have overseen in the past. I would not build another iteration of this project just because I want to move on from the fight I’ve battled with this project, but if I had to, I would definitely plan more considerately on each aspects on the project rather than jumping straight into the fabrication and wasting time pondering about what it ‘could have been’. 

Technical Information (Block diagram + Schematic diagram)

Block text of the project 2

Code Submission

// The provided Arduino code orchestrates an interactive system involving a button, a rotary encoder, a slide potentiometer,   // NeoPixel LEDs, and a LiquidCrystal display. It allows users to set and activate a timer through button presses, adjusting   // time with the rotary encoder, and displays time remaining on the LCD. The code features four distinct constellation patterns // displayed via NeoPixel LEDs, done by boolean arrays to control individualized NeoPixels. Additionally, the colors of the LEDs // can be controlled by the slide potentiometer's analog input. When the timer reaches zero, a default pattern illuminates the // final constellation while a concluding message appears on the LCD, creating an engaging visual experience tied to the timer // functionality.


// Pin mapping:

// NeoPixel Chain PIN: 13

// SW in Rotary Encoder: 3

// DT in Rotary Encoder: 4

// Click Pin in Rotary Encoder: 5

// Slide Potentiometer: A0


#include <BfButton.h>

#include <Adafruit_NeoPixel.h>

#include <LiquidCrystal_I2C.h>

#ifdef __AVR__

#include <avr/power.h>

#endif


#define PIN 13

#define NUMPIXELS 12

#define btnPin 3

#define DT 4

#define CLK 5

#define slide A0

int seconds = millis()*1000;


BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW);

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

LiquidCrystal_I2C lcd(0x27,16,2);


// Arrays for different constellation on NeoPixel LEDs

bool libraArray[11] = {1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0};

bool cancerArray[11] = {1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0};

bool dipperArray[11] = {0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1};

bool ariesArray[11] = {0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0};

bool defaultArray[11] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};


int counter = 0;

int setTimer = 0;

int angle = 0; 

int aState;

int aLastState;  

bool systemOn = false;

bool inTimer = false;


int elapsedTime = 0;

int startTime=0;

bool start=0;


//Button press hanlding function for single press, double press, and long press

void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) {

  switch (pattern) {

    case BfButton::SINGLE_PRESS:

      Serial.println("Single push");

      setTimer = counter;

      inTimer = !inTimer;

      break;

      

    case BfButton::DOUBLE_PRESS:

      Serial.println("Double push");

      inTimer = false;

      counter = 0;

      start = 0;

      break;

      

    case BfButton::LONG_PRESS:

      Serial.println("SystemOn!");

      systemOn = !systemOn;

      if (systemOn == true){

        lcd.println("Timer is on!");

      }

      else{

        lcd.println("Timer is off :(");

      }

      Serial.println(systemOn);

      break;

  }

}


void setup() {

  lcd.init();

  lcd.clear();

  lcd.backlight();

  pixels.begin();

  Serial.begin(9600);

  Serial.println(angle);

  pinMode(CLK,INPUT_PULLUP);

  pinMode(DT,INPUT_PULLUP);

  pinMode(slide, INPUT);

  aLastState = digitalRead(CLK);

  btn.onPress(pressHandler)

  .onDoublePress(pressHandler)

  .onPressFor(pressHandler, 1000);

}


void loop() {

  btn.read();

// rotary encoder reading part

  if (systemOn && inTimer==false){

    aState = digitalRead(CLK);

    if (aState != aLastState){     

      if (digitalRead(DT) != aState) { 

        counter ++;

        angle ++;

      }

      else {

        counter--;

        angle --;

      }

      if (counter >=120 ) {

        counter = 120;

      }

      if (counter <=0 ) {

        counter = 0;

      }

      lcd.clear();

      lcd.print(counter);

      }

      aLastState = aState;

      pixels.setBrightness(60);

    }

    else{

      pixels.setBrightness(30);

    }

   

// set the timer if its presse

  if (setTimer > 0 && inTimer == true){

    int timerDuration = setTimer * 60; // in seconds

    if(start==0){

      startTime= starttimer();

      start=1;

    }


    unsigned long mil = millis() / 1000;

    int remainingTime = timerDuration - mil;

    drawsign(timerDuration, remainingTime);

    int LCDPrintRemainingTime = remainingTime / 60;

    lcd.clear();

    lcd.setCursor(0,0);

    lcd.print("Remaining Time:");

    lcd.setCursor(0,1);

    lcd.println(LCDPrintRemainingTime);


    if (remainingTime == 0){

      inTimer = false;

      setTimer = 0;

      counter = 0;

      timerDuration = 0;

      remainingTime = 0;

      elapsedTime = 0;

      ending();

    }

  }

}


// ------------------------------------------------------------------------------------------------------------------------ constellation functions


int starttimer(){

  startTime=millis();

}


void drawsign(int timerDuration, int elapsedTime){

  if ((timerDuration * (3/4)) <= elapsedTime){

    pixels.clear();

    libra();

  }

  else if ((timerDuration * (3/4)) >= elapsedTime && (timerDuration * (1/2)) < elapsedTime ){

    pixels.clear();

    dipper();

  }

  else if ((timerDuration * (1/2)) > elapsedTime && (timerDuration * (1/4)) < elapsedTime){

    pixels.clear();

    aries();

  }

  else if ((timerDuration * (1/4)) > elapsedTime){

    pixels.clear();

    cancer();

  }

}


void libra(){

  int potVal = 0;

  potVal = analogRead(slide);

  int colorVal = map(potVal, 0, 1023, 0, 255);

  pixels.clear();

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

    pixels.setBrightness(100);

    if (libraArray[i]){

    pixels.setPixelColor(i, pixels.Color(colorVal, 150, 255));

    pixels.show();

    }

  }

}


void aries(){

  pixels.clear();

  int potVal = 0;

  potVal = analogRead(slide);

  int colorVal = map(potVal, 0, 1023, 0, 255);

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

    pixels.setBrightness(100);

    if (ariesArray[i]){

    pixels.setPixelColor(i, pixels.Color(colorVal, 150, 255));

    pixels.show();

    }

  }

}


void cancer(){

  int potVal = 0;

  potVal = analogRead(slide);

  int colorVal = map(potVal, 0, 1023, 0, 255);

  pixels.clear();

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

    pixels.setBrightness(100);

    if (cancerArray[i]){

    pixels.setPixelColor(i, pixels.Color(colorVal, 150, 255));

    pixels.show();

    }

  }

}


void dipper(){

  int potVal = 0;

  potVal = analogRead(slide);

  int colorVal = map(potVal, 0, 1023, 0, 255);

  pixels.clear();

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

    pixels.setBrightness(100);

    if (dipperArray[i]){

    pixels.setPixelColor(i, pixels.Color(colorVal, 150, 255));

    pixels.show();

    }

  }

}


void ending(){

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

    pixels.setBrightness(100);

    if (defaultArray[i]){

    pixels.setPixelColor(i, pixels.Color(255, 0, 0));

    pixels.show();

    }

  }

  lcd.print("Reach for the stars");

}