Plethandsken
Gruppemedlemmer: Stefan, Juri, Henning og Jakob
Vi ønsker at forbedre brugen af plethandsker i kampsport. Træner og elev skal kunne få en præcis beskrivelse af slagets antal, hårdhed og beskaffenhed. Målet er en plethandske der kan sende brugbare data til din computer eller telefon. Umiddelbart “var” der ikke lignende produkter på markedet så derfor anså vi det som en spændende udfordring!
- Grøn ring: Arduino
- Gul ring: Plethandske
- Rød ring: FSR sensor
- Brun ring: Boksehandske
Idegrundlag
Platformen er Arduino hvilket er en microcontroller. Vi har brugt Processing til at styring og aflæsning af sensor input. Til plethandsken har vi valgt at teste en FSR sensor og et accelerometer. VI har taget valget på baggrund af newtons anden lov som er følgende:
F = M · A
Kræft(N) = Masse(kg) · Acceleration(m/s)
Ideen er at når vi kender kraften og accelerationen af et slag kan vi sige noget om slagets beskaffenhed. Gennem fysisk test af en prototype vil vi afsløre om vore sensorer kan give et brugbart resultat. Der er flere faktorer som spiller ind bla:
- Plethandsken er ikke statisk
- Hvordan skal vore sensorer opfatte et korrekt slag?
- Omsætte den fysiske data til håndgribelig brugerfeedback
- Hvilken masse er det vi får regnet ud ?
- Placering af sensorer
Test af sensor
For at tillade flere brugere ville den optimale løsning være at placere sensorer i selve plethandsken.
Bruger scenariet er at træneren holder den grå “handske” og at forskellige elever kan få feedback på deres slag.
Vores tanker omkring brug af newtons lov kræver meget præcise målinger af alle sensorer. Vi har været begrænset af vores FSR sensor da den kun kan registrere 100 newton. Dvs. at alle test-slag gav et resultat nær max output.
Vi overvejede også at placere accelerometeret i boksehandsken også i processing angive brugerens vægt, men dette gav ikke mening for vores brugerscenarie.
Den brune handske er i bevægelse hele tiden så det er svært at få et korrekt sensor output der er brugbart. Derfor valgte vi at fokusere på FSR sensoren alene. Vores opgave var således at omsætte max værdierne til noget visuelt forståeligt for brugeren.
Opsætning af hardware
På billedet her ses vores hardware opsætning. På arduinoen har vi monteret et bluetooth modul, der fungerer som en server vores pc ( klienten ) opretter forbindelse til.
På denne måde kan vi trådløst sende data til både pc og telefon. Bluetooth modulet opfører sig som en slags seriel port uden ledning.
FSR sensoren sender en værdi fra 0 -1024 og det er så “processings” opgave at oversætte det visuelt så en bruger kan forstå dataen.
Sammensætning af hardware
Kommunikationsmodel
Teknisk tegning
Kode (Arduino)
#include <SoftwareSerial.h>
int bluetoothTx = 2; // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3; // RX-I pin of bluetooth mate, Arduino D3
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup()
{
Serial.begin(9600); // Begin the serial monitor at 9600bps
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps
bluetooth.print("$"); // Print three times individually
bluetooth.print("$");
bluetooth.print("$"); // Enter command mode
delay(1); // Short delay, wait for the Mate to send back CMD
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably
bluetooth.begin(9600); // Start bluetooth serial at 9600
}
void loop()
{
int sensorValue = analogRead(A2); //stores the output from the sensor
Serial.println(sensorValue); //prints it to the Serial Moniter for testing purposes
delay(70); //this is the fastest we can send data without making trouble for processing on the other end
//too much data will make processing get behind and the draw events will be delayed making it look iffy
bluetooth.print(sensorValue); //prints the data via bluetooth
bluetooth.print("\n"); //a marker for the other end to know that no more data is comming.
}
Kode (Processing)
import processing.serial.*;
Serial myPort;
float val;
float max;
String strVal;
int counter;
int arrayLength = 5000;
int xStart = 20;
int yStart = 580;
color yellow = #FFCC00;
color red = #FF0000;
color blue = #00AAEE;
float[] number = new float[arrayLength];
void setup()
{
size(1200, 900); //screen size
frameRate(60); //frame rate, how many times pr second the screen is redrawn
String portName = Serial.list()[0]; // select the port you want to use, 0 is in our case the usb and 1 is the bluetooth, given that thoose are the only 2 devices connected
myPort = new Serial(this, portName, 9600); //defines the port for later usage
printArray(Serial.list()); //prints all COM ports for troubleshooting, use this to find out which port you should use.
background(255); //background is default white!
}
void draw()
{
if ( myPort.available() > 0) { // It will only draw if data is available
strVal = myPort.readStringUntil('\n'); //stores the value in a string
if (strVal != null) //alot of nulls will be send when there is no data or if there is some kind of noise, if this is the case we do not want to execute our code
{
val = Float.parseFloat(strVal); //we store the value as a float, so we can apply math and draw figures with it
if (val > 50) //values below 50 will not be read, as due to the mechanical setup the sensor is sometimes pressed slightly which gives small useless outputs.
{
while(val != 0.0) //we will run a while loop until we get a 0.0 value, this is because when hitting the sensor it will generate more than one value,
//and we want to wait until we have all the values stored before we start drawing. otherwise the result will not be intuitive to the average user.
{
strVal = myPort.readStringUntil('\n'); //we need to check new values in the while loop too, as it does not leave this loop
if (strVal != null) { //again check for nulls
number[counter] = val; //we start storing our values in an array, we do this before overwring the old value with the new, so we get the initial value in the array aswell.
val = parseFloat(strVal);
println("this is a float value: "+val); //trouble shooting, gives output
counter++; //incrementer for the array
}
}
println("-----: "+counter+" :-----"); //shows how many entries that was in the array
max = max(number); //we take the largest value in the array, which is respresents hard the person hit
for(int i = 0; i < (arrayLength-1); i++) //dumb everything in the array so it can be used again
{
number[i] = 0;
}
if (max > 800) { //different color for different sprectrum og values
fill(red);
} else if ((max < 800) && (max > 650)) {
fill(yellow);
} else {
fill(blue);
}
rect(xStart, yStart-(max/2), 55, (max/2)); //uses values to draw a rectangle representing the value
xStart = xStart+60; // move xStart so the new rectangle will be drawn next to the old one with a 5 pixel width seperating them
}
fill(255);
stroke(255);
rect(20,580,200,200); //this draw a box that deletes the old textvalue so a new one can be inserted
textSize(40);
String strmax = ""+max; //the value to be written coverted back to a string
stroke(#BEBEBE); //fancy color
fill(#BEBEBE);
line(20,600,1100,600); //a line for visual purposes
text(strmax,20,640); //this gives the output as a text below the bars
if( xStart > 1100) { //once a certain (18) amount of bars have been drawn, we want to reset the screen to make room for more, we do this by redrawing it white and resetting xStart
xStart = 20;
background(255);
}
counter = 0; //reset the counter so once we get another value it will fill the array up from the start
}
}
}
Alternativ udgave
Vi har sideløbende med den funktionelle prototype arbejdet på en forbedret visualisering i processing. Ideen var at der også skulle være lidt interaktivitet på skærmen, så man kunne interagere med sine resultater bagefter. Koden kom dog aldrig til at fungere helt i praksis med de fysiske slag. Her ses koden i test-fasen samt en videopræsentation af koden.
int numberOfColumns = 14; // antal søjler int columnWidth = 40; // søjlebredde int xStart = 75; int yStart = 500; PFont f; // klargør font float maxVal = random(0, 400); // tilfældig TEMP tal PShape[] rectangles = new PShape[numberOfColumns]; // array til søjler int[] xPos = new int[numberOfColumns]; // array til xPos af hver kolonne float[] yPos = new float[numberOfColumns]; // array til højden ell værdien af hver kolonne String powerPoint = ""; // klargør streng til point angivelse void setup() { f = createFont("Arial", 40, true); // lav font med max font str 40 size(800, 600, P2D); background(255, 255, 255); fill(#BEBEBE); stroke(#BEBEBE); line(xStart, yStart+25, 800-xStart, yStart+25); // linje til adskillelse af søjler og text textFont(f, 18); text("Power", xStart, yStart+55); noStroke(); // ingen ramme omkring søjler (kun fill) for (int i = 0; i < rectangles.length; i++) { rectangles[i] = createShape(RECT, xStart, yStart-maxVal, columnWidth, maxVal); shape(rectangles[i]); // tegn søjle xPos[i] = xStart; // gem værdien af søjlens x-position yPos[i] = maxVal; // gem værdien af søjlens y-værdi / point maxVal = random(0, 500); // nyt TEMP random tal xStart = xStart + columnWidth+5; // næste søjle har en afstand på 5px // print(i +".\t" + "x: " + xPos[i] + "\t" + "y: " + yPos[i] + "\n"); } } void draw() { // *************************************** // hvid kasse til at skjule text-point når man hover over ny søjle fill(255, 255, 255); rect(xPos[0]+65, yStart+35, 300, 50); fill(#BEBEBE); // *************************************** for (int i = 0; i < rectangles.length; i++) { shape(rectangles[i]); // hvis man hover over en søjle, ændre farve og angiv point i text if ((mouseX > xPos[i]) && (mouseX < xPos[i]+columnWidth) && (mouseY < yStart ) && (mouseY > yStart-yPos[i]) ) { rectangles[i].setFill(color(#2FC944)); powerPoint = str(yPos[i]); textFont(f, 40); fill(0); text(powerPoint, xPos[0]+65, yStart+70); } else { // når man "forlader" en søjle så gå tilbage til standard søjlefarve rectangles[i].setFill(color(#BEBEBE)); } } }
Video af fungerende prototype
Konklusion
Som det ses ud fra videoen af den fungerende prototype (ikke den alternative), så er det lidt tilfældigt hvor godt resultatet er. FSR-sensoren er desværre ikke præcis nok til at give et troværdigt resultat. Hvis vi skulle lave en ny prototype, så ville det kræve test af en række andre type sensorer. Idéen er der, men i praksis fungerer idéen ikke helt endnu..