A. PARENTING YOUR CHILD FOR YOU
B. FINISHED DOCUMENTATION VIDEOS
C. CONCEPTUALIZATION AND DESIGN
Initially, my design was rather complex, a carousel looking music box, but it made no sense and needed to be simplified to a smaller object that could be picked up and shaken. I wanted it to mainly address shaken baby syndrome, which is caused by the purposeful neglect and abuse against children. I wanted it to have a minigame where you could either shake the box or let it play music. If the box was shaken, you'd be put into a difficult game where you'd need to use the drawer and the crank to fight off blood drops. the design needed to be less gory since it'd be too dark. During the user testing session, it wasn't exactly refined to test with the sensors, but I was recommended to cover the potentiometer.
D. CONCEPTUALIZATION AND DESIGN
I initially wanted to 3D print my components, as seen in this STL I created through tinkercad. What ended up happening was that the box was lasercutted as it'd take 3 days to fully print the STL I made. I mainly struggled with the code on the processing side. I wasn't sure how the states exactly worked nor did I understand the time function that well. I tried to swap states and it'd end up bringing components from other states to a different one. I mainly used a potentiometer, 360 servo, vibration sensor and LDR for the drawer. I wish I filled the drawer with glitter and balls inside that would be stuck to a string if held upside down. I ended up rejecting the idea to 3D print a baby as someone suggested since I was already too deep in the subtlety of symbolism. The main problem I encountered was the components breaking down suddenly or not working anymore.
E. CONCLUSIONS
It achieved its goals and mainly was based on shaking and doing a very tight sealed interaction that was difficult to perform with the consequence of shaking the box. My project was portable, one could easily pick it up as it was light-weight and that aligns with my definition since its something people can use.
If I had more time on the project, I'd refine the details and make it less silly, give it more paint, etc. When it comes to projects like this, it's important to not overestimate what can be done in a day vs underestimating what can be done in one. I overestimated my expectations and that ultimately made it compressed. I mainly sought out assistance from the LAs and TAs for coding and it assisted to have visual representations of what was needed.
F. DISASSEMBLY
G. APPENDIX
#include <Servo.h>
Servo SERVO360;
#define NUM_OF_VALUES_FROM_PROCESSING 1 /* CHANGE THIS ACCORDING TO YOUR PROJECT */
int PIN_FIVE = 5; //PIN 2 IS AN LED
int PIN_FOUR = 4; //PIN 4 IS AN LED
int PIN_SEVEN = 7;
/* This array stores values from Processing */
int processing_values[NUM_OF_VALUES_FROM_PROCESSING];
int LDR = A0; //LDR = A0
int VIBRATION_SENSOR = A1; //VS to A1
int PRESSURE_SENSOR = A2; //force sensor is at A2
int POTENTIOMETER = A3; // we are digitally reading it
void setup() {
Serial.begin(9600);
pinMode(PIN_FIVE, OUTPUT); //this receives data
pinMode(PIN_FOUR, OUTPUT); //THIS IS GREEN LED
pinMode(PIN_SEVEN, OUTPUT); // sending the data if it is on or off
SERVO360.attach(9);
SERVO360.write(90);
}
void loop() {
getSerialData();
//ANALOG SENSORS/SENSORS INTENDED TO BE ANALOG
// int PRS = analogRead(PRESSURE_SENSOR); // PRS IS READING THE ANALOG SENSOR
// int VS = analogRead(VIBRATION_SENSOR); //Vibration Sensor is being read in VS
int LDRS = analogRead(LDR);
int POT = analogRead(POTENTIOMETER); // this sensor is being read digitally
int VIB = analogRead(VIBRATION_SENSOR);
int PRE = analogRead(PRESSURE_SENSOR);
Serial.print(LDRS); ///Value 1 == bend sensor
Serial.print(",");
Serial.print(VIB); // Value 2 == vibration sensor
Serial.print(",");
// Serial.print(PRE); //value 3 == Force sensor 01
// Serial.print(",");
Serial.print(POT); //Value 4 == potentiometer
Serial.println();
// int pos = 10;
// for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
// // in steps of 1 degree
// SERVO360.write(pos); // tell servo to go to position in variable 'pos'
// delay(15);
// pos // waits 15 ms for the servo to reach the position
// }
// SERVO360.write(180);
// delay(1000);
// digitalWrite(PIN_FOUR, HIGH);
// digitalWrite(PIN_FIVE, HIGH);
// add your code here using elements in the values array
if (processing_values[0] == 1) {
SERVO360.write(160);
delay(100);
// Serial.println("LEDS ACTIVE");
} else {
// digitalWrite(PIN_TWO, LOW);
digitalWrite(PIN_FOUR, LOW);
digitalWrite(PIN_SEVEN, LOW);
// Serial.println("LEDS INACTIVE");
SERVO360.write(90);
}
if(processing_values[0] == 2)
{
digitalWrite(PIN_FOUR, HIGH);
delay(10);
SERVO360.write(160);
delay(100);
}
} // end of VOID LOOP
/* Receive Serial data from Processing */
/* You won't need to change this code */
void getSerialData() {
static int tempValue = 0; // the "static" makes the local variable retain its value between calls of this function
static int tempSign = 1;
static int valueIndex = 0;
while (Serial.available()) {
char c = Serial.read();
if (c >= '0' && c <= '9') {
// received a digit:
// multiply the current value by 10, and add the character (converted to a number) as the last digit
tempValue = tempValue * 10 + (c - '0');
} else if (c == '-') {
// received a minus sign:
// make a note to multiply the final value by -1
tempSign = -1;
} else if (c == ',' || c == '\n') {
// received a comma, or the newline character at the end of the line:
// update the processing_values array with the temporary value
if (valueIndex < NUM_OF_VALUES_FROM_PROCESSING) { // should always be the case, but double-check
processing_values[valueIndex] = tempValue * tempSign;
}
// get ready for the new data by resetting the temporary value and sign
tempValue = 0;
tempSign = 1;
if (c == ',') {
// move to dealing with the next entry in the processing_values array
valueIndex = valueIndex + 1;
} else {
// except when we reach the end of the line
// go back to the first entry in this case
valueIndex = 0;
}
}
}
} // END OF GET SERIAL DATA
Processing Code:
//any libraries
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim;
AudioPlayer LULLABY;
AudioPlayer CRY;
AudioPlayer BEEP;
AudioPlayer LOSE;
AudioPlayer WIN;
import processing.serial.*; //serial communications library
// global variables
int state = 0; //this is to test to make sure it runs into state 3 as expected, will be set to 0 when finalized
int count = -1; //count is set to -1 to prevent misclicks
PImage CURSOR; //assigned to cursor
int NUM_OF_VALUES_FROM_PROCESSING = 1; //only one value from processing -> arduino
int NUM_OF_VALUES_FROM_ARDUINO = 3; //only TWO value from arduino -> processing (right now)
int FAIL_STATE_TRUE = 0;
int ballCount;
//for the "food", will make a void function to be called for it
float[] cxs = new float[25];
float[] cys = new float[25];
float[] csizes = new float[25];
color[] colors = new color[25];
float[] cxspeeds = new float[25];
float[] cyspeeds = new float[25];
boolean[] cb = new boolean[25];
boolean[] pcb = new boolean[25];
//snow white
float[] snowxs = new float[10];
float[] snowys = new float[10];
float[] snowsizes = new float[10];
color[] snowcolors = new color[10];
float[] snowxspeeds = new float[10];
float[] snowyspeeds = new float[10];
int target = 0;
int ptarget = 0;
Serial serialPort; //import serialPort
int gameStartTime;
//arrays
int arduino_values[] = new int[NUM_OF_VALUES_FROM_ARDUINO]; //makes a new array for the values from Arduino
int processing_values[] = new int[NUM_OF_VALUES_FROM_PROCESSING]; //makes a new array for the values from processing
void setup(){
size(500,500);
background(0);
minim = new Minim(this);
LULLABY = minim.loadFile("LULLABY.mp3"); //first audio
CURSOR = loadImage("CURSOR.png");
BEEP = minim.loadFile("BEEP.mp3");
CRY = minim.loadFile("CRY.mp3");
LOSE = minim.loadFile("LOSE.mp3");
WIN = minim.loadFile("WIN.mp3");
printArray(Serial.list());
serialPort = new Serial(this, "COM7", 9600);
//for the "monsters"
for (int i=0; i < 25; i=i+1) {
cxs[i] = random(0, width);
cys[i] = random(0, height);
csizes[i] = random(50,70);
colors[i] = color(random(255),random(255), random(255));
cxspeeds[i] = random(1, 5);
cyspeeds[i] = random(1, 5);
cb[i] = false;
}
//for snow
for (int i=0; i < 10; i=i+1) {
snowxs[i] = random(width);
snowys[i] = random(height);
snowsizes[i] = random(10, 60);
snowcolors[i] = color(0);
snowxspeeds[i] = random(1, 5);
snowyspeeds[i] = random(1, 5);
}
} //end of set up
void draw(){
sendSerialData();
getSerialData();
background(0);
if(state == 0){
text("CRANK TO START", 250, 250);
textSize(20);
LULLABY.loop();
int POTENTIOMETER = arduino_values[2];
//println(POTENTIOMETER);
int value = POTENTIOMETER;
if(value == 1023){
state = 1;
}
}
if(state == 1){
for (int i=0; i<height; i++){
float b = map(i, 0, height, 0, 251);
float g = map(i, 0, height, 0, 229);
float r = map(i, 0, height, 0, 252);
stroke(r, g, b);
line(0, i, width, i);
text("Don't shake the box!", 150, 250);
textSize(20);
}
//println(LULLABY.position());
if(LULLABY.position() >= 15000){
processing_values[0] = 1;}
for (int i=0; i < 10; i=i+1) {
fill(#FFFFFF);
noStroke();
circle(snowxs[i], snowys[i], snowsizes[i]);
snowxs[i] = snowxs[i] + snowxspeeds[i];
snowys[i] = snowys[i] + snowyspeeds[i];
// check right edge
if (snowxs[i] > width) {
snowxs[i] = 0;
}
// check bottom edge
if (snowys[i] > height) {
snowys[i] = 0;
}
}
if(arduino_values[1] >= 19){
background(#FF0026);
count++;
LULLABY.pause();
//play cry
BEEP();
if(count == 3){
state = 3;
CRY.loop();
}
}else{
LULLABY.play();
}
//end if = 3
}
//play lullaby
//STATE 3 IS OUR TRANSITION, RESET ALL VARIABLES HERE
if(state == 3){
state = 4;
gameStartTime = millis();
count = -1;
processing_values[0] = 0;
} //end of state 3
//state 4 is our GAME
if (state == 4) {
int target = 0;
float x = arduino_values[2];
float y = arduino_values[0];
x = map(arduino_values[2], 0, 1023, 0, width);
y = map(arduino_values[0],0,900,0,height);
fill(#FFFFFF);
circle(x, y, 10);
pushMatrix();
translate(x,y);
rotate(radians(map(y, 0, height, 0, 360)));
image(CURSOR,0,0,width/5,height/5);
popMatrix();
for (int i=0; i < 25; i=i+1) {
noStroke();
fill(colors[i]);
circle(cxs[i], cys[i], csizes[i]);
// chase balls away
if (dist(x, y, cxs[i], cys[i]) < csizes[i]/2+20) {
if (x > width/2) {
cxs[i] = cxs[i]+10;
}
if (x < width/2) {
cxs[i] = cxs[i]-10;
}
if (y > height/2) {
cys[i] = cys[i]+10;
}
if (y < height/2) {
cys[i] = cys[i]-10;
}
}
// check if passed edges
if (cxs[i] > width+10 || cxs[i] < -10 || cys[i] > height+10 || cys[i] < -10) {
cb[i] = true;
if (pcb[i] == false && cb[i] == true) {
target++;
pcb[i] = cb[i] ;
target = ptarget + target;
ptarget = target;
println(target);
println(state);
if(target >= 25){
state = 6;
}
}
}
if (millis() > gameStartTime + 40000) { //if 20 seconds passes without completing the game, you fail.
state = 5;
if (state == 5) {
cxs[i] = random(100, width-500);
target = 0;
cys[i] = random(100, height-500);
}
}
//for each cb=true target++
}
}
if(state == 5){
LOSE.play();
println("STATE IS NOW FAIL");
fill(#ffffff);
text("You Failed... wait 30 secs to try again", 50, 50);
textSize(60);
if(millis() > gameStartTime + 30000){
state = 2;
}
}
if(state == 6){
fill(#ffffff);
WIN.play();
processing_values[0] = 2;
fill(0);
text("You win! To reset, put the crank to 0 and the drawer back in",10,10);
if(arduino_values[2] == 0 && arduino_values[0] <= 50){
state++;
}
}
if(state >= 7){
state = 0;
processing_values[0] = 0;
}
}
//if target == 25 then move to state 6
//for loop end
//println(ballCount);
// check if passed edges
//for state 4
//where void draw ends
// END OF DRAW
//draw ehds
// STATE 4 END
//end if state = 3
//STATE 5 iS OUR FAIL WHICH GOES BACK TO STATE 3
//state 6 is the win state, which will transition to the next stage of the project
//println(state);
//end of draw
//void mousePressed(){
//if(state == 2){
// count++; //adds to the count if neither state or count = 3
// } //end else state or count not == 3
// if(state == 4){
// }
//} //end of mouse pressed loop
//don't touch this
void sendSerialData() {
String data = "";
for (int i=0; i<processing_values.length; i++) {
data += processing_values[i];
// if i is less than the index number of the last element in the values array
if (i < processing_values.length-1) {
data += ","; // add splitter character "," between each values element
}
// if it is the last element in the values array
else {
data += "\n"; // add the end of data character linefeed "\n"
}
}
// write to Arduino
serialPort.write(data);
//print("To Arduino: " + data); // this prints to the console the values going to arduino
} // end of send serial data
void getSerialData() {
while (serialPort.available() > 0) {
String in = serialPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII
if (in != null) {
print("From Arduino: " + in);
String[] serialInArray = split(trim(in), ",");
if (serialInArray.length == NUM_OF_VALUES_FROM_ARDUINO) {
for (int i=0; i<serialInArray.length; i++) {
arduino_values[i] = int(serialInArray[i]);
}
}
}
}
} //end of get Serial Data
void BEEP(){
BEEP.play();
}