Incontinuare la articolul precedent mi-am pus intrebarea :
Cum se poate face cel mai simplu gamepad cu Arduino ?
Să aiba un grup de 5 butoane , cu următorul rol :
Cum se poate face cel mai simplu gamepad cu Arduino ?
Să aiba un grup de 5 butoane , cu următorul rol :
- dacă aps pe 4 din ele, să deplaseze intr-o fereastra de pe PC o figură geometrică, (un pătrat) pe patru direcţii: sus; jos; dreapta; stânga;
- al cincilea buton, să fie "fire" - când îl apăs, să se schimbe culoarea pătratului;
În primul rând, trebuie să construim gamepad-ul
nostru pe breadboard. Vom folosi 4 butoane pentru direcţii (dreapta, sus, stânga, jos), și un altul
pentru foc.
O
să le conectãm la pinii Arduino și masă în
mod direct, fără nici o rezistenţã pullup sau pulldawn: vom activa rezistenţe pull-up interne din cadrul programului.Folosind
rezitorii pullup interni, circuitul va fi mult mai simplu. El va arãta
astfel :
http://www.varesano.net/blog/fabio/serial-communication-arduino-and-processing-simple-examples-and-arduino-based-gamepad-int prezentat în paragraful " Interfacing Arduino with a program running on a PC: Arduino and Processing to implement a simple gamepad and videogame"
Şi aici a fost
surpriza: la compilare, a apãrut eroarea şi confuzia!
Am fost nevoit sã reiau la rând funcţiile din Arduino IDE, şi totul despre
tipurile de date BYTE ! ca sã pricep scriptul. A trebuit sã inlocuiesc
ultima instrutiune, dar … macar am priceput “ce şi cum face“ programul.
Am tradus comentariile , am corectat
ultima instrucţiune şi scriptul meu este astfel :
-------------------------------------------------------------------------------------------------------
/** game1
* Utilizeaza rezistoarele interne pullups pentru a citi
starea
* celor 5 butoane.
* Apoi , declara
variabila "unsigned int state" care este de fapt
* echivalenta cu
tipul Byte. Prin operatii pe bit, (bitwise)
* incarca succesiv
valorile citite de pe pini pe locurile 5; 4; 3; 2; 1 din variabila state;
* variabila state ocupa 4 digiti; ea este expediata serial
*/
#define IN1 2 // fire
#define IN2 3 // right
#define IN3 4 // up
#define IN4 5 // left
#define IN5 6 // down
int state1 = HIGH;
int state2 = HIGH;
int state3 = HIGH;
int state4 = HIGH;
int state5 = HIGH;
void setup() {
Serial.begin(9600);
pinMode(IN1, INPUT);
digitalWrite(IN1, HIGH); // enable pullup
resitor
pinMode(IN2, INPUT);
digitalWrite(IN2, HIGH); // enable pullup
resitor
pinMode(IN3, INPUT);
digitalWrite(IN3, HIGH); // enable pullup
resitor
pinMode(IN4, INPUT);
digitalWrite(IN4, HIGH); // enable pullup
resitor
pinMode(IN5, INPUT);
digitalWrite(IN5, HIGH); // enable pullup
resitor
}
void loop() {
delay(10); // debounces switches
int val1 = digitalRead(IN1);
int val2 = digitalRead(IN2);
int val3 = digitalRead(IN3);
int val4 = digitalRead(IN4);
int val5 = digitalRead(IN5);
// verific daca s-a facut vre-o modificare in "state"
if(state1 != val1 || state2 != val2 || state3
!= val3 || state4 != val4 || state5 != val5) {
state1 = val1;
state2 = val2;
state3 = val3;
state4 = val4;
state5 = val5;
/*
acum, creem un cuvint pe 8 biti (1
byte) ai carui 5 biti din dreapta reprezinta -
dela dreapta la stinga- starea butoanelor
fire, right, up, left, down :
adica 0 daca e apasat, 1 daca nu e apasat
not pressed
Ceilalti
biti nu sint utilizati.
*/
unsigned int state = (val5 << 4) |
(val4 << 3) | (val3 << 2) | (val2 << 1) | val1 ;
Serial.write(state);
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------------
Programul de mai sus este destul de
simplu. Am văzut deja totul despre logica de comunicare aici.
Singurul lucru nou
este faptul că am încercat să limitez cantitatea de date care călătoresc pe
firul de serie. De aceea, am setat variabila "state" cu
ajutorul unor operații la nivel de bit. Se construiește un cuvânt
de 8 biți ("state"), a cărui 5 biți din dreapta sunt setaţi la 1 în cazul în care
butonul asociat nu este apăsat, sau la 0, dacă este apăsat.
Fiecare bit este inserat pe un loc specificat in byte. Ceilalţi 3 biti
rãmin neutilizaţi. astfel , se va expedia serial un singur byte.
Jocul video din Processing
Mai
sus, am creat un program care este capabil sã trimitã datele noastre de stare trimise de gamepad pe firul serial la PC-ului.
Acum avem nevoie de ceva pe partea de PC, care
va citi aceste date și care va reacționa conform cu valorile situate în variabila “state”.Vom
crea un program simplu care deplaseazã un pătrat pe o fereastră.
Folosind
butoanele de pe gamepad vom deplasa caseta de pe ecran.
Când
apăsați butonul foc, caseta se va schimba culoarea casetei.
Scriptul l-am copiat de la adresa specificată in link-ul de mai sus.
Atentie : şi partea asta de program am modificat-o pentru cã instrucţiunea din scriptul
original care cautã portul serial al lui
Arduino, pentru ca pe PC-ul meu nu a funcţionat.
Linia urmãtoare
myPort = new
Serial(this, "/dev/ttyUSB5", 9600);
a
trebuit sã o inlocuiesc cu setul de instrucţiuni:
String portName =
Serial.list()[portIndex];
println(" Connecting to ->
" + Serial.list()[portIndex]);
myPort = new Serial(this, portName,
9600)
Scriptul corectat, editat in Processing 2.0 şi care
merge , este acesta :
-------------------------------------------------------------------------------------------------------------
//
game1 = Processing
import processing.serial.*;
Serial myPort; //
Create object from Serial class
short portIndex = 1; // select the com port, 0 is the first
port
int state = 31;
int fire = 1;
int right = 1;
int up = 1;
int left = 1;
int down = 1;
int x = 275;
int y = 275;
int c = 0;
void setup()
{
size(600, 600);
String portName = Serial.list()[portIndex];
println(" Connecting to -> " +
Serial.list()[portIndex]);
myPort = new Serial(this, portName, 9600);
}
void draw() {
if(myPort.available() > 0) {
state =
myPort.read();
println(state);
println(binary(state)); //sa
vedem efectul
println(state);
fire = state &
1;
right = (state
& 2) >> 1;
up = (state &
4) >> 2;
left = (state
& 8) >> 3;
down = (state
& 16) >> 4;
print(fire);
print(right);
print(up);
print(left);
println(down);
}
c = (fire == 0) ?
250 : 0;
if(right == 0
&& left == 1) {
x = x + 2;
}
if(up == 0
&& down == 1) {
y = y - 2;
}
if(left == 0
&& right == 1) {
x = x - 2;
}
if(down == 0
&& up == 1) {
y = y + 2;
}
background(255, 255,
150);
fill(c);
rect(x, y, 50, 50);
}
Intrebarea retoricã ar fi : de ce unii mai publicã , daca scripurile lor nu sint corectate, şi funcţionale !
Poate mai sânt şi începatori , chiar şi copii de 14 – 18 ani, care vor sã lucreze , şi sã reuşeascã !
Niciun comentariu:
Trimiteți un comentariu