Paso 8: El código
El código deNotas de código:
No voy a entrar en mucho detalle acerca de cómo los trabajos del código que los comentarios bastante extensos en el código será suficiente para explicarlo, si no la hay ya buenos tutoriales por ahí.
Limitaciones:
El código funciona sólo está configurado de manera que sólo puede hacer una cosa a la vez y hasta el arduino de doble núcleo es más fácil lidiar con eso.
Se trata de fotografiar un tagger no notará si consigue tiro/etiquetado. Podría complicar el código mediante el uso de interrupciones, pero en el mundo real no es un gran problema, el tiro tiro o se sucede tan rápidamente que muy raramente interfieren con uno a.
En el futuro iteraciones del código probablemente se hacerlo para que el tagger comprueba ver si ha sido etiquetado entre cada pedacito lo transmite, lo que es muy poco probable que se pierda un mensaje entrante (hit / tag). He jugado algunos juegos usando este código y el código similar y parece que funciona bien.
------------------------------------------------------------------------------------------------------------------
Comienzo del código (copiar y pegar en el sketch de arduino)
//
Lanzamiento de la etiqueta de Duino V1.01
Laser Tag para el arduino basado en el protocolo de etiqueta de Miles.
Por J44industries: www.J44industries.blogspot.com
Para obtener información en la construcción de tu propio Duino Tagger:
//
Mucho crédito se merece ir a o ' Brien Duane si no hubiera sido por los excelentes tutoriales de Duino etiqueta que escribió que nunca hubiera podido escribir este código.
Tutoriales de Duane son muy recomendables de leer para obtener una mejor comprensión de la arduino y la comunicación de IR. Ver su http://aterribleidea.com/duino-tag-resources/ sitio
//
Este código establece las bases para el sistema de etiqueta de láser basado en arduino y trata de cumplir el protocolo de etiqueta millas cuando sea posible.
Datos de miles Tag: http://www.lasertagparts.com/mtdesign.htm
Hay mucho margen para la expansión de las capacidades de este sistema, y esperemos que el juego seguirá evolucionando durante algún tiempo.
Licencia: Attribution Share Alike: dar crédito donde crédito es debido, pero usted puede hacer lo que quieras con el código.
Si tienes mejoras de código o adiciones por favor van a http://duinotag.blogspot.com
//
Digital IO
int triggerPin = 3; Botón de fuego primario. Bajo = presiona
int trigger2Pin = 13; Botón de fuego secundario. Bajo = presiona
int speakerPin = 4; Salida directa a la sonda/altavoz piezoeléctrico
int audioPin = 9; Generador de audio. Puede utilizarse para activar sonidos registrados en la clase de electrónica se puede obtener en la tarjeta que juega un mensaje personalizado.
int lifePin = 6; Un nivel de salida analógica (PWM) corresponde al resto de la vida. Pin de uso PWM: 3,5,6,9,10 o 11. Puede utilizarse para gráficos de barras de LED. por ejemplo, LM3914N
int ammoPin = 5; Un nivel de salida analógica (PWM) corresponde a la munición restante. Pin de uso PWM: 3,5,6,9,10 o 11.
int hitPin = 7; Pin de salida de LED utilizado para indicar cuando el jugador ha sido golpeado.
int IRtransmitPin = 2; Perno de disparo primario modo IR Transmisor: Use alfileres 2,4,7,8,12 o 13. HACER pins de uso PWM no!! Más info: http://j44industries.blogspot.com/2009/09/arduino-frequency-generation.html#more
int IRtransmit2Pin = 8; Perno de disparo secundario modo IR Transmisor: Use alfileres 2,4,7,8,12 o 13. HACER pins de uso PWM no!!
int IRreceivePin = 12; El pin que se pueden leer las señales de infrarrojos
int IRreceive2Pin = 11; Permite la comprobación de sensores externos se unen, así como distinguir entre ubicaciones de los sensores (por ejemplo, localización de disparos en la cabeza)
Requisitos mínimo arma: golpe de gatillo, receptor IR, led, LED.
Datos de jugador y juego
int myTeamID = 1; 1-7 (0 = mensaje del sistema)
int myPlayerID = 5; ID de jugador
int myGameID = 0; Interprited por configureGane de subrutina; permite el cambio rápido de tipos de juego.
int myWeaponID = 0; Deffined de subrutina gameType y configureGame.
int myWeaponHP = 0; Deffined de subrutina gameType y configureGame.
maxAmmo int = 0; Deffined de subrutina gameType y configureGame.
maxLife int = 0; Deffined de subrutina gameType y configureGame.
automático de int = 0; Deffined de subrutina gameType y configureGame. Automática de incendios 0 = Semi Automatico, 1 = totalmente automático.
int automatic2 = 0; Deffined de subrutina gameType y configureGame. ¿Auto disparo secundario?
Detalles de la señal de entrada
int recibido [18]; Los datos recibidos: recibido [0] = sensor que, recibido [1] - [17] paridad de byte2 byte1 (estructura Miles)
control de int = 0; Variable utilizada en la comprobación de paridad
Gráficas de las estadísticas
munición de int = 0; Munición actual
vida de int = 0; Vida actual
Código Variables
int espera = 0; Deffined en frequencyCalculations (IRpulse + 50)
int fuego = 0; 0 = no de fuego, 1 = disparar primaria, 2 = secundaria fuego
int TR = 0; Lectura de gatillo
int l = 0; Última lectura del gatillo
int T2R = 0; Gatillo 2 lectura (disparo secundario)
int LT2R = 0; Gatillo 2 lectura (para fuego secundario)
Propiedades de la señal
int IRpulse = 600; Duración del pulso básico de 600uS MilesTag estándar 4 * IRpulse para cabecera pedacito, 2 * IRpulse de 1, 1 * IRpulse de 0.
int IRfrequency = 38; Frecuencia en kHz, los valores estándar son: 38kHz, 40kHz. Elegir a depende de las características de su receptor
int IRt = 0; LLEVADO a tiempo a dar frecuencia de transmisión correcta, calculado en la configuración.
int IRpulses = 0; Número de oscilaciones que se necesita para hacer un IRpulse completo, calculado en la configuración.
Jefe int = 4; Longitud del encabezado en pulsos. 4 = Miles etiqueta estándar
int maxSPS = 10; Máximo disparos por segundos. Aún no se ha utilizado.
int TBS = 0; Tiempo entre tomas. Aún no se ha utilizado.
Datos de la transmisión
byte1 int [8]; Cadena para almacenar byte1 de los datos que obtienen transmitidos cuando el jugador.
byte2 int [8]; Cadena para almacenar byte1 de los datos que obtienen transmitidos cuando el jugador.
int myParity = 0; Cadena para almacenar la paridad de los datos que obtienen transmitidos cuando el jugador.
Datos recibidos
memoria int = 10; Número de señales a grabar: permite que los datos del juego que deben ser revisadas después del juego, ninguna disposición para transmitir y acceder a él sin embargo sin embargo.
hitNo de int = 0; Hit número
Byte1
int jugador [10]; Matriz debe ser tan grande como la memoria
equipo int [10]; Matriz debe ser tan grande como la memoria
Byte2
arma de int [10]; Matriz debe ser tan grande como la memoria
hp int [10]; Matriz debe ser tan grande como la memoria
int paridad [10]; Matriz debe ser tan grande como la memoria
void setup() {}
Serial com para ayudar con la depuración.
Serial.Begin(9600);
Serial.println("startup...");
Declaraciones de PIN
pinMode (triggerPin, entrada);
pinMode (trigger2Pin, entrada);
pinMode (speakerPin, salida);
pinMode (audioPin, salida);
pinMode (lifePin, salida);
pinMode (ammoPin, salida);
pinMode (hitPin, salida);
pinMode (IRtransmitPin, salida);
pinMode (IRtransmit2Pin, salida);
pinMode (IRreceivePin, entrada);
pinMode (IRreceive2Pin, entrada);
frequencyCalculations(); Calcula longitudes de pulso etc para la frecuencia deseada
configureGame(); Ver y configurar los detalles del juego
tagCode(); Basado en juego de detalles de obras etc. los datos que se transmitirán cuando se disparó un tiro
digitalWrite (triggerPin, HIGH); No es realmente necesario si tu circuito tiene el tirón correcto hasta resistencias ya pero no daña
digitalWrite (trigger2Pin, HIGH); No es realmente necesario si tu circuito tiene el tirón correcto hasta resistencias ya pero no daña
para (int i = 1; i < 254; i ++) {/ / juegos Loop start ruido
analogWrite(ammoPin, i);
playTone((3000-9*i), 2);
}
A continuación 4 líneas inicializar la pantalla LED
analogWrite (ammoPin, (munición (int)));
analogWrite (lifePin, (int) (la vida));
lifeDisplay();
ammoDisplay();
Serial.println("Ready...");
}
Principal lazo la mayoría del código está en las rutinas de sub
void loop() {}
receiveIR();
Si (fuego! = 0) {}
Shoot();
ammoDisplay();
}
triggers();
}
SUB RUTINAS
void ammoDisplay() {/ / actualizaciones munición LED salida
Float ammoF;
ammoF = (260/maxAmmo) * munición;
Si (ammoF < = 0) {ammoF = 0;}
if(ammoF > 255) {ammoF = 255;}
analogWrite (ammoPin, ((int) ammoF));
}
void lifeDisplay() {/ / actualizaciones munición LED salida
flotador lifeF;
lifeF = (260/maxLife) * vida;
Si (lifeF < = 0) {lifeF = 0;}
if(lifeF > 255) {lifeF = 255;}
analogWrite (lifePin, ((int) lifeF));
}
void receiveIR() {/ / Void comprueba una señal entrante y decodifica si ve uno.
error de int = 0;
if(digitalRead(IRreceivePin) == LOW) {/ / si el pin de recepción es baja se está recibiendo una señal.
digitalWrite(hitPin,HIGH);
¿if(digitalread(irreceive2pin) == LOW) {/ / es la entrada la señal siendo recibida por los sensores de la cabeza?
recibió [0] = 1;
}
Else {}
recibió [0] = 0;
}
while(digitalRead(IRreceivePin) == LOW) {}
}
para (int i = 1; i < = 17; i ++) {/ / se repite varias veces para asegurarse de que toda la señal ha sido recibida
recibió [i] = pulseIn (IRreceivePin, baja, tiempo de espera); pulseIn comando espera un pulso y luego registra su duración en microsegundos.
}
Serial.Print ("sensor:"); Impresiones si era una cabeza de tiro o no.
Serial.Print(Received[0]);
Serial.Print("...");
para (int i = 1; i < = 17; i ++) {/ / se ve en cada uno de los impulsos recibidos
int receivedTemp [18];
receivedTemp [i] = 2;
Si (recibidos [i] > (IRpulse - 200) & & recibidos [i] < (IRpulse + 200)) {receivedTemp [i] = 0;} Trabajos fuera de la longitud de pulso si es un 1 o 0 que recibió de datos escribe resultado en cadena receivedTemp
Si (recibidos [i] > (IRpulse + IRpulse - 200) & & recibidos [i] < (IRpulse + IRpulse + 200)) {receivedTemp [i] = 1;} Resulta de la longitud de pulso si es unas 1 o 0 que recibió los datos
recibió [i] = 3; Datos recibidos de los trapos
recibió [i] = receivedTemp [i]; Entradas de interpretaron datos
Serial.Print("");
Serial.Print(Received[i]); Imprimir los resultados de datos interpretados
}
Serial.println(""); Nueva línea para poner en orden los resultados impresos
Comprobación de paridad. ¿Los datos recibido una señal válida?
comprobar = 0;
para (int i = 1; i < = 16; i ++) {}
Si (recibidos [i] == 1) {comprobar = control + 1;}
Si (recibidos [i] == 2) {error = 1;}
}
Serial.println(check);
comprobar = check >> 0 y B1;
Serial.println(check);
Si (Compruebe! = received[17]) {error = 1;}
Si (error == 0){Serial.println "(señal válida del);}
Else{serial.println("error");}
Si (error == 0){interpritReceived();}
digitalWrite(hitPin,LOW);
}
}
void interpritReceived() {/ / después de que un mensaje ha sido recibido por la subrutina ReceiveIR este decidedes de subrutina cómo debe reaccionar a los datos
if(hitNo == Memory) {hitNo = 0;} / / hitNo clasifica hacia fuera donde los datos deben ser guardados si se recibieron declaración medios obtienen sobrescribe datos antiguos si es mucho
equipo [hitNo] = 0;
jugador [hitNo] = 0;
arma [hitNo] = 0;
HP [hitNo] = 0;
Siguientes líneas algunos Effectivly convierte los datos binarios en decimal
IM seguro que debe haber una forma mucho más eficiente de hacer esto
Si (recibido [1] == 1) {equipo [hitNo] = equipo [hitNo] + 4;}
Si (recibido [2] == 1) {equipo [hitNo] equipo [hitNo] = 2;}
Si (recibido [3] == 1) {equipo [hitNo] = equipo [hitNo] + 1;}
Si (recibido [4] == 1) {jugador [hitNo] jugador [hitNo] = 16;}
Si (recibido [5] == 1) {jugador [hitNo] jugador [hitNo] = 8;}
Si (recibido [6] == 1) {jugador [hitNo] jugador [hitNo] = 4;}
Si (recibido [7] == 1) {jugador [hitNo] jugador [hitNo] = 2;}
Si (recibido [8] == 1) {jugador [hitNo] jugador [hitNo] = 1;}
Si (recibido [9] == 1) {arma [hitNo] = arma [hitNo] + 4;}
Si (recibido [10] == 1) {arma [hitNo] armas [hitNo] = 2;}
Si (recibido [11] == 1) {arma [hitNo] = arma [hitNo] + 1;}
Si (recibido [12] == 1) {hp [hitNo] hp [hitNo] = 16;}
Si (recibido [13] == 1) {hp [hitNo] hp [hitNo] = 8;}
Si (recibido [14] == 1) {hp [hitNo] hp [hitNo] = 4;}
Si (recibido [15] == 1) {hp [hitNo] hp [hitNo] = 2;}
Si (recibido [16] == 1) {hp [hitNo] hp [hitNo] = 1;}
paridad [hitNo] = recibido [17];
Serial.Print ("golpe No:");
Serial.Print(hitNo);
Serial.Print ("jugador:");
Serial.Print(Player[hitNo]);
Serial.Print ("equipo:");
Serial.Print(Team[hitNo]);
Serial.Print ("arma:");
Serial.Print(Weapon[hitNo]);
Serial.Print ("caballos de fuerza:");
Serial.Print(HP[hitNo]);
Serial.Print ("paridad:");
Serial.println(Parity[hitNo]);
Esto es probablemente donde se debe agregar más código a ampliar las capacidades de juego en el momento que el código sólo comprueba que los datos recibidos no era un mensaje de sistema y resta una vida si no fuera.
Si (jugador [hitNo]! = 0){hit();}
hitNo ++;
}
void shoot() {}
¿if(Fire == 1) {/ / se ha presionado el gatillo?
Serial.println ("fuego 1");
sendPulse (IRtransmitPin, 4); Transmitir el pulso de la cabecera, enviar subrutina pulso aborda los detalles
delayMicroseconds(IRpulse);
para (int i = 0; i < 8; i ++) {/ / transmitir Byte1
Si (byte1 [i] == 1) {}
sendPulse (IRtransmitPin, 1);
Serial.Print ("1");
}
Else{serial.Print ("0");}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
}
para (int i = 0; i < 8; i ++) {/ / transmitir Byte2
Si (byte2 [i] == 1) {}
sendPulse (IRtransmitPin, 1);
Serial.Print ("1");
}
Else{serial.Print ("0");}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
}
if(myParity == 1) {/ / paridad
sendPulse (IRtransmitPin, 1);
}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
Serial.println("");
Serial.println ("hecho 1);
}
if(Fire == 2) {/ / donde se añadirá un modo de fuego secundario
Serial.println ("fuego 2");
sendPulse (IRtransmitPin, 4); Cabecera
Serial.println ("hecho 2");
}
FUEGO = 0;
Municion = munición - 1;
}
void sendPulse (int pin, int longitud) {/ / importar variables como esto permite modos de disparo secundario etc..
Este vacío genertates la frecuencia de la portadora por la información a transmitir
int i = 0;
o int = 0;
mientras (i < longitud) {}
i ++;
mientras (o < IRpulses) {}
o ++;
digitalWrite (pin, HIGH);
delayMicroseconds(IRt);
digitalWrite (pin, LOW);
delayMicroseconds(IRt);
}
}
}
void triggers() {/ / comprueba si los factores desencadenantes han sido Prensas
LTR = TR; Estado anterior de los registros. Fuego primario
LT2R = T2R; Estado anterior de los registros. Fuego secundario
TR = digitalRead(triggerPin); Busca estado de botón disparador actual
T2R = digitalRead(trigger2Pin); Busca estado de botón disparador actual
Código busca cambios en el estado de disparo para darle un comportamiento disparo automático semi
Si (TR! = LTR & & TR == LOW) {}
FUEGO = 1;
}
Si (T2R! = LT2R & & T2R == LOW) {}
FUEGO = 2;
}
Si (TR == baja & & automático == 1) {}
FUEGO = 1;
}
Si (T2R == baja & & automatic2 == 1) {}
FUEGO = 2;
}
Si (fuego == 1 || FUEGO == 2) {}
if(ammo < 1) {fuego = 0; noAmmo();}
if(Life < 1) {fuego = 0; dead();}
Fuego tipo código a añadir aquí
}
}
void configureGame() {/ / donde se almacenan las características de juego, permite varios juego tipos a grabar y solo tienes que cambiar una variable (myGameID) para elegir el juego.
if(myGameID == 0) {}
myWeaponID = 1;
maxAmmo = 30;
Municion = 30;
maxLife = 3;
vida = 3;
myWeaponHP = 1;
}
if(myGameID == 1) {}
myWeaponID = 1;
maxAmmo = 100;
Municion = 100;
maxLife = 10;
vida = 10;
myWeaponHP = 2;
}
}
void frequencyCalculations() {/ / funciona hacia fuera de todos los tiempos necesarios para dar la frecuencia portadora correcta para la señal IR
IRt = (int) (500/IRfrequency);
IRpulses = (int) (IRpulse / (2 * IRt));
IRt = IRt - 4;
Por qué-4 escucho llorar. Permite por el tiempo tomado para que comandos a ser ejecutados.
Más info: http://j44industries.blogspot.com/2009/09/arduino-frequency-generation.html#more
Serial.Print ("concusiones tiempo período 2:");
Serial.println(IRt);
Serial.Print ("pulsaciones:");
Serial.println(IRpulses);
tiempo de espera = IRpulse + 50; Agregar 50 al esperado pulso tiempo da un pequeño margen de error el pulso Lee valor de tiempo
}
void tagCode() {/ / obras es lo que los jugadores tagger (el código que se transmite cuando dispara)
byte1 [0] = myTeamID >> 2 y B1;
byte1 [1] = myTeamID >> 1 y B1;
byte1 [2] = myTeamID >> 0 y B1;
byte1 [3] = myPlayerID >> 4 y B1;
byte1 [4] = myPlayerID >> 3 y B1;
byte1 [5] = myPlayerID >> 2 y B1;
byte1 [6] = myPlayerID >> 1 y B1;
byte1 [7] = myPlayerID >> 0 y B1;
byte2 [0] = myWeaponID >> 2 y B1;
byte2 [1] = myWeaponID >> 1 y B1;
byte2 [2] = myWeaponID >> 0 y B1;
byte2 [3] = myWeaponHP >> 4 y B1;
byte2 [4] = myWeaponHP >> 3 y B1;
byte2 [5] = myWeaponHP >> 2 y B1;
byte2 [6] = myWeaponHP >> 1 y B1;
byte2 [7] = myWeaponHP >> 0 y B1;
myParity = 0;
para (int i = 0; i < 8; i ++) {}
Si (byte1 [i] == 1) {myParity = myParity + 1;}
Si (byte2 [i] == 1) {myParity = myParity + 1;}
myParity = myParity >> 0 y B1;
}
Siguientes líneas algunos imprimen el código completo tagger.
Serial.Print ("Byte1:");
Serial.Print(byte1[0]);
Serial.Print(byte1[1]);
Serial.Print(byte1[2]);
Serial.Print(byte1[3]);
Serial.Print(byte1[4]);
Serial.Print(byte1[5]);
Serial.Print(byte1[6]);
Serial.Print(byte1[7]);
Serial.println();
Serial.Print ("Byte2:");
Serial.Print(byte2[0]);
Serial.Print(byte2[1]);
Serial.Print(byte2[2]);
Serial.Print(byte2[3]);
Serial.Print(byte2[4]);
Serial.Print(byte2[5]);
Serial.Print(byte2[6]);
Serial.Print(byte2[7]);
Serial.println();
Serial.Print ("paridad:");
Serial.Print(myParity);
Serial.println();
}
void playTone (int tono, duración int) {/ / una rutina sub para la reproducción de tonos como el ejemplo de la melodía de arduino estándar
para (largo i = 0; i < duración * 1000L; i += tono * 2) {}
digitalWrite (speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite (speakerPin, bajo);
delayMicroseconds(tone);
}
}
void dead() {/ / void determina lo que hace el tagger cuando está fuera de vidas
Hace unos ruidos y parpadea algunas luces
para (int i = 1; i < 254; i ++) {}
analogWrite(ammoPin, i);
playTone((1000+9*i), 2);
}
analogWrite (ammoPin, (munición (int)));
analogWrite (lifePin, (int) (la vida));
Serial.println("Dead");
para (int i = 0; i < 10; i ++) {}
analogWrite (ammoPin, 255);
digitalWrite(hitPin,HIGH);
Delay (500);
analogWrite (ammoPin, 0);
digitalWrite(hitPin,LOW);
Delay (500);
}
}
void noAmmo() {/ / hacer algo de ruido y flash algunas luces cuando fuera de la munición
digitalWrite(hitPin,HIGH);
playTone (500, 100);
playTone(1000, 100);
digitalWrite(hitPin,LOW);
}
void hit() {/ / hacer algo de ruido y flash algunas luces cuando te disparen
digitalWrite(hitPin,HIGH);
vida = vida - hp [hitNo];
Serial.Print ("la vida:");
Serial.println(Life);
playTone (500, 500);
Si (vida < = 0){dead();}
digitalWrite(hitPin,LOW);
lifeDisplay();
}