Stap 8: De Code
De CodeCode opmerkingen:
Ik ga niet veel details over hoe de code werkt hopelijk de vrij uitgebreid commentaar, waarin de code zal volstaan om het te verklaren, zo niet het daar al goede tutorials die er zijn.
Beperkingen:
De code werkt alleen is ingesteld op een manier dat het slechts één ding tegelijk en tot de dual core-arduino kan doen is het makkelijkst wil omgaan met die.
Dit betekent dat wanneer een muzikale is schieten het ziet niet als het wordt schot/gelabeld. U de code met behulp van interrupts kan bemoeilijken, maar in de echte wereld, die het is niet echt een groot probleem, het schieten of krijgen schot zo snel gebeuren dat zij zeer zelden met elkaar interfereren.
In de toekomst iteraties van de code die ik waarschijnlijk maken zal, zodat de tagger om te zien controleert als er tagged in-between elke bit het uitzendt, waardoor het zeer zeer onwaarschijnlijk dat het een binnenkomend bericht (hit / tag) zou missen. Ik heb een paar games met behulp van deze code en de gelijkaardige code gespeeld en het lijkt goed te werken.
------------------------------------------------------------------------------------------------------------------
Begin van de code (kopiëren en plakken in de arduino schets)
//
Duino Tag release V1.01
Laser Tag voor de arduino die is gebaseerd op het Protocol van de Tag Miles.
Door J44industries: www.J44industries.blogspot.com
Ga voor informatie over het bouwen van uw eigen Duino Tagger naar:
//
Veel lof verdient naar Duane O'Brien als het niet had voor de uitstekende Duino Label tutorials die hij schreef dat ik nooit geweest kundig voor het schrijven van deze code.
Duane's tutorials zijn sterk aanbevolen lezen om een beter inzicht van de arduino en IR-communicatie. Zie zijn site http://aterribleidea.com/duino-tag-resources/
//
Deze code de basis voor arduino gebaseerd laser tag systeem uiteengezet en probeert vast te houden aan het protocol van de tag mijl waar mogelijk.
Miles Tag details: http://www.lasertagparts.com/mtdesign.htm
Er is veel ruimte voor uitbreiding van de mogelijkheden van dit systeem, en hopelijk het spel zal blijven evolueren voor enige tijd te komen.
Licentie: Naamsvermelding GelijkDelen: geven krediet waar krediet is te wijten, maar u kunt doen wat je wilt met de code.
Als u code verbeteringen of toevoegingen Ga naar http://duinotag.blogspot.com
//
De digitale IO
int triggerPin = 3; Drukknop voor primaire brand. Laag = ingedrukt
int trigger2Pin = 13; Drukknop voor secundaire brand. Laag = ingedrukt
int speakerPin = 4; Directe output piezo sounder/spreker
int audioPin = 9; Audio Trigger. Kan worden gebruikt voor verrekening van de geluiden opgenomen in het soort elektronica kunt u in de wenskaart die spelen een aangepast bericht.
int lifePin = 6; Een analoge uitgangsniveau (PWM) komt overeen met de resterende looptijd. Gebruik PWM pin: 3,5,6,9,10 of 11. Kan worden gebruikt om de LED bar grafieken rijden. BV LM3914N
int ammoPin = 5; Een analoge uitgangsniveau (PWM) komt overeen met de resterende munitie. Gebruik PWM pin: 3,5,6,9,10 of 11.
int hitPin = 7; LED uitgang pins gebruikt om aan te geven wanneer de speler heeft getroffen.
int IRtransmitPin = 2; Primaire vuur modus IR zender pin: gebruik pennen 2,4,7,8,12 of 13. Doe niet gebruik PWM pinnen! Meer info: http://j44industries.blogspot.com/2009/09/arduino-frequency-generation.html#more
int IRtransmit2Pin = 8; Secundaire vuur modus IR zender pin: gebruik pennen 2,4,7,8,12 of 13. Doe niet gebruik PWM pinnen!
int IRreceivePin = 12; De pin dat binnenkomende IR-signalen worden gelezen uit
int IRreceive2Pin = 11; Voorziet in controle externe sensoren zijn aangesloten, alsook het onderscheid te maken tussen de locaties van de sensor (bijv spotten hoofd schoten)
Minimale pistool eisen: trigger, ontvanger, IR led, LED raken.
Speler en spel details
int myTeamID = 1; 1-7 (0 = systeembericht)
int myPlayerID = 5; Speler-ID
int myGameID = 0; Interprited door de configureGane subroutine; zorgt voor snelle verandering van spelsoorten.
int myWeaponID = 0; Deffined door gameType en configureGame subroutine.
int myWeaponHP = 0; Deffined door gameType en configureGame subroutine.
int maxAmmo = 0; Deffined door gameType en configureGame subroutine.
int maxLife = 0; Deffined door gameType en configureGame subroutine.
int automatische = 0; Deffined door gameType en configureGame subroutine. Automatische brand 0 = Semi Auto, 1 = volledige Auto.
int automatic2 = 0; Deffined door gameType en configureGame subroutine. Secundaire brand auto?
Binnenkomend signaal Details
int ontvangen [18]; Gegevens ontvangen: ontvangen [0] = welke sensor, ontvangen [1] - [17] byte1 byte2 pariteit (Miles Tag structuur)
int selectievakje = 0; Variabele gebruikt in pariteitscontrole
Stats
int munitie = 0; Huidige munitie
int leven = 0; Huidige leven
Codevariabelen
int timeOut = 0; Deffined in frequencyCalculations (IRpulse + 50)
int brand = 0; 0 = niet vuur, 1 = primaire brand, 2 = secundaire brand
int TR = 0; Trigger-lezing
int LTR = 0; Laatste Trigger-lezing
int T2R = 0; Trigger 2 lezing (voor secundaire brand)
int LT2R = 0; Laatste Trigger 2 lezing (voor secundaire brand)
Eigenschappen van signaal
int IRpulse = 600; Fundamentele impulstijd van 600uS MilesTag standaard 4 * IRpulse voor header bit, 2 * IRpulse voor 1, 1 * IRpulse voor 0.
int IRfrequency = 38; -Frequentie in kHz standaard waarden zijn: 38kHz, 40kHz. Kies afhankelijk van de kenmerken van uw ontvanger
int metro = 0; LED op tijd te geven de juiste zendfrequentie, berekend in setup.
int IRpulses = 0; Het aantal trillingen die nodig zijn om een volledige IRpulse, berekend in setup.
int koptekst = 4; De lengte van de header in peulvruchten. 4 = Miles tag standaard
int maxSPS = 10; Maximale schoten Per seconde. Nog niet zijn gebruikt.
int TBS = 0; Tijd tussen de opnamen. Nog niet zijn gebruikt.
Gegevens van de transmissie
int byte1 [8]; De tekenreeks voor het opslaan van byte1 van de gegevens die wordt verzonden wanneer de speler wordt geactiveerd.
int byte2 [8]; De tekenreeks voor het opslaan van byte1 van de gegevens die wordt verzonden wanneer de speler wordt geactiveerd.
int myParity = 0; De tekenreeks voor het opslaan van de pariteit van de gegevens die wordt verzonden wanneer de speler wordt geactiveerd.
Ontvangen data
int. geheugen = 10; Aantal signalen moeten worden opgetekend: zorgt voor de spelgegevens worden herzien na de wedstrijd, geen voorziening voor het verzenden van / toegang tot het nog wel.
int hitNo = 0; Druk op nummer
Byte1
int speler [10]; Matrix moet zo groot zijn als geheugen
int team [10]; Matrix moet zo groot zijn als geheugen
Byte2
int wapen [10]; Matrix moet zo groot zijn als geheugen
int hp [10]; Matrix moet zo groot zijn als geheugen
int pariteit [10]; Matrix moet zo groot zijn als geheugen
VOID Setup {}
Seriële GMO's opgezet om te helpen met het opsporen van fouten.
Serial.begin(9600);
Serial.println("Startup...");
PIN verklaringen
pinMode (triggerPin, INPUT);
pinMode (trigger2Pin, INPUT);
pinMode (speakerPin, OUTPUT);
pinMode (audioPin, OUTPUT);
pinMode (lifePin, OUTPUT);
pinMode (ammoPin, OUTPUT);
pinMode (hitPin, OUTPUT);
pinMode (IRtransmitPin, uitvoer);
pinMode (IRtransmit2Pin, uitvoer);
pinMode (IRreceivePin, INPUT);
pinMode (IRreceive2Pin, INPUT);
frequencyCalculations(); Pulse lengtes etc voor de gewenste frequentie berekend
configureGame(); Opzoeken en configureren van spel details
tagCode(); Gebaseerd op spel enz werken uit de gegevens die worden verzonden wanneer een shot is ontslagen details
digitalWrite (triggerPin, hoge); Niet echt vereist als uw circuit reeds de juiste trekkracht van weerstanden, maar niet schadelijk
digitalWrite (trigger2Pin, hoge); Niet echt vereist als uw circuit reeds de juiste trekkracht van weerstanden, maar niet schadelijk
voor (int i = 1; ik < 254; i ++) {/ / lus speelt opstarten van lawaai
analogWrite(ammoPin, i);
playTone((3000-9*i), 2);
}
Volgende initialiseren 4 lijnen het display LEDs
analogWrite (ammoPin, ((int) munitie));
analogWrite (lifePin, ((int) leven));
lifeDisplay();
ammoDisplay();
Serial.println("Ready...");
}
Main loop allermeest naar de code is in de sub-routines
void loop {}
receiveIR();
Als (brand! = 0) {}
Shoot();
ammoDisplay();
}
Triggers();
}
SUB ROUTINES
VOID ammoDisplay() {/ / Updates munitie LED output
float ammoF;
ammoF = (260/maxAmmo) * munitie;
Als (ammoF < = 0) {ammoF = 0;}
if(ammoF > 255) {ammoF = 255;}
analogWrite (ammoPin, (ammoF (int)));
}
VOID lifeDisplay() {/ / Updates munitie LED output
float lifeF;
lifeF = (260/maxLife) * leven;
Als (lifeF < = 0) {lifeF = 0;}
if(lifeF > 255) {lifeF = 255;}
analogWrite (lifePin, (lifeF (int)));
}
VOID receiveIR() {/ / Void controleert of een inkomend signaal en decodeert het als het een ziet.
int fout = 0;
if(digitalRead(IRreceivePin) == LOW) {/ / als laag is de pin ontvangen een signaal wordt ontvangen.
digitalWrite(hitPin,HIGH);
if(digitalRead(IRreceive2Pin) == LOW) {/ / Is het binnenkomende signaal wordt ontvangen door de hoofd sensoren?
ontvangen [0] = 1;
}
else {}
ontvangen [0] = 0;
}
while(digitalRead(IRreceivePin) == LOW) {}
}
voor (int i = 1; ik < = 17; i ++) {/ / herhaalt meerdere malen om ervoor te zorgen het hele signaal is ontvangen
ontvangen [i] = pulseIn (IRreceivePin, lage, time-out); pulseIn opdracht wacht op een puls en registreert vervolgens zijn duur in microseconden.
}
Serial.Print ("sensor:"); Afdrukken als het was een hoofd geschoten of niet.
Serial.Print(received[0]);
Serial.Print("...");
voor (int i = 1; ik < = 17; i ++) {/ / kijkt elke één van de ontvangen pulsen
int receivedTemp [18];
receivedTemp [i] = 2;
Als (ontvangen [i] > (IRpulse - 200) & & ontvangen [i] < (IRpulse + 200)) {receivedTemp [i] = 0;} Werkt vanuit de impulslengte als was het een gegevens-1 of 0 die werd ontvangen schrijft resultaat naar receivedTemp string
Als (ontvangen [i] > (IRpulse + IRpulse - 200) & & ontvangen [i] < (IRpulse + IRpulse + 200)) {receivedTemp [i] = 1;} Werkt vanuit de impulslengte als was het een gegevens-1 of 0 die werd ontvangen
ontvangen [i] = 3; Veegt rauwe ontvangen gegevens
ontvangen [i] = receivedTemp [i]; Ingangen geïnterpreteerd gegevens
Serial.Print("");
Serial.Print(received[i]); Geïnterpreteerde gegevensresultaten afdrukken
}
Serial.println(""); Nieuwe lijn voor het opruimen van afdrukresultaten
Parity Check. De gegevens kreeg een geldig signaal?
Controleer = 0;
for (int i = 1; ik < = 16; i ++) {}
Als (ontvangen [i] == 1) {controleren = selectievakje + 1;}
Als (ontvangen [i] == 2) {fout = 1;}
}
Serial.println(check);
controleren check = >> 0 & B1;
Serial.println(check);
Als (controleren! = received[17]) {fout = 1;}
Als (fout == 0){Serial.println ("geldig signaal");}
else{Serial.println("Error");}
Als (fout == 0){interpritReceived();}
digitalWrite(hitPin,LOW);
}
}
VOID interpritReceived() {/ / nadat een bericht is ontvangen door de ReceiveIR subroutine deze subroutine decidedes hoe het op de gegevens reageren moet
if(hitNo == Memory) {hitNo = 0;} / / hitNo sorteert uit waar de gegevens moeten worden opgeslagen als verklaring betekent oude gegevens wordt overschreven als teveel wordt ontvangen
team [hitNo] = 0;
speler [hitNo] = 0;
wapen [hitNo] = 0;
HP [hitNo] = 0;
Volgende paar regels een converteert het binaire gegevens naar decimaal
Im moet zeker er een veel efficiëntere manier om dit te doen
Als (ontvangen [1] == 1) {team [hitNo] = team [hitNo] + 4;}
Als (ontvangen [2] == 1) {team [hitNo] = team [hitNo] + 2;}
Als (ontvangen [3] == 1) {team [hitNo] = team [hitNo] + 1;}
Als (ontvangen [4] == 1) {speler [hitNo] = player [hitNo] + 16;}
Als (ontvangen [5] == 1) {speler [hitNo] = player [hitNo] + 8;}
Als (ontvangen [6] == 1) {speler [hitNo] = player [hitNo] + 4;}
Als (ontvangen [7] == 1) {speler [hitNo] = player [hitNo] + 2;}
Als (ontvangen [8] == 1) {speler [hitNo] = speler [hitNo] + 1;}
Als (ontvangen [9] == 1) {wapen [hitNo] = wapen [hitNo] + 4;}
Als (ontvangen [10] == 1) {wapen [hitNo] = wapen [hitNo] + 2;}
Als (ontvangen [11] == 1) {wapen [hitNo] = wapen [hitNo] + 1;}
Als (ontvangen [12] == 1) {hp [hitNo] = hp [hitNo] + 16;}
Als (ontvangen [13] == 1) {hp [hitNo] = hp [hitNo] + 8;}
Als (ontvangen [14] == 1) {hp [hitNo] = hp [hitNo] + 4;}
Als (ontvangen [15] == 1) {hp [hitNo] = hp [hitNo] + 2;}
Als (ontvangen [16] == 1) {hp [hitNo] = hp [hitNo] + 1;}
pariteit [hitNo] = ontvangen [17];
Serial.Print ("No Hit:");
Serial.Print(hitNo);
Serial.Print ("speler:");
Serial.Print(Player[hitNo]);
Serial.Print ("Team:");
Serial.Print(team[hitNo]);
Serial.Print ("wapen:");
Serial.Print(Weapon[hitNo]);
Serial.Print ("HP:");
Serial.Print(HP[hitNo]);
Serial.Print ("pariteit:");
Serial.println(parity[hitNo]);
Dit is waarschijnlijk waar meer code moet worden toegevoegd aan de spel mogelijkheden uitbreiden op het moment dat de code slechts controleert dat de ontvangen gegevens niet een systeembericht en trekt af van een leven als het niet was.
Als (speler [hitNo]! = 0){hit();}
hitNo ++;
}
ongeldig shoot() {}
if(Fire == 1) {/ / heeft de trigger hebt gedrukt?
Serial.println ("brand 1");
sendPulse (IRtransmitPin, 4); Overbrengen van Header puls, stuur pulse subroutine behandelt de details
delayMicroseconds(IRpulse);
voor (int i = 0; ik < 8; i ++) {/ / verzenden Byte1
Als (byte1 [i] == 1) {}
sendPulse (IRtransmitPin, 1);
Serial.Print ("1");
}
else{Serial.Print ("0");}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
}
voor (int i = 0; ik < 8; i ++) {/ / verzenden Byte2
Als (byte2 [i] == 1) {}
sendPulse (IRtransmitPin, 1);
Serial.Print ("1");
}
else{Serial.Print ("0");}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
}
if(myParity == 1) {/ / pariteit
sendPulse (IRtransmitPin, 1);
}
sendPulse (IRtransmitPin, 1);
delayMicroseconds(IRpulse);
Serial.println("");
Serial.println ("gedaan 1");
}
if(Fire == 2) {/ / waar een secundaire vuur modus zou worden toegevoegd
Serial.println ("FIRE 2");
sendPulse (IRtransmitPin, 4); Koptekst
Serial.println ("gedaan 2");
}
BRAND = 0;
munitie = munitie - 1;
}
VOID sendPulse (int pin, int lengte) {/ / importeren van variabelen zoals dit maakt voor secundaire brand modi enz.
Dit void genertates de draaggolffrequentie voor de informatie die moet worden verstrekt
int i = 0;
int o = 0;
terwijl (ik < lengte) {}
i ++;
terwijl (o < IRpulses) {}
o ++;
digitalWrite (pin, hoge);
delayMicroseconds(IRt);
digitalWrite (pin, laag);
delayMicroseconds(IRt);
}
}
}
VOID triggers() {/ / wordt gecontroleerd als de triggers persen geweest
LTR = TR; Vorige status van de records. Primaire brand
LT2R = T2R; Vorige status van de records. Secundaire brand
TR = digitalRead(triggerPin); Huidige status van de knop van de trigger worden opgezocht
T2R = digitalRead(trigger2Pin); Huidige status van de knop van de trigger worden opgezocht
Code ziet er veranderingen in de trigger staat te geven het een semi automatische schieten gedrag
Als (TR! = LTR & & TR LOW ==) {}
BRAND = 1;
}
Als (T2R! = LT2R & & T2R == LOW) {}
BRAND = 2;
}
Als (TR == LOW & & automatische == 1) {}
BRAND = 1;
}
Als (T2R == LOW & & automatic2 == 1) {}
BRAND = 2;
}
Als (brand == 1 || BRAND == 2) {}
if(Ammo < 1) {brand = 0; noAmmo();}
if(Life < 1) {brand = 0; dead();}
Brand tarief code hier worden toegevoegd
}
}
VOID configureGame() {/ / waar het spel kenmerken zijn opgeslagen, kunt u verschillende spel types worden geregistreerd en u moet alleen één variabele (myGameID) te halen van het spel veranderen.
if(myGameID == 0) {}
myWeaponID = 1;
maxAmmo = 30;
munitie = 30;
maxLife = 3;
leven = 3;
myWeaponHP = 1;
}
if(myGameID == 1) {}
myWeaponID = 1;
maxAmmo = 100;
munitie = 100;
maxLife = 10;
leven = 10;
myWeaponHP = 2;
}
}
VOID frequencyCalculations() {/ / alle van de tijdsinstellingen die nodig zijn om de juiste draaggolffrequentie voor het infrarood signaal werkt
Metro = (int) (500/IRfrequency);
IRpulses = (int) (IRpulse / (2 * IRt));
Metro = IRt - 4;
Waarom-4 ik hoor huilen je. Het staat voor de tijd die nodig is voor de opdrachten worden uitgevoerd.
Meer info: http://j44industries.blogspot.com/2009/09/arduino-frequency-generation.html#more
Serial.Print ("Oscilation tijd periode /2:");
Serial.println(IRt);
Serial.Print ("pulsen:");
Serial.println(IRpulses);
timeOut = IRpulse + 50; 50 toe te voegen aan de verwachte pulse tijd geeft lezen een weinig marge voor fout aan de pols time-out waarde
}
VOID tagCode() {/ / werkt wat spelers muzikale (de code die wordt verstuurd wanneer ze schieten) is
byte1 [0] = myTeamID >> 2 & B1;
byte1 [1] = myTeamID >> 1 & B1;
byte1 [2] = myTeamID >> 0 & B1;
byte1 [3] = myPlayerID >> 4 & B1;
byte1 [4] = myPlayerID >> 3 & B1;
byte1 [5] = myPlayerID >> 2 & B1;
byte1 [6] = myPlayerID >> 1 & B1;
byte1 [7] = myPlayerID >> 0 & B1;
byte2 [0] = myWeaponID >> 2 & B1;
byte2 [1] = myWeaponID >> 1 & B1;
byte2 [2] = myWeaponID >> 0 & B1;
byte2 [3] = myWeaponHP >> 4 & B1;
byte2 [4] = myWeaponHP >> 3 & B1;
byte2 [5] = myWeaponHP >> 2 & B1;
byte2 [6] = myWeaponHP >> 1 & B1;
byte2 [7] = myWeaponHP >> 0 & B1;
myParity = 0;
for (int i = 0; ik < 8; i ++) {}
Als (byte1 [i] == 1) {myParity = myParity + 1;}
Als (byte2 [i] == 1) {myParity = myParity + 1;}
myParity = myParity >> 0 & B1;
}
Volgende paar regels afdrukken de volledige muzikale code.
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 ("pariteit:");
Serial.Print(myParity);
Serial.println();
}
VOID playTone (int Toon, int duur) {/ / een sub routine voor het afspelen van tonen als de standaard arduino melodie voorbeeld
voor (lang ik = 0; ik < duur * 1000L; ik += Toon * 2) {}
digitalWrite (speakerPin, hoge);
delayMicroseconds(tone);
digitalWrite (speakerPin, laag);
delayMicroseconds(tone);
}
}
VOID dead() {/ / void bepaalt wat de tagger doet wanneer het buiten leven
Maakt een paar geluiden en aantal verlichting knippert
for (int i = 1; ik < 254; i ++) {}
analogWrite(ammoPin, i);
playTone((1000+9*i), 2);
}
analogWrite (ammoPin, ((int) munitie));
analogWrite (lifePin, ((int) leven));
Serial.println("Dead");
for (int i = 0; ik < 10; i ++) {}
analogWrite (ammoPin, 255);
digitalWrite(hitPin,HIGH);
vertraging (500);
analogWrite (ammoPin, 0);
digitalWrite(hitPin,LOW);
vertraging (500);
}
}
VOID noAmmo() {/ / wat lawaai maken en flash enkele lichten wanneer ze buiten munitie
digitalWrite(hitPin,HIGH);
playTone (500, 100);
playTone(1000, 100);
digitalWrite(hitPin,LOW);
}
VOID hit() {/ / wat lawaai maken en enkele lichten knipperen als u krijgen schot
digitalWrite(hitPin,HIGH);
Life = leven - hp [hitNo];
Serial.Print ("leven:");
Serial.println(Life);
playTone (500, 500);
Als (leven < = 0){dead();}
digitalWrite(hitPin,LOW);
lifeDisplay();
}