Projekt Arduino Painstation

Verze z 23. 12. 2015, 16:25, kterou vytvořil Jakub.Fiala (diskuse | příspěvky) (→‎Videodokumentace)
(rozdíl) ← Starší verze | zobrazit aktuální verzi (rozdíl) | Novější verze → (rozdíl)

Členové projektu

Jakub Sedláček, Studia nových médií, e-mail: jakubsed@email.cz

David Vávra, Studia nových médií, e-mail: vavra.dav@gmail.com

Karel Nejedlý, Studia nových médií, e-mail: karel.nejedly@email.cz

Motivace vzniku projektu a jeho význam

Projekt Arduino Painstation vychází z původního díla umělecké skupiny "/////////fur//// art entertainment interfaces" s názvem Painstation. Originální projekt je založen na arkádové hře Pong, která je však obohacena o prvek zpětné vazby ve formě mírné bolesti působené hráčům . K tomuto účelu slouží tzv. PEU (Pain execution unit), na které má hráč položenu ruku dlaní dolů a která využívá elektrických šoků, tepelných impulzů a miniaturního mechanického "biče". Bolest je použita jako trest za hráčův neúspěch a její intenzita a podoba se mění v závislosti na postupu ve hře.

Smyslem zařízení je vnést do triviální interakce člověka a počítače, která se odehrává především v rovině symbolů, prvek reality. V digitálním světě jsou naše činy často zcela oproštěny od přímé, skutečné a hmatatelné zpětné vazby, která nás jinak motivuje k přemýšlení o našich činech a jejich důsledcích. Projekt Painstation tak tomuto pohodlnému způsobu komunikace nastavuje zrcadlo k čemuž využívá populárního a přístupného formátu arkádové hry Pong, kde je strojem zprostředkovaná interakce mezi hráči konfrontována s realitou tímto, sice netradičním, ale symbolickým způsobem. Naším cílem je tento projekt napodobit a s využitím možností open hardware i zpřístupnit dalším zájemcům.

V naší verzi tohoto uměleckého herního zařízení budeme rovněž vycházet z arkádové hry Pong a využívat bolest jako formu zpětné vazby za hráčův neúspěch. Zásadní rozdíl bude představovat použitý hardware - tím je v našem případu Arduino Uno s přidaným shieldem Tinker Kit. Samotná hra bude ovládána prostřednictvím dvou analogových slide faderů a bude probíhat na notebooku Lenovo Y500.

Zpětná vazba bude tvořena elektrošoky, které vytvoří připojené zařízení na elektrickou stimulaci svalstva a čtyři elektrody (2 pro každého hráče), které budou umístěny na hráčově předloktí. Součástí zpětné vazby jsou také svítící LED diody, které indikují, který hráč právě dostal šok / gól.

Použitý hardware a software

Vývojová deska Arduino UNO

Shield TinkerKit Sensor Shield V.2

Tinker Kit relé

Baterie 2200-3S (11,1V)

Arduino TinkerKit T000150 lineární tahový potenciometr

6x 2Pin Propojovací Kabel F-F 30cm RepRap Arduino

Elektronický svalový stimulátor HT-329L

1x Žlutá LED Dioda

1x Zelená LED Dioda

Programovací jazyk Processing

Arduino software IDE

Odkazy na knihovnu arduina a vlastní zdrojový kód

Arduino kód

Náš finální kód využíval hlavně ukázkové projekty https://www.arduino.cc/en/Tutorial/AnalogReadSerial a https://www.arduino.cc/en/Tutorial/SwitchCase. Níže uvedený kód je verze z průběhu vývoje a nejde tedy o kód finální s funkcionalitou plně odpovídající prezentačnímu videu. Ten byly bohužel ztracen v důsledku selhání HDD a systému záloh.

Upozornění! Vzhledem k omezení syntaxe wikisofia kopírujte prosím zdrojový kód přímo z editace zdroje stránky, nikoliv z podoby, do jaké je intepretována při zobrazení na stránce. Přislušný úsek je v souladu se syntaxí české wikipedie umístěn mezi značkou <tt> a </tt>.

int led = 3; int led2 = 5; int kejs = 0; int brightness = 0; int sensorMin; int sensorMax; const long interval = 1000; unsigned long previousMillis = 0;

void setup() {

 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
 pinMode(led,OUTPUT);

} void loop() {

 if (Serial.available()) {
   // read the most recent byte (which will be from 0 to 255):
   kejs = Serial.read();
  
   switch (kejs) {
   case 0:    // 
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis >= interval) {
     
     brightness = 0;
     analogWrite(led, brightness);
     analogWrite(led2, brightness);
 }
     break;
   case 1:    // 
     brightness = 255;
     analogWrite(led, brightness);
     break;
   case 2:    // 
     brightness = 255;
     analogWrite(led2, brightness);
     break;
   }
 }
   int sensorValue = analogRead(A0);
 int sensorValue2 = analogRead(A1);
 Serial.print(sensorValue);
 Serial.print(",");
 Serial.println(sensorValue2);
 delay(1);

}

Processing kód

Náš finální kód byl přizpůsobenou verzí kódu volně dostupného ze stránky http://teachmetomake.com/wordpress/arduino-and-processing-pong-example, který jsme obohatili například o postupné zrychlování a přizpůsobili jej pro fullscreen zobrazení. Následuje ukázka podoby kódu z průběhu vývoje (zatím bez zrychlování):

Upozornění! Vzhledem k omezení syntaxe wikisofia kopírujte prosím zdrojový kód přímo z editace zdroje stránky, nikoliv z podoby, do jaké je intepretována při zobrazení na stránce. Přislušný úsek je v souladu se syntaxí české wikipedie umístěn mezi značkou <tt> a </tt>.

import processing.serial.*; // import the Serial library import java.awt.Rectangle; // import Java's Rectangle class

Serial myPort; // The serial port

Rectangle leftPaddle, rightPaddle; // Rectangles for the paddles

int paddleHeight = 65; // vertical dimension of the paddles int paddleWidth = 10; // horizontal dimension of the paddles

int ballSize = 10; // the size of the ball int xDirection = 3; // the ball's horizontal direction. left is –2, right is 2. int yDirection = 3; // the ball's vertical direction. up is –2, down is 2. int xPos, yPos; // the ball's horizontal and vertical positions

int leftScore = 0; // score for left player int rightScore = 0; // score for right player

int fontSize = 30; // size of the fonts on the screen

void setup() {

 size(1280, 720);       // set the size of the applet window
 // List all the available serial ports
 println(Serial.list());
 // Open whatever port is the one you're using.
 myPort = new Serial(this, Serial.list()[0], 9600);
 // don't generate a serialEvent() unless you get a newline character:
 myPort.bufferUntil('\n');

 // initialize the paddles:
 leftPaddle = new Rectangle(50, height/2, paddleWidth, paddleHeight);
 rightPaddle = new Rectangle(width-50, height/2, paddleWidth, paddleHeight);

 noStroke(); // no borders on drawn shapes
 fill(255);  // drawn shapes are white
 resetBall();
 // create a font with the third font available to the system:
 PFont myFont = createFont(PFont.list()[2], fontSize);
 textFont(myFont);
 

} void draw() {

 // clear the screen:
 background(0);
 myPort.write(0);
 
 // draw the paddles:
 rect(leftPaddle.x, leftPaddle.y, leftPaddle.width, leftPaddle.height);
 rect(rightPaddle.x, rightPaddle.y, rightPaddle.width, rightPaddle.height);
 // calculate the ball's position and draw it
 animateBall();
 // print the scores
 text(leftScore, fontSize, fontSize);
 text(rightScore, width-fontSize, fontSize);

} // serialEvent method is run automatically whenever the buffer // reaches the byte value set by bufferUntil(): void serialEvent(Serial thisPort) {

 // read the serial buffer:
 String inputString = thisPort.readStringUntil('\n');
 if (inputString != null)
 {
   // trim the carrige return and linefeed from the input string:
   inputString = trim(inputString);
   // split the input string at the commas
   // and convert the sections into integers:
   int sensors[] = int(split(inputString, ','));
   // if we have received all the sensor values, use them:
   if (sensors.length == 2) {
     // scale the sliders' results to the paddles' range:
     leftPaddle.y = int(map(sensors[0], 0, 903, 0, height - leftPaddle.height));
     rightPaddle.y = int(map(sensors[1], 0, 895, 0, height - rightPaddle.height));
   }
 }

} void animateBall() {

 if (leftPaddle.contains(xPos, yPos) ||    // if the ball pos is inside the left paddle
 rightPaddle.contains(xPos, yPos)) {       // or the ball pos is inside the right paddle
   xDirection = -xDirection;               // reverse the ball's X direction
 }
 // if the ball goes off the screen left:
 if (xPos < 0) 
 {     
      rightScore++;
//Serial port;  
//port = new Serial(this, Serial.list()[0], 9600);

myPort.write(1);

myPort.write(0);

   resetBall();   
 }   // if the ball goes off the screen right:   
      
 if (xPos > width) 
 {
   leftScore++;
   myPort.write(2);
 
   myPort.write(0);
   resetBall();
 }
   if (leftScore >= 10) 
 {
   exit();
  }
     if (rightScore >= 10) 
 {
   exit();
  }
 // stop the ball going off the top or the bottom of the screen:
 if ((yPos <= 0) || (yPos >=height)) {
   // reverse the y direction of the ball:
   yDirection = -yDirection;
 }
 // update the ball position:
 xPos = xPos + xDirection;
 yPos = yPos + yDirection;
 // Draw the ball:
 rect(xPos, yPos, ballSize, ballSize);

} void resetBall() {

 // initialize the ball in the center of the screen:
 xPos = width/2;
 yPos = height/2;
}

Popis vývoje a konečné verze vlastního produktu

Příprava projektu a tvorba konceptu

Konečná podoba ovládacího pultu Arduino Painstation

Náš projekt do značné míry vychází z projektu Painstation umělecké skupiny "/////////fur//// art entertainment interfaces" a jeho cílem je převést základní myšlenku a koncepci tohoto díla do hardwarově odlišné verze využívající platformu Arduino. Základním požadavkem při přípravě konceptu Arduino Painstation tedy bylo jeho přizpůsobení možnostem platformy Arduino, jak po hardwarové, tak i softwarové stránce. S ohledem k časovým i technickým možnostem bylo rovněž třeba přistoupit ke zjednodušení celého herního systému a tvorbě prozatímního designu celého zařízení, který bude řešen na základě dostupných materiálů.

S ohledem k předloze zachováváme ústřední roli arkádové hry Pong. PEU (Pain execution unit) originálního Painstation nahrazujeme zařízením pro elektronickou stimulaci svalstva využívající 4 elektrod. Monitor a hardware potřebný ke hře budeme nahrazovat prostřednictvím laptopu. Ovládací prvky Arduino Painstation budou tvořeny párem lineárních tahových potenciometrů, které plnohodnotně nahrazují ovládací rozhraní originálního přístroje. Myšlenka, principy a základní koncept Painstation tak zůstávají zachovány, ale jsou převedeny do snáze proveditelné a dostupné podoby s ohledem k myšlenkám Open hardware.

Implementace

a) Stažení Arduino IDE a stažení programovacího jazyka Processing
Prvním našim krokem je stažení a seznámení se s příslušným programovacím prostředím a jazykem. Na tomto základě rozdělujeme práci a úkoly v rámci týmu. V této přípravné fázi rovněž kompletujeme potřebné vybavení.

b) Zapojení shieldu Tinker Kit do Arduino UNO
První zapojení shieldu, kontrola jeho funkčnosti prostřednictvím jednoduchých příkazů.

c) Zapojení dvou LED diod a test jejich funkčnosti

d) Stažení Processing kódu hry Pong
V této fázi připravujeme, kontrolujeme a následně upravujeme kód pro arkádovou hru Pong.

e) Úprava Processing kódu hry Pong ( zapojení potenciometrů a propojení s Pong) přizpůsobení LED diod

f) Úprava rozsahu potenciometrů pro pozicování pálek hry Pong

g) Připojení přístroje pro elektronickou stimulaci svalstva přes relé 2x k shieldu Tinker Kit

h) Test funkčnosti
Ve zkušební fázi provádíme test funkčnosti celého zařízení, včetně zkoušek různých stupňů elektrické stimulace a jejich přizpůsobení hře.

i) Aktualizace (přizpůsobení viz kód)
Po závěrečné aktualizaci kódu doplňujeme nové funkce a opravujeme zpozorované chyby.

j) Test funkčnosti
V rámci závěrečného testu funkčnosti je projekt Arduino Painstation vyzkoušen na různých úrovních intenzity a bez zpozorování chyb, které by měli výraznější vliv na hru.

Evaulace

Projekt je ke dni 30.6.2015 hotov a je plně funkční dle vytyčeného cíle. Základ tvoří arkádová hra Pong a hráči jsou za chyby trestáni prostřednictvím čtyř elektrod. Síla a úroveň výboje se určuje manuálním nastavením zařízení na elektronickou stimulaci svalstva. Hra je, dle našeho názoru, skvěle fungujícím konceptem společenské počítačové hry a zaslouží si budoucí široce použitelné zpracování.

Videodokumentace

https://youtu.be/FT19-VXUGNc