Navn:

Bouncy bouncy (Oh such a good time)

Gruppemedlemmer:

Sanijel Hadzikadunic

Simon Ryan Juul

Tobias Norman Kettelz

Kenneth Damkjær Nielsen

 

Illustration af wearable:

hophop

De røde prikker i billedet ovenover repræsenterer vores accelerometre.

Case:

Vores wearable tager udgangspunkt i gymnastik; nærmere betegnet springgymnastik. Tobias underviser i denne disciplin og fremsagde ideen om en mulighed for at få registreret, hvordan gymnastens positur under afsæt påvirker hele springet. Tanken var at kunne få målt vinklen mellem overkrop og underkrop i afsætningsøjeblikket. Herefter ville instruktøren kunne sammenholde disse data med sin egen viden og kunnen, for at forbedre elevens afsæt.

Anvendelsesmuligheder

En dynamisk monitorering af vinklen mellem lår og tyngdepunktet vil kunne bruges som et redskab for gymnaster og instruktører i træningssammenhænge. Produktet er målrettet eliteudøvere og disses instruktører, da det på dette niveau er meget små udsving i kropspositioner, gør en stor forskel på et springs kvalitet. Ved at kunne monitorere vinklen undervejs et spring, gøres det nemmere for instruktøren og gymnasten at se, i hvilken del af springet, at der skal rettes op. Monitoreringen vil også afsløre, om gymnasten evner at ændre kropspositioner hurtigt nok. Produktet vil kunne bruges af i mange forskellige gymnastikdiscipliner, da der i stort set dem alle fokuseres på forholdet mellem lårenes position og tyngdepunktet.

Produktet vil desuden kunne bruges i forbindelse med konkurrencer, hvor dommere vil kunne få hjælp til at give en mere ensartet og fair vurdering af en gymnasts præstation. Vha. monitorering af vinklen mellem lår og tyngdepunkt, vil man kunne fastsætte intervaller for en række bestemte positioner, der skal rammes på bestemte tidspunkter. Dette ville reducere menneskelige fejlvurderinger under konkurrencer, hvor tempoet er højt, og skellet mellem vinder og taber er meget smalt.

Lignende teknologi

En anden teknologi, der kan hjælpe sportsudøvere til bedre træning er den gratis app, Übersense (http://www.ubersense.com). Übersense er kort sagt en video capturing app, der tillader næranalyse af en bevægelse. Optagelser kan afspilles i 4 forskellige hastigheder, eller brugeren kan scrolle mellem frames på en bar nederst i billedet. Det er også muligt at tegne linjer, pile, cirkler, rektangler og vinkler som et ekstra lag på videoen. Derudover er det muligt at afspille to videoer samtidigt, så to bevægelser nemmere sammenlignes. Her kan der enten vælges en video fra ens eget arkiv, eller man kan finde en andre übersensebrugeres videoer online. Übersense er et rigtig godt redskab, der er nemt at bruge. Desværre udbydes det kun til iPhone og iPad.

Muligheden for at tegne vinkler i übersense er brugbar, men desværre er den tegnede vinkel statisk. Her kunne vores dynamiske monitorering af vinklen fungere ideelt i sammenspil med et program som übersense.

 

Hvad er vores design?:

Vi vil gerne måle vinklen mellem en gymnasts overkrop of underkrop i håb om at kunne hjælpe en instruktør med at forbedre træningen. Vi vil gøre dette ved at fastspænde to accelerometre på gymnastens krop; et på overkroppen og et på underkroppen (låret). Disse accelerometre skal kunne kommunikere med hinanden og tilbagegive data, som kan bruges af vores program til at udregne vinklen mellem dem. Dette skal herefter sættes op i en graf, som viser vinklen i forskellige tidsintervaller.

 

Hvordan er hardwaren sammensat?:

2014-05-05 12.39.29

Kode og beskrivelse

Vi har valgt at bruge 2 ADXLl345. Siden vi valgte at bruge 2 ADXL345 har vi valgt at bruge et SPI (Serial Peripheral Interface) system, til at opbygge vores struktur til POP2. Enhederne kommunikerer i master / slave mode, hvor master-enheden initierer data. Hver slave har tilladelse til at kommunikere med alle udvalgte kommunikations linjer linjer. Sommetider kaldes SPI en fire-wire seriel bus, i modsætning til tre-, to-og one-wire serielle busser. SPI er ofte omtalt som SSI (Synchronous Serial Interface) (Hvis vi kigger på vores fritzing kan vi se at vores opsætning følger denne struktur).

SDA (slave 1) -> SDA (slave 2) -> port 11
SDO (slave 1) -> SDO (slave 2) -> port 12
SCL (slave  1) -> SCL (slave 2) -> port 13
CS (slave 1) -> port 10
CS (slave 2) -> port 9

Arduino Accelerometre

 

Hvordan er opførelsen implementeret?:

I vores arduino koder behandler vi kun de rå data, det vil sige vi finder ud af hvad hver ADXL345 måler. Denne data bliver senere hen brugt i vores processing kode. Målet med arduino kode var at få det hele til at virke, få begge ADXL til at måle data og forberede denne data til at blive brugt i processing.

ARDUINO KODE

//Add the SPI library so we can communicate with the ADXL345 sensor
#include <SPI.h>

//Assign the Chip Select signal to pin 10.
int CS1=10;
int CS2=9;

//This is a list of some of the registers available on the ADXL345.
char POWER_CTL = 0x2D;	//Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32;	//X-Axis Data 0
char DATAX1 = 0x33;	//X-Axis Data 1
char DATAY0 = 0x34;	//Y-Axis Data 0
char DATAY1 = 0x35;	//Y-Axis Data 1
char DATAZ0 = 0x36;	//Z-Axis Data 0
char DATAZ1 = 0x37;	//Z-Axis Data 1

//This buffer will hold values read from the ADXL345 registers.
char values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;
int x1,y1,z1;

void setup(){ 
  //Initiate an SPI communication instance.
  SPI.begin();
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);

  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS1, OUTPUT);
  pinMode(CS2, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS1, HIGH);
  digitalWrite(CS2, HIGH);

  //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
  writeRegister(CS1, DATA_FORMAT, 0x01);
  writeRegister(CS2, DATA_FORMAT, 0x01);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(CS1, POWER_CTL, 0x08);  //Measurement mode 
  writeRegister(CS2, POWER_CTL, 0x08);  //Measurement mode  
}

void loop(){
  //Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
  //The results of the read operation will get stored to the values[] buffer.
  readRegister(CS1, DATAX0, 6, values);

  //The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
  //The X value is stored in values[0] and values[1].
  x = ((int)values[1]<<8)|(int)values[0];
  //The Y value is stored in values[2] and values[3].
  y = ((int)values[3]<<8)|(int)values[2];
  //The Z value is stored in values[4] and values[5].
  z = ((int)values[5]<<8)|(int)values[4];

  //Print the results to the terminal.
  /*
  Serial.println("Device 1:");
  Serial.print(x, DEC);
  Serial.print(',');
  Serial.print(y, DEC);
  Serial.print(',');
  Serial.println(z, DEC);      
  */
  delay(100);

  readRegister(CS2, DATAX0, 6, values);

  //The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
  //The X value is stored in values[0] and values[1].
  x1 = ((int)values[1]<<8)|(int)values[0];
  //The Y value is stored in values[2] and values[3].
  y1 = ((int)values[3]<<8)|(int)values[2];
  //The Z value is stored in values[4] and values[5].
  z1 = ((int)values[5]<<8)|(int)values[4];

  //Print the results to the terminal.
  Serial.print(x, DEC);
  Serial.print(',');
  Serial.print(y, DEC);
  Serial.print(',');
  Serial.print(z, DEC);
  Serial.print(',');
  Serial.print(x1, DEC);
  Serial.print(',');
  Serial.print(y1, DEC);
  Serial.print(',');
  Serial.print(z1, DEC);
Serial.print(',');
Serial.prinln(0); //Dummy value

delay(100); } //This function will write a value to a register on the ADXL345. //Parameters: // char registerAddress - The register to write a value to // char value - The value to be written to the specified register. void writeRegister(int CS, char registerAddress, char value){ //Set Chip Select pin low to signal the beginning of an SPI packet. digitalWrite(CS, LOW); //Transfer the register address over SPI. SPI.transfer(registerAddress); //Transfer the desired register value over SPI. SPI.transfer(value); //Set the Chip Select pin high to signal the end of an SPI packet. digitalWrite(CS, HIGH); } //This function will read a certain number of registers starting from a specified address and store their values in a buffer. //Parameters: // char registerAddress - The register addresse to start the read sequence from. // int numBytes - The number of registers that should be read. // char * values - A pointer to a buffer where the results of the operation should be stored. void readRegister(int CS, char registerAddress, int numBytes, char * values){ //Since we're performing a read operation, the most significant bit of the register address should be set. char address = 0x80 | registerAddress; //If we're doing a multi-byte read, bit 6 needs to be set as well. if(numBytes > 1)address = address | 0x40; //Set the Chip select pin low to start an SPI packet. digitalWrite(CS, LOW); //Transfer the starting register address that needs to be read. SPI.transfer(address); //Continue to read registers until we've read the number specified, storing the results to the input buffer. for(int i=0; i<numBytes; i++){ values[i] = SPI.transfer(0x00); } //Set the Chips Select pin high to end the SPI packet. digitalWrite(CS, HIGH); }

 

I vores processing kode har vi taget de værdier ADXL345 har givet os og sat dem ind i et array. Vores mål med opgaven er at finde vinklen mellem vektor a og vektor b. Dette kræver at værdierne er i int format, dog er det data vi har modtaget i string format. Så den anden opgave ligger i at forvandle strings til int. Dette blev gjort via integer.parseint();. Da vi nu har vores data i int forat, kan vi benytte PVector til at finde vinklen mellem vektor a og vektor b. PVector er en bibliotek i processing der arbejder med vektorer. Til sidste illustrerede vi denne vinklen på en bar graph i forhold til størrelsen på vinklen.

PROCESSING KODE

import processing.serial.*;
Serial myPort;
String sensorReading="";
PFont font;
float angle;

void setup() {
  size(700,700);
  myPort = new Serial(this, "COM7", 9600);
  myPort.bufferUntil('\n');
  font = createFont(PFont.list()[2],32);
  textFont(font);
}

void serialEvent (Serial myPort){
 sensorReading = myPort.readStringUntil('\n');

 String[] list = split(sensorReading, ',');

 /* if(sensorReading != null){
    sensorReading=trim(sensorReading);
  }*/

  float I1x = Integer.parseInt(list[0]);
  float I1y = Integer.parseInt(list[1]);
  float I1z = Integer.parseInt(list[2]);
  float I2x = Integer.parseInt(list[3]);
  float I2y = Integer.parseInt(list[4]);
  float I2z = Integer.parseInt(list[5]);

  PVector origen = new PVector(0,0,0);
  PVector a = new PVector(I1x,I1y,I1z);
  PVector b = new PVector(I2x,I2y,15);

  angle = PVector.angleBetween(a, b); 

  println(degrees(angle));

}

void draw() {
  //The serialEvent controls the display
  background(255);
  fill(#ff0000);
  rect(200,200,100,degrees(angle));
  //println(degrees(angle));
}

low deghigh deg

 

Kogt lidt ned kan kodens opførsel beskrives således:

Flowchart

 

Konklusion:

Vores wearable skulle gerne kunne afhjælpe en gymnastikinstruktør med træning af elever. De generelle principper bag dette er på plads og med en videre udvikling vil det kunne bruges efter hensigten. I dens nuværende format kan vores wearable kun bruges til at afmåle en vinkel imellem de to accelerometre, men er ikke blevet testet under de rette omstændigheder.

Video: https://www.youtube.com/watch?v=YxfW3pG75Ac

Leave a Reply