The Cube
The Cube is meant to be a mysterious device. I will not tell you what it is or does because I want you to discover and imagine it.
Please feel free to pick it up and play with it as you please.
To Reset the cube for the next user please move the switch under the speaker.
Nurture Yourself
Nurture Yourself is a new way to measure your daily health. Its purpose is to remind us to nurture all aspects of ourselves whether it be mind, body or soul. This sculpture is meant to be a feel good device with a childlike whimsy. My hope is that it brings you joy and helps you on your path of growth today.
Please feel free to interact with the board, and follow the guide to see how much you have nurtured yourself today.
If the string slips behind the pulley please return it to its wheel
Fixing the cube and balancing out the weights on Nurture was relatively easy, but a little time consuming. I learned a lot about trail and error in those last weeks but it was very satisfying to get my two projects, which were as I thought, very close to done finally finished and working the way I semi imagined them to was very satisfying.
For the Cube all I had to do was rewire the power, which I found was interfering with the ability of the speaker to speaker and perhaps overpowering some components causing them to shutdown part way through the sequence. After rewiring I reassembled the cube and added some more satisfying light sequences to the pattern. I had the fun idea to add a song at the end that only plays after the cube has turned red, making the user think it might blow up only to change to a fun sequence of multi colored lights that danced and sang.
For Nurture yourself, I added three clear laser cut bins for the charms to go on while the piece was mounted on the wall, this way they were easily accessible by the user and visible at the same time. I also added a fun illustrated chart off to the side of the board that told you what charm was for what and how to use the board. Finally I switched out the rubber bands with stronger bands, which I cut from a bigger onw until they worked, and then I filled the baskets with Lead so they would be heavier, easier to reset and to not pull at each other, but light enough to effect the bands when the charms went into them. I also went back with some glue to make sure the rubber bands stayed attached, which didn't end up working out as well as I hoped.
I enjoyed staging my cube, because I believe it gave it the reverence it deserved. I printed a little base so it could be propped up at an angle, to give it an antigravity look. The thing I found most difficult was making clear where the power button was and the fact that it needed to be turned on and off or else it would loose batteries. If I could go back Intime I would have installed a bigger battery pack or just made the whole thing electrical despite the cord.
I think hanging Nurture yourself from the wall helped it to be at eye level for the users, which made for sense for the use and the visual. I think again in the back and time land: I would have loved to make this work bigger, and honestly in the future land I might. it was very rewarding to see people interact with both pieces. It was a very meaningful and growing experience. I wish the showcase was limited to the first 30 minutes where everything was working perfectly, but despite that I learned a lot about trouble shooting on the spot and setting up for exhibitions. I am proud of my work overall and enjoyed the experience.
// Project: The Cube
// Electronic Logics and Creative Practice 2023
// Evette LaComb
// Pin Map:
// 5 - switch one
// 4 - switch two
// 3 - switch three
// 2 - switch four
// 6 - neopixel LEDs
// 10 - speaker
// 11 - speaker
// This code reads switches and then lights LEDs and plays Sounds based on a mode number
// I used a neopixel and a speaker library in this code I did not write.
int TOGone = 5;
int TOGtwo = 4;
int TOGthree = 3;
int TOGfour = 2;
int gReen = 200;
int bLue = 200;
int rEd = 0;
int brightness = 250;
int mode = 0;
int resetLED = false;
int pix = 48;
int START = 3;
int PRO = 2;
int FIN = 1;
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
#define NUMPIXELS 48 // Popular NeoPixel ring size
#define LED_COUNT 48//
#define LED_PIN 6
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 200 // Time (in milliseconds) to pause between pixels
//////////
//SPEAKER stuff
#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266)) // Using a soft serial port
#include <SoftwareSerial.h>
SoftwareSerial softSerial(/*rx =*/10, /*tx =*/11);
#define FPSerial softSerial
#else
#define FPSerial Serial10p...
#endif
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
pinMode(TOGone, INPUT);
pinMode(TOGtwo, INPUT);
pinMode(TOGthree, INPUT);
pinMode(TOGfour, INPUT);
// light stuff
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
pixels.begin();
/////////////////////////////////////
//Speaker Stuff
#if (defined ESP32)
FPSerial.begin(9600, SERIAL_8N1, /*rx =*/D3, /*tx =*/D2);
#else
FPSerial.begin(9600);
#endif
Serial.begin(115200);
if (!myDFPlayer.begin(FPSerial, /*isACK = */true, /*doReset = */true)) { //Use serial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true){
delay(0); // Code to compatible with ESP8266 watch dog.
}
}
myDFPlayer.volume(20); //Set volume value. From 0 to 30
}
void loop() {
//Serial.println(mode);
/////////////////////////////////////////////
int TOGR1 = digitalRead(TOGone);
int TOGR2 = digitalRead(TOGtwo);
int TOGR3 = digitalRead(TOGthree);
int TOGR4 = digitalRead(TOGfour);
// int TOGR1 = HIGH;
// int TOGR2 = LOW;
// int TOGR3 = HIGH;
// int TOGR4 = HIGH;
////////////////////////////////
///RESET THE LEDS WHEN TURING ON
if(resetLED == false){
for(int i=0; i<48; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
resetLED = true;
}
////////////////////////////////
// START UP LIGHT SHOW
if (mode == 0){
myDFPlayer.play(START);
colorWipe(strip.Color( 0, 100, 200), 50); // Blue
mode += 1;
}
//////////////////
//CASE ONE
if (mode == 1){
if (((TOGR1 == HIGH) | (TOGR2 == HIGH) | (TOGR3 == LOW)) && (TOGR4 == HIGH)){
myDFPlayer.play(PRO);
for(int i=0; i<7; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 1 complete");
mode += 1;
}
}
////////////////////////
//CASE TWO
if (mode == 2){
if(((TOGR1 == LOW) | (TOGR2 == LOW) | (TOGR3 == LOW)) && (TOGR4 == LOW)){
myDFPlayer.play(PRO);
for(int i=7; i<15; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 2 complete");
mode += 1;
}
}
if (mode == 3){
if(((TOGR1 == LOW) | (TOGR2 == LOW)) && ((TOGR3 == LOW) && (TOGR4 == HIGH))){
myDFPlayer.play(PRO);
for(int i=15; i<23; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 3 complete");
mode += 1;
}
}
if (mode == 4){
if(((TOGR1 == HIGH) | (TOGR2 == LOW)) && ((TOGR3 == HIGH) && (TOGR4 == HIGH))){
myDFPlayer.play(PRO);
for(int i=23; i<31; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 4 complete");
mode += 1;
}
}
if (mode == 5){
if(((TOGR1 == LOW) && (TOGR2 == LOW)) && ((TOGR3 == LOW) | (TOGR4 == LOW))){
myDFPlayer.play(PRO);
for(int i=31; i<39; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 5 complete");
mode += 1;
}
}
if (mode == 6){
if((TOGR1 == HIGH) && (TOGR2 == HIGH) && (TOGR3 == HIGH) && (TOGR4 == HIGH)){
myDFPlayer.play(PRO);
for(int i=39; i<47; i++) {
pixels.setPixelColor(i, pixels.Color(0, 200, 200));
pixels.show();
delay(DELAYVAL);
}
Serial.println("mode 6 complete");
delay(1000);
mode += 1;
}
}
if (mode == 7){
myDFPlayer.play(FIN);
delay(450);
for (int i=0; i<10; i ++){
gReen = (gReen - 20);
bLue = (bLue - 20);
rEd = (rEd + 20);
for(int i=0; i<47; i++) {
pixels.setPixelColor(i, pixels.Color(rEd, gReen, bLue));
pixels.show();
}
delay(50);
}
delay(4000);
rainbow(1);
mode += 1;
}
}
/////COPIES FUNCTIONS FROM EXAMPLE CODE
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<47; i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
delay(1000);
for (int i=0; i <10; i++){
brightness = (brightness - 25);
strip.setBrightness(brightness);
strip.show();
delay(wait);
}
}
void rainbow(int wait) {
strip.setBrightness(250);
// Hue of first pixel runs 5 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
// means we'll make 5*65536/256 = 1280 passes through this loop:
for(long firstPixelHue = 0; firstPixelHue < 10*65536; firstPixelHue += 265) {
// strip.rainbow() can take a single argument (first pixel hue) or
// optionally a few extras: number of rainbow repetitions (default 1),
// saturation and value (brightness) (both 0-255, similar to the
// ColorHSV() function, default 255), and a true/false flag for whether
// to apply gamma correction to provide 'truer' colors (default true).
strip.rainbow(firstPixelHue);
// Above line is equivalent to:
// strip.rainbow(firstPixelHue, 1, 255, 255, true);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}