Lightgun wifi Samco modificata
Inviato: 06/11/2020, 11:24
Salve,
volevo condividere con voi, i risultati ottenuti modificando il codice del progetto Samco.
Per il momento mi sono dedicato alla versione con 2 led perché comunque funziona molto bene.
La prima modifica che ho apportato è stata al sistema di calibrazione.
L'originale prevede diverse fasi, ma non sempre si riesce a capire la fase corrente.
Inoltre prevede di acquisire la posizione di punti determinati per rapportare i dati rilevati dalla camera, alla risoluzione dello schermo/posizione sensori.
Questo sarebbe ottimo, se non fosse per il fatto, che se non si è estremamente precisi, il puntatore impazzisce. In sostanza per riuscire a calibrare occorrono diversi tentativi, in cui bisogna riattraversare le varie fasi di funzionamento.
Per questo motivo ho optato per una soluzione diversa.
Ho registrato i dati di una calibrazione ottimale, che permette di far funzionare la pistola da subito. Successivamente (se necessaio) si possono scorrere dei preset che permettono di adattare il movimento alla risoluzione.
Inoltre mi avanzavano delle schede radio nRF24L01 da un progetto precedente (costano comunque pochi euro) perciò ho provato ad implementare la trasmissione/ricezione nel codice della pistola.
Ovviamente per questo sono serviti due arduino, uno in trasmissione (sulla pistola) che si occupa dell'acquisizione dei dati della camera, e uno in ricezione (collegato al device arcade) che gestisce la ricezione e l'emulazione mouse.
qui trovate come collegare la scheda nrf24l01 (il collegamento è lo stesso per RX e TX)
http://www.meccanicaeautomazione.it/com ... -nrf24l01/
qui come collegare la camera
https://create.arduino.cc/projecthub/sa ... use-05d110
Buon divertimento!
Codice modulo TX (pistola)
Codice modulo RX
volevo condividere con voi, i risultati ottenuti modificando il codice del progetto Samco.
Per il momento mi sono dedicato alla versione con 2 led perché comunque funziona molto bene.
La prima modifica che ho apportato è stata al sistema di calibrazione.
L'originale prevede diverse fasi, ma non sempre si riesce a capire la fase corrente.
Inoltre prevede di acquisire la posizione di punti determinati per rapportare i dati rilevati dalla camera, alla risoluzione dello schermo/posizione sensori.
Questo sarebbe ottimo, se non fosse per il fatto, che se non si è estremamente precisi, il puntatore impazzisce. In sostanza per riuscire a calibrare occorrono diversi tentativi, in cui bisogna riattraversare le varie fasi di funzionamento.
Per questo motivo ho optato per una soluzione diversa.
Ho registrato i dati di una calibrazione ottimale, che permette di far funzionare la pistola da subito. Successivamente (se necessaio) si possono scorrere dei preset che permettono di adattare il movimento alla risoluzione.
Inoltre mi avanzavano delle schede radio nRF24L01 da un progetto precedente (costano comunque pochi euro) perciò ho provato ad implementare la trasmissione/ricezione nel codice della pistola.
Ovviamente per questo sono serviti due arduino, uno in trasmissione (sulla pistola) che si occupa dell'acquisizione dei dati della camera, e uno in ricezione (collegato al device arcade) che gestisce la ricezione e l'emulazione mouse.
qui trovate come collegare la scheda nrf24l01 (il collegamento è lo stesso per RX e TX)
http://www.meccanicaeautomazione.it/com ... -nrf24l01/
qui come collegare la camera
https://create.arduino.cc/projecthub/sa ... use-05d110
Buon divertimento!
Codice modulo TX (pistola)
Codice: Seleziona tutto
int positionX[4]; // RAW Sensor Values
int positionY[4];
int oneY = 0; // Re-mapped so left sensor is always read first
int oneX = 0;
int twoY = 0;
int twoX = 0;
int finalX = 0; // Values after tilt correction
int finalY = 0;
int xLeft = 0; // Stored calibration points
int yTop = 0;
int xRight = 0;
int yBottom = 0;
int MoveXAxis = 0; // Unconstrained mouse postion
int MoveYAxis = 0;
int conMoveXAxis = 0; // Constrained mouse postion
int conMoveYAxis = 0;
int count = 4; // Set intial count
int _tigger = 7; // Label Pin to buttons
int _up = 11;
//int _down = 9;
//int _left = 10;
int _right = 12;
int _A = A1;
int _B = A0;
int _start = A2;
int _select = A3;
int _reload = 8;
int _pedal = 5;
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;
int buttonState7 = 0;
int buttonState8 = 0;
int buttonState9 = 0;
int buttonState10 = 0;
int oldbuttonState7 = 0;
int oldbuttonState8 = 0;
#include <DFRobotIRPosition.h>
DFRobotIRPosition myDFRobotIRPosition;
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#define MIRF_PAYLOAD 32
byte rxData[MIRF_PAYLOAD + 1];
byte txData[MIRF_PAYLOAD + 1];
char msg[50];
int msgIndex = 0;
String stringa;
int res_x = 1920;
int res_y = 1080;
int ritardo = 10;
void setup() {
memset(rxData, 0, sizeof(rxData));
memset(txData, 0, sizeof(txData));
Serial.begin(9600);
Mirf.cePin = 9;
Mirf.csnPin = 10;
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.setRADDR((byte*)"clie1");
Mirf.payload = MIRF_PAYLOAD;
Mirf.channel = 10;
Mirf.config();
pinMode(_tigger, INPUT_PULLUP); // Set pin modes
pinMode(_up, INPUT_PULLUP);
// pinMode(_down, INPUT_PULLUP);
// pinMode(_left, INPUT_PULLUP);
pinMode(_right, INPUT_PULLUP);
pinMode(_A, INPUT_PULLUP);
pinMode(_B, INPUT_PULLUP);
pinMode(_start, INPUT_PULLUP);
pinMode(_select, INPUT_PULLUP);
pinMode(_reload, INPUT_PULLUP);
myDFRobotIRPosition.begin(); // Start IR Camera
delay(500);
}
void loop() {
Mirf.setTADDR((byte*)"serv1");
memcpy(txData, msg + msgIndex, MIRF_PAYLOAD);
Mirf.send(txData);
while (Mirf.isSending()) {
}
delay(ritardo);
mouseButtons();
getPosition();
}
/* ----------------------------------------------- */
/* --------------------------- METHODS ------------------------- */
/* ----------------------------------------------- */
void getPosition() { // Get tilt adjusted position from IR postioning camera
myDFRobotIRPosition.requestPosition();
if (myDFRobotIRPosition.available()) {
for (int i = 0; i < 4; i++) {
positionX[i] = myDFRobotIRPosition.readX(i);
positionY[i] = myDFRobotIRPosition.readY(i);
}
if (positionX[0] > positionX[1]) {
oneY = positionY[0];
oneX = positionX[0];
twoY = positionY[1];
twoX = positionX[1];
}
else if (positionX[0] < positionX[1]) {
oneY = positionY[1];
oneX = positionX[1];
twoY = positionY[0];
twoX = positionX[0];
}
else {
oneY = res_y;
oneX = 0;
twoY = res_y;
twoX = 0;
}
finalX = (res_x / 2) + cos(atan2(twoY - oneY, twoX - oneX) * -1) * (((oneX - twoX) / 2 + twoX) - (res_x / 2)) - sin(atan2(twoY - oneY, twoX - oneX) * -1) * (((oneY - twoY) / 2 + twoY) - (res_y / 2));
finalY = (res_y / 2) + sin(atan2(twoY - oneY, twoX - oneX) * -1) * (((oneX - twoX) / 2 + twoX) - (res_x / 2)) + cos(atan2(twoY - oneY, twoX - oneX) * -1) * (((oneY - twoY) / 2 + twoY) - (res_y / 2));
stringa = String("-5-") + String(finalX) + String("-") + String(finalY) + String("-") + String(buttonState2) + String("-") + String(buttonState9) + String("-") + String(buttonState8) + String("-") + String(buttonState7) + String("-") + String(buttonState1) ;
stringa.toCharArray(msg, 50) ;
}
else {
Serial.println("Device not available!");
}
}
void mouseButtons() { // Setup Left, Right & Middle Mouse buttons
buttonState2 = digitalRead(_tigger);
buttonState3 = digitalRead(_up);
// buttonState4 = digitalRead(_down);
// buttonState5 = digitalRead(_left);
buttonState6 = digitalRead(_right);
buttonState9 = digitalRead(_start);
buttonState10 = digitalRead(_select);
buttonState1 = digitalRead(_reload);
buttonState7 = digitalRead(_A);
buttonState8 = digitalRead(_B);
}
Codice modulo RX
Codice: Seleziona tutto
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#define MIRF_PAYLOAD 32
byte rxData[MIRF_PAYLOAD + 1];
byte txData[MIRF_PAYLOAD + 1];
int finalX = 0; // Values after tilt correction
int finalY = 0;
int MoveXAxis = 0; // Unconstrained mouse postion
int MoveYAxis = 0;
int conMoveXAxis = 0; // Constrained mouse postion
int conMoveYAxis = 0;
int count = 4; // Set intial count
int buttonState1 = 0;
int lastButtonState1 = 0;
int buttonState2 = 0;
int lastButtonState2 = 0;
int buttonState3 = 0;
int lastButtonState3 = 0;
int buttonState4 = 0;
int lastButtonState4 = 0;
int buttonState5 = 0;
int lastButtonState5 = 0;
int buttonState6 = 0;
int lastButtonState6 = 0;
int buttonState7 = 0;
int lastButtonState7 = 0;
int buttonState8 = 0;
int lastButtonState8 = 0;
int buttonState9 = 0;
int lastButtonState9 = 0;
int buttonState10 = 0;
int lastButtonState10 = 0;
int correzzione = 0;
int offset_x = 0; //300
int offset_y = 0; //200
int barra = 0;
#include <HID.h> // Load libraries
#include <Wire.h>
#include <Keyboard.h>
#include <AbsMouse.h>
//#include <DFRobotIRPosition.h>
//DFRobotIRPosition myDFRobotIRPosition;
int res_x = 1920; // Put your screen resolution width here
int res_y = 1080; // Put your screen resolution height here
String ricevuto;
char *lettura[10];
byte c_lettura = 0;
char charBuf[50];
void setup() {
memset(rxData, 0, sizeof(rxData));
memset(txData, 0, sizeof(txData));
Serial.begin(9600);
Mirf.cePin = 9;
Mirf.csnPin = 10;
Mirf.spi = &MirfHardwareSpi;
Mirf.init();
Mirf.setRADDR((byte*)"serv1");
Mirf.payload = MIRF_PAYLOAD;
Mirf.channel = 10;
Mirf.config();
AbsMouse.init(res_x, res_y);
AbsMouse.move((res_x / 2), (res_y / 2)); // Set mouse position to centre of the screen
delay(500);
}
void loop() {
c_lettura = 0;
memset(rxData, 0, sizeof(rxData));
if (!Mirf.isSending() && Mirf.dataReady()) {
Mirf.getData(rxData);
if (count == 4)count = 0;
lettura[c_lettura] = strtok((const char*)rxData, "-");
while ( c_lettura < 9)
{
lettura[c_lettura] = strtok(NULL, "-");
++c_lettura;
}
finalX = atoi(lettura[0]);
finalY = atoi(lettura[1]);
buttonState2 = atoi(lettura[2]);
buttonState9 = atoi(lettura[3]);
buttonState8 = atoi(lettura[4]);
buttonState7 = atoi(lettura[5]);
buttonState1 = atoi(lettura[6]);
Serial.print(count);
Serial.print("|");
Serial.print(offset_x);
Serial.print("|");
Serial.print(offset_y);
Serial.print("|");
Serial.print(buttonState2);
Serial.print("|");
Serial.print(buttonState9);
Serial.print("|");
Serial.print( buttonState8);
Serial.print("|");
Serial.print(buttonState7);
Serial.print("|");
Serial.println(buttonState1);
Mirf.setTADDR((byte*)"clie1");
for (unsigned i = 0; i != MIRF_PAYLOAD; ++i) {
txData[i] = rxData[i] + 1;
}
Mirf.send(txData);
} else {
if (count == 0)count = 4;
}
if (count == 4) {
mouseButtons();
go();
}
/* ------------------ START/PAUSE MOUSE ---------------------- */
else if (count == 3 ) {
reset();
mouseCount();
mouseButtons();
}
/* -------------------- Calibrazione -------------------------- */
else if (count == 2 ) {
if (barra == 0){
AbsMouse.move(offset_x + correzzione, offset_y + correzzione);
delay(20);
AbsMouse.move((res_x - (offset_x + correzzione)), offset_y + correzzione);
delay(20);
}else{
AbsMouse.move((res_x - (offset_x + correzzione)), (res_y - (offset_y + correzzione)));
delay(20);
AbsMouse.move(offset_x + correzzione, (res_y - (offset_y + correzzione)));
delay(20);
}
mouseCount();
reset();
/* ---------------------------------------------- */
}
else {
AbsMouse.move(conMoveXAxis, conMoveYAxis);
mouseButtons();
MoveXAxis = map (finalX, 1600, 1200, offset_x, (res_x - offset_x));
MoveYAxis = map (finalY, 700-barra, 1000-barra, offset_y, (res_y - offset_y));
conMoveXAxis = constrain (MoveXAxis, 0, res_x);
conMoveYAxis = constrain (MoveYAxis, 0, res_y);
reset();
}
}
/* ----------------------------------------------- */
/* --------------------------- METHODS ------------------------- */
/* ----------------------------------------------- */
void go() { // Setup Start Calibration Button
// buttonState1 = digitalRead(_reload);
if (buttonState1 != lastButtonState1) {
if (buttonState1 == LOW) {
count == 3;
}
else { // do nothing
}
delay(50);
}
lastButtonState1 = buttonState1;
}
void mouseButtons() { // Setup Left, Right & Middle Mouse buttons
if (buttonState2 != lastButtonState2) {
if (buttonState2 == LOW) {
AbsMouse.press(MOUSE_LEFT);
}
else {
AbsMouse.release(MOUSE_LEFT);
}
}
if (buttonState3 != lastButtonState3) {
if (buttonState3 == LOW) {
Keyboard.press(KEY_UP_ARROW);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
if (buttonState4 != lastButtonState4) {
if (buttonState4 == LOW) {
Keyboard.press(KEY_DOWN_ARROW);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
if (buttonState5 != lastButtonState5) {
if (buttonState5 == LOW) {
Keyboard.press(KEY_LEFT_ARROW);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
if (buttonState6 != lastButtonState6) {
if (buttonState6 == LOW) {
Keyboard.press(KEY_RIGHT_ARROW);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
if (buttonState7 != lastButtonState7) {
if (buttonState7 == LOW) {
AbsMouse.press(MOUSE_RIGHT);
}
else {
AbsMouse.release(MOUSE_RIGHT);
}
}
if (buttonState8 != lastButtonState8) {
if (buttonState8 == LOW) {
AbsMouse.press(MOUSE_MIDDLE);
}
else {
AbsMouse.release(MOUSE_MIDDLE);
}
}
if (buttonState9 != lastButtonState9) {
if (buttonState9 == LOW) {
Keyboard.press(KEY_BACKSPACE);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
if (buttonState10 != lastButtonState10) {
if (buttonState10 == LOW) {
Keyboard.press(KEY_RETURN);
delay(100);
Keyboard.releaseAll();
}
else {
}
}
lastButtonState2 = buttonState2;
lastButtonState3 = buttonState3;
lastButtonState4 = buttonState4;
lastButtonState5 = buttonState5;
lastButtonState6 = buttonState6;
lastButtonState7 = buttonState7;
lastButtonState8 = buttonState8;
lastButtonState9 = buttonState9;
lastButtonState10 = buttonState10;
}
void mouseCount() { // Set count down on trigger
if (buttonState2 != lastButtonState2) {
if (buttonState2 == LOW) {
if (count == 3) {
count--;
} else if (count == 2) {
if (offset_x < 500) {
offset_x = offset_x + 100;
offset_y = offset_y + 80;
} else {
offset_x = 0;
offset_y = 0;
}
}
else { // do nothing
}
// delay(10);
}
lastButtonState2 = buttonState2;
}
if (buttonState7 != lastButtonState7) {
if (buttonState7 == LOW) {
if (barra==0) {
barra = 300;
} else {
barra = 0;
}
}
lastButtonState7 = buttonState7l;
}
}
void reset() { // Pause/Re-calibrate button
if (buttonState1 != lastButtonState1) {
if (buttonState1 == LOW) {
if (count == 0) {
count = 3;
} else {
count = 0;
}
delay(50);
}
else { // do nothing
}
delay(50);
}
lastButtonState1 = buttonState1;
}