Ligament rehabilitation for climbers requires consistent and moderate work-out training. However, it would become a tidious seesion that not everyone has the perserverance to keep it as a daily routine. Ligament Rehabilitation Incubator allows users to have fun with gachapon discoveries during their training sessions and encourage them to work out everyday.
I designed an "incubator" equipment with soft materials to improve user comfort. The device can collect data, assist in, and adjust climbers' recovery training accordingly. Those data can be used as parameters to determine the type of unknown gachapons.
Gachapons in various types give visual feedback, suggesting the progress and the quality of the training session. It's monitering the gripping presure, sweating, heart beating, temperature, and work-out progress, etc, which would further determine what will spawn from the gachapon.
Default state of various gachapons
During the training sessions
The product was rapidly prototyped with the combination of Arduino Uno R3 and Processing. It contains several electronic components to detect temperature, humidity, skin conductivity, heart beats, and gripping pressure as game parameters.
#include//import capacitive sensing library #include "DHT.h" #define DHTPIN 2 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); int ref0; int led1 = 13; int led2 = 12; void setup() { // put your setup code here, to run once: Serial.begin(9600); // *initialization - make the connection to the UNO board //Serial.println(F("DHTxx test!")); dht.begin(); ref0 = ADCTouch.read(A0, 500); //Initial reference value // pinMode(led1, OUTPUT); // pinMode(led2, OUTPUT); } void loop() { // put your main code here, to run repeatedly: int value0 = ADCTouch.read(A0); // Read value of pin A0 value0 = value0 - ref0; //Serial.print (","); //delay(10); delay(100); float h = dht.readHumidity(); float t = dht.readTemperature(); float f = dht.readTemperature(true); // Check if any reads failed and exit early (to try again). if (isnan(h) || isnan(t) || isnan(f)) { Serial.println(F("Failed to read from DHT sensor!")); return; } // Compute heat index in Fahrenheit (the default) //float hif = dht.computeHeatIndex(f, h); // Compute heat index in Celsius (isFahreheit = false) //float hic = dht.computeHeatIndex(t, h, false); if (value0 > 30) { digitalWrite (led1, HIGH); digitalWrite (led2, LOW); } else { digitalWrite(led1, LOW); digitalWrite(led2, HIGH); } Serial.print(value0); Serial.print(','); Serial.print(h); Serial.print(','); Serial.println(t); // Serial.print(','); // Serial.println(f); // Serial.print(F("Conductive Value: ")); // Serial.print(value0); // Serial.print(F(" Humidity: ")); // Serial.print(h); // Serial.print(F("% Temperature: ")); // Serial.print(t); // Serial.print(F("C ")); // Serial.print(f); // Serial.print(F("F Heat index: ")); // Serial.print(hic); // Serial.print(F("C ")); // Serial.print(hif); // Serial.println(F("F")); // digitalWrite (led1, HIGH); // digitalWrite (led2, LOW); // delay(2000); // digitalWrite(led1, LOW); // digitalWrite(led2, HIGH); // delay(200); //remember to check tools => board + port }
import processing.serial.*; // importing processing serial library for connecting with arduino Serial myPort; //usb port String val; //incoming data from arduino as character - string String[] stringData; float v, h, t; int sensorVal; //we use this variable for the data as number type float angle = 0; float sunMovement = 0; float accum_v = 0; float sun_color = 0; float sun_radiate = 120; float sun_radiate_alpha = 255; //Egg egg1; float tiltAmp = 1; PImage grass01; PImage grass02; PImage grass03; PImage grass04; PImage egg01; PImage egg02; PImage egg03; PImage egg04; int x = 0; int y = 0; float spacing = 20; float diameter = 10; void setup(){ size(displayWidth, displayHeight); //egg1 = new Egg(displayWidth/2, displayHeight/2, 0, 150); String portName = "/dev/cu.usbmodem14301"; //find port name in arduino sogtware and put it here myPort = new Serial(this, portName, 9600); //create serial connection myPort.bufferUntil('\n'); //load all image grass01 = loadImage("Grass01.png"); grass02 = loadImage("Grass02.png"); grass03 = loadImage("Grass03.png"); grass04 = loadImage("Grass04.png"); egg01 = loadImage("Egg01.png"); egg02 = loadImage("Egg02.png"); egg03 = loadImage("Egg03.png"); egg04 = loadImage("Egg04.png"); } void draw(){ background(255); float n = width / spacing; float a = 1; //floor noStroke(); fill(245); rect(0, 280, displayWidth, 540); //floor dot pattern for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { a *= -1; var x = i * spacing; var y = j * spacing; if(a > 0){ x = x + spacing / 2; } var d = diameter; fill(255); ellipse(x, y, d, d); } } //sun movement if(sunMovement <= 100){ sunMovement += 0.15; } if(v > 7){ noStroke(); fill(203 - sun_color, 64 + sun_color, 66 + sun_color * 1.5, sun_radiate_alpha); ellipse(1100 + sunMovement, 150 + sunMovement, sun_radiate, sun_radiate); } //noStroke(); //fill(203 - sun_color, 64 + sun_color, 66 + sun_color * 1.5, sun_radiate_alpha); //ellipse(1100 + sunMovement, 150 + sunMovement, sun_radiate, sun_radiate); noStroke(); fill(203 - sun_color, 64 + sun_color, 66 + sun_color * 1.5); ellipse(1100 + sunMovement, 150 + sunMovement, 120, 120); if(sun_radiate < 200) { sun_radiate += 2; } else { sun_radiate = 120; } if(sun_radiate_alpha > 0) { sun_radiate_alpha -= 6.375; } else { sun_radiate_alpha = 255; } //grass backward image(grass04, 371, 230, 575, 246); image(grass03, 695, 328, 627, 217); angle += 0.05; //egg position and rotation pushMatrix(); translate(displayWidth/2, displayHeight/2 + 100); noStroke(); fill(220); ellipse(0 + cos(angle) * 10, 0, 160, 30); scale(0.3); rotate(cos(angle) / 8 * tiltAmp); image(egg01, x - egg01.width/2, y - egg01.height); popMatrix(); //egg1.display(); //grass frount image(grass02, 946, 594, 252, 172); image(grass01, 390, 467, 348, 221); //arduino data loading while (myPort.available() > 0){ val = myPort.readStringUntil('\n'); // reads it and stores it in val; \n is the line break //try{ // //val = myPort.readString(); // stringData = split(val, ','); // //sensorVal = Integer.valueOf(val.trim()); // converts the text strin into a number //} //catch(Exception e){ //} } if (val != null) { stringData = split(val, ','); float[] values = float(stringData); v = values[0]; h = values[1]; t = values[2]; } //egg tilt value tiltAmp = 1 + v / 20; //sun color change sun_color = (h - 50) * 2; //loading bar accumulation if(v >= 30){ if(accum_v < 250){ accum_v = accum_v + v * 0.01; } else { accum_v = 250; } } //temperature bar float pos_x = - 180; float pos_y = 0; float sphere_d = 30; float rect_w = 20; float rect_h = 120; float thickness = 8; float sphere_d_in = 30 - thickness; float rect_w_in = 20 - thickness; float rect_h_in = 120 - thickness + 4; float sphere_d_out = 30 + thickness - 4; float rect_w_out = 20 + thickness - 4; float rect_h_out = 120 + thickness - 6; float sphere_red = 30 - 1.5 * thickness; float rect_w_red = 20 - 1.5 * thickness; float rect_h_red = 120 - 1.5 * thickness + 6; float dist = 120 - (t - 26) * 50; if(dist < 0) { dist = 0; } else if (dist > rect_h_red){ dist = rect_h_red; } pushMatrix(); translate(displayWidth/2, displayHeight/2); noStroke(); fill(255); ellipse(pos_x, pos_y, sphere_d_out, sphere_d_out); rect(pos_x - rect_w_out / 2, pos_y - rect_h_out, rect_w_out, rect_h_out, 10); fill(220); ellipse(pos_x, pos_y, sphere_d, sphere_d); rect(pos_x - rect_w / 2, pos_y - rect_h, rect_w, rect_h, 10); fill(255); ellipse(pos_x, pos_y, sphere_d_in, sphere_d_in); rect(pos_x - rect_w_in / 2, pos_y - rect_h_in, rect_w_in, rect_h_in, 10); fill(#cb4042); ellipse(pos_x, pos_y, sphere_red, sphere_red); rect(pos_x - rect_w_red / 2, pos_y - rect_h_red + dist, rect_w_red, rect_h_red - dist, 10); popMatrix(); //loading bar stroke(255); strokeWeight(8); fill(255); rect(displayWidth/2 - 130, displayHeight/2 + 140, 260, 40, 10); noStroke(); fill(#FFC408); rect(displayWidth/2 - 125, displayHeight/2 + 145, accum_v, 30, 7); stroke(220); strokeWeight(4); noFill(); rect(displayWidth/2 - 130, displayHeight/2 + 140, 260, 40, 10); //tiltAmp = 1 + v / 100; //egg1.wobble(); //print(displayWidth); //print(displayHeight); print(cos(angle) / 8 * tiltAmp); print(','); print(v); print(','); print(h); print(','); println(t); } class Egg { float x, y; // X-coordinate, y-coordinate float tilt; // Left and right angle offset float angle; // Used to define the tilt float scalar; // Height of the egg // Constructor Egg(float xpos, float ypos, float t, float s) { x = xpos; y = ypos; tilt = t; scalar = s / 100.0; } void wobble() { tilt = cos(angle) / 8 * tiltAmp; angle += 0.1; } void display() { noStroke(); fill(200); pushMatrix(); translate(x, y); rotate(tilt); scale(scalar); beginShape(); vertex(0, -100); bezierVertex(25, -100, 40, -65, 40, -40); bezierVertex(40, -15, 25, 0, 0, 0); bezierVertex(-25, 0, -40, -15, -40, -40); bezierVertex(-40, -65, -25, -100, 0, -100); endShape(); popMatrix(); } }