Automated NERF Turret
Ik woon sinds kort op mijzelf samen met mijn broer, dus het leek mij leuk om iets van een beveiligingssysteem te maken voor ons nieuwe huis. Ik heb wat gebrainstormd en ik kwam op een paar ideeën. Mijn eerste idee was om iets te doen met 'laser tripwires' of iets vergelijkbaars. Een soort onzichtbare val wat audio liet afspelen. Toen ben ik iets meer rond gaan kijken door mijn huis om te kijken wat er allemaal nog meer was waar ik mee kon werken. Ik vond een doos met speelgoed en daarin zaten een aantal NERF geweren, waarvan er een vol-automatisch was met een hoge munitiecapaciteit. Ik en mijn broer zijn grote liefhebbers van militair materiaal, dus wist ik dat ik hier een autonome sentry turret mee wilde maken.
Het idee is dat de turret van links naar rechts draait, en door middel van een sensor kan zien of er iets voor hem staat. Wanneer het iemand ziet wordt de trekker overgehaald.
Supplies
1x NERF Havok Fire EBF-25
1x Arduino Uno
1x MG996R servomotor
1x FS90 micro servomotor
1x Regelbare Step-Up Module 3-34V naar 4-35V LM2577
1x Ultrasonic Sensor HC SR04
1x 9v Adapter
Jumper Cables
Female - Female Jumper Cables
Laser Diode 5v
Rope, not too thick
Superglue
Various tools (screwdriver, drill, nails and screws, etc.)
Various materials (wood, cardboard, etc.)
Duct Tape
Thin hard-plastic slat
Research
Het is de bedoeling dat het geweer op zichzelf doelwitten kan zoeken en "uitschakelen". De NERF Havok Fire EBF-25 is een zeer goede kandidaat vanwege zijn automatische vuurfunctie en een lange munitierits. Ik heb gekeken naar wat er zoal mogelijk is met Arduino. Ik heb ook gezocht naar andere projecten waarin mensen een turret hebben gemaakt. In deze projecten gebruikten ze echter materiaal en componenten die te duur waren voor mij (zoals servo's van 40,- en cams van 90,-), dus heb ik naar kleinere en goedkopere opties gezocht. Ook brachten mensen in deze projecten permanente aanpassingen toe aan de NERF guns zelf, wat ik niet wilde doen om de originele staat te behouden. Ik heb toen zitten brainstormen voor manieren om hier omheen te komen.
Links voor de inspiratie-projecten:
https://www.instructables.com/Nerf-Vulcan-Sentry-G...
https://www.instructables.com/Auto-Turret-With-Pix...
https://www.instructables.com/Raspberry-Pi-Motion-...
Na wat onderzoek en gesprekken met medestudenten ben ik erachter gekomen wat ik nodig heb; een servomotor om de turret heen en weer te laten bewegen, een servomotor om de trekker over te halen en een ultrasoon sensor om objecten te vinden binnen een bepaalde afstand recht voor de turret.
MG996R Servo Aansluiten Aan Arduino
Op de foto met de groene mat is de eerste setup van de servo te zien, waarbij deze met 180 graden heen en weer draait. Let op: er zit hier nog geen 9 volt adapter en regulator tussen. Deze zijn nodig om de juiste hoeveelheid stroom naar de servo te vervoeren. De Arduino geeft standaard 5v, en de servo heeft 7v nodig.
In mijn project zitten de GND en de Vin vast gesoldeerd aan de regulator. Uit de regulator komen weer 2 kabels die naar de + en de - van de servo gaan. Dit is de stroomtoevoer. De servo zit in de Arduino vast aan pin 9.
Om te testen of de servo werkt kan je het stukje code hieronder gebruiken wat de servo heen en weer laat draaien.
#include <Servo.h> Servo servo1; int servo_position = 0; void setup() { servo1.attach(9); } void loop() { for (servo_position = 0; servo_position <=180; servo_position +=1) { servo1.write(servo_position); delay(10); } for (servo_position = 180; servo_position <=0; servo_position -=1) { servo1.write(servo_position); delay(10); } }<br>
Platform Rotatie (poging 1)
Mijn eerste schematic was een goed idee in mijn hoofd, maar op dit punt van het project wist ik nog niet precies wat de technische limitaties waren, voornamelijk die van de MG996R servo (de grote zwarte). Deze servo zou de hele basis moeten dragen en ronddraaien. Het gewicht was echter veel te zwaar (zie video), en het geweer stond er nog niet eens op. Hieruit concludeerde ik dat de basis lichter moest worden, en dat ik het gewicht ergens anders op moest laten vallen, en dat de servo enkel de beweging moest maken.
Platform Rotatie (poging 2)
Na de eerste poging ben ik erop gekomen om de servo de basis te laten trekken. Het idee was om 2 touwen te spannen, vastgebonden aan de onderkant van de plank. Het touw loopt door oogjes om het mooi op de plaats te houden. Deze touwen worden bevestigd aan de servo, en door de draaiende beweging worden de touwen een voor een strakgetrokken, wat ervoor zorgt dat de plank heen en weer draait. De eerste iteratie hiervan was in het klein getest met een stukje karton.
Nadat het prototype werkte heb ik de servo eraan vastgemaakt, en het ongeladen platform kan bewogen worden zonder dat de servo problemen heeft. Ik heb wel wat extra steun nodig voor de touwen, want het hangt nog iets te los.
Een ander probleem is dat het platform nu doorhangt aan de uiteinden omdat het een dunnere plaat is. Ik moet wat ondersteuning vinden wat deze delen omhoog houdt, maar het draaien niet belemmerd.
Deze ondersteuning zijn vier wieltjes. Deze houden de plank stevig recht en laten het vloeiender heen en weer bewegen.
Ik ben er echter achter gekomen dat het platform met een beladen gewicht moeizaam beweegt, en de draaicirkel is heel klein. Hier maak ik nog wat iteraties voor.
Platform Rotatie (poging 3)
Dit zijn mijn laatste paar iteraties voor het roteren van de turret. In plaats van de touwen onder aan de basis te bevestigen heb ik ze naar buiten laten wijzen, en komen ze terug naar de servo aan de achterkant. Hierdoor ontstaat er een soort katrol-systeem wat het gewicht meer verdeeld, waardoor de servo minder hoeft te trekken.
De eerste iteratie is een latje van hout waar de touwen aan zijn vastgebonden. Hij kan de turret heen en weer trekken, maar de gipsplaat is te zwak om de servo op zijn plaats te houden. Ik heb het geprobeerd met schroeven en veel duct tape. Later heb ik een sterkere houten plank geregeld. Deze hield de servo wel op de plaats, maar daardoor bleek het dat de servo het toch net niet aankan.
De tweede iteratie is een dun metalen latje. Deze werkte hetzelfde als de houten lat maar het lukte ook niet om beweging in de turret te krijgen.
De laatste iteratie is een hard-plastic latje die is vastgelijmd aan de servo. De touwen zitten aan de uiteindes vastgeknoopt. Deze staat op een houten verhoging geschroefd om niet in de knoop te raken met de turret-base. Dit latje was heel stevig en de gewichtsverdeling was goed. Om de afstand te overbruggen van de Arduino naar de achterkant van de turret-base heb ik female-female jumper cables gebruikt.
FS90 Micro Servo Trigger-Action
Mijn plan was om de trekker over te halen met de micro servo. Ik had er even over nagedacht en ik kwam er al snel achter dat het de beste optie zou zijn om een touw vast te binden aan de servo, en deze om de trekker heen te spannen. Wanneer de servo 90 graden draait wordt het touw strak getrokken en wordt de trekker overgehaald. Ik heb een dun, stevig touw gebruikt zodat het makkelijk aan de servo en de trekker gebonden kan worden.
Ik was bang dat de servo niet sterk genoeg was om de trekker over te halen. Gelukkig is de trekker heel gevoelig waardoor er nauwelijks kracht nodig is om het over te halen.
Deze servo zit in de Arduino vast aan pin 11, de GND en de 5V pins. Om de afstand te overbruggen van de Arduino naar de loop heb ik de kabels verlengd met female-female jumper cables.
Zorg dat het touw strak staat tussen de servo en de trekker. De servo moet in zijn 0-positie staan. Ik heb het draad om de trekker heen gelust en door zichzelf heen gestoken, en daarna de lus vastgeplakt aan het handvat.
Ultrasone Sensor
Ik heb een ultrasoon sensor gebruikt om de turret te laten 'kijken'. Het moeilijkste was de sensor laten werken met de servo's. Het is namelijk de bedoeling dat deze sensor de 'aansturing' is van de functies van de turret.
De zwarte servo moet 180 graden draaien totdat de sensor iets ziet. Op dat moment moet de servo stoppen. Wanneer de sensor geen zicht meer heeft draait de servo weer verder. De blauwe servo moet 90 graden draaien wanneer de sensor iets ziet om zo de trekker over te halen. Deze draait weer terug wanneer de sensor het doelwit verliest.
De sensor zit in de Vcc en de GND, de Echo pin zit in A0 en de Trig pin zit in de 4 van de Arduino.
Afwerking
Om de bedradingmooi weg te werken heb ik inspiratie gehaald uit de Taurus Raging Bul revolver. Deze revolver heeft in tegenstelling tot normale pistool-lopen een brede loop wat een meer robuuste uitstraling heeft. Vrijwel alle kabels liggen bij de loop van de turret, dus ik heb met camouflagepatronen dit deel dicht gemaakt waardoor ook mijn turret een robuust uiterlijk krijgt.
Ik heb een camouflagepatroon gemaakt in dezelfde tinten als het geweer zelf om de stijl te bewaren. De voorkant heeft een klep waardoor de Arduino en de bedrading toegankelijk zijn. Natuurlijk zit er ook een opening in de voorkant voor de ultrasone sensor. Als finishing touch heb ik een rode laser aan de loop gemonteerd. Deze laser zit in de 3.3v en de GND in de Arduino.
Je kan de afwerking maken zoals je wilt. Wees creatief, dat deed ik ook! Zolang je maar niks meer van de kabeltjes ziet.
Elektronische Schema
Het geheel wordt van stroom voorzien door een 9v adapter. Omdat de zwarte servo niet meer aankan dan 7v heb ik een regulator tussen de servo en de Arduino verbonden om de stroomtoevoer te reguleren. De blauwe servo en de ultrasone sensor zitten wel direct aan de Arduino verbonden.
Code (met Notities)
Ik heb deze code zelf geschreven, maar ik heb wel hulp gekregen van mensen die meer bekend zijn met code. Zo heeft Yannick Mul (1A) mij geholpen met bug fixing en de correcte communicatie tussen de ultrasone sensor en de MG996R servo, en Wido Beukhof (1A) heeft mij uitgelegd hoe de ultrasone sensor werkt en hoe die code eruit moet zien.
De code van de ultrasone sensor is gebaseerd op een tutorial van Arbi Abdul Jabbaar op Project Hub (https://create.arduino.cc/projecthub/abdularbi17/ultrasonic-sensor-hc-sr04-with-arduino-tutorial-327ff6)
#include <Servo.h> Servo bigServo; // servo object voor servo (zwart) Servo trigger; // servo object voor servo (blauw) bool enemy = false; // boolean voor enemy int val = 0; // variabele die assisteert bij de waarde van de "enemy", deze geeft 0 of 1 aan. 0 is geen enemy, 1 is wel enemy int pos = 0; // variable om de positie van de zwarte servo op te slaan // variabelen servo (zwart) int current_pos; int previous_pos = 0; const int trigPin = 4; // verbindt sensor trigger met pin 4 const int echoPin = A0; // verbindt sensor echo met pin A0 // variabelen sensor long duration; int distance; void setup() { bigServo.attach(9); // verbindt servo (zwart) met pin 9 trigger.attach(11); // verbindt servo (blauw) met pin 11 trigger.write(0); // servo (blauw) staat op 0 // sensor pinMode(trigPin, OUTPUT); // zet trigPin als output pinMode(echoPin, INPUT); // zet echoPin als input Serial.begin(9600); // start de serial communication } void loop() { // Wanneer er geen 'enemy' gezien wordt door de sensor beweegt de zwarte servo 180 graden heen en weer. De waarde 'val' is dan 0, en enemy = false. // Zodra de distance kleiner is dan 50 cm wordt de waarde 'val' 1, waardoor enemy = true wordt, en de loop wordt onderbroken (break). // Na een break, bij het verlies van 'enemy', gaat de zwarte servo weer verder vanaf het punt waar het was gestopt. Deze waarde is opgeslagen in de variabele 'pos'. // De eerste line "if (enemy == false)" hoort bij de 3 delen code die hierna volgen. De zwarte servo heeft 2 delen, en de blauw 1 deel. if (enemy == false) { for (current_pos = previous_pos; current_pos <= 180; current_pos += 2) { bigServo.write(current_pos); previous_pos = current_pos; if (distance <= 50) { val = 1; } else { val = 0; } if (val == 1) { enemy = true; } if (val == 0) { enemy = false; } if (enemy == true) { break; } // sensor digitalWrite(trigPin, LOW); // zet trigPin op LOW voor 2 ms delayMicroseconds(2); digitalWrite(trigPin, HIGH); // zet de trigPin op HIGH voor 10 ms delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); // leest de echoPin, stuurt reistijd van de geluidsgolven terug in microsecondes distance = (duration * 0.0343) / 2; // berekening van de afstand d.m.v. geluid delay(15); // wacht 15ms voor de servo om zijn positie te bereiken // Prints in the Serial Monitor Serial.print("Distance: "); Serial.println(distance); Serial.print("Val: "); Serial.println(val); Serial.print("Enemy: "); Serial.println(enemy); } // De code vanaf hier is hetzelfde als bovenstaand, maar dan voor de tegenovergestelde draairichting van de zwarte servo. for (current_pos = previous_pos; current_pos >= 0; current_pos -= 2) { bigServo.write(current_pos); previous_pos = current_pos; if (distance <= 50) { val = 1; } else { val = 0; } if (val == 1) { enemy = true; } if (val == 0) { enemy = false; } if (enemy == true) { break; } // sensor digitalWrite(trigPin, LOW); // zet trigPin op LOW voor 2 ms delayMicroseconds(2); digitalWrite(trigPin, HIGH); // zet de trigPin op HIGH voor 10 ms delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); // leest de echoPin, stuurt reistijd van de geluidsgolven terug in microsecondes distance = (duration * 0.0343) / 2; // berekening van de afstand d.m.v. geluid delay(15); // wacht 15ms voor de servo om zijn positie te bereiken // Prints in the Serial Monitor Serial.print("Distance: "); Serial.println(distance); Serial.print("Val: "); Serial.println(val); Serial.print("Enemy: "); Serial.println(enemy); } } // Dit gedeelte is voor de trekker. Hier wordt bij het zien van een 'enemy' binnen 50 cm de waarde opgeteld met 1. Wanneer 'val' 3 of hoger is wordt enemy = true. Onder de 3 is enemy = false. // Wanneer enemy = true, wordt de blauwe servo met 90 graden gedraaid. Op enemy = false gaat deze weer terug naar 0. else { if (distance <= 50) { val++; } else { val = 0; } if (val >= 3) { enemy = true; } if (val < 3) { enemy = false; } trigger.write(90); delay(100); trigger.write(0); // sensor digitalWrite(trigPin, LOW); // zet trigPin op LOW voor 2 delayMicroseconds(2); digitalWrite(trigPin, HIGH); // zet de trigPin op HIGH voor 10 ms delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); // leest de echoPin, stuurt reistijd van de geluidsgolven terug in microsecondes distance = (duration * 0.0343) / 2; // berekening van de afstand d.m.v. geluid } }
Een Paar Processfoto's
Ik voelde me wel een behoorlijke doe-het-zelf'er tijdes dit project. Het was wennen maar ik vond het heel leuk. Hier zijn nog wat willekeurige processfoto's van mijn project.
Reflectie
Ik vond dit een heel lastig project. Al het technische inzicht en de uitvoering was moeilijk om te leren en uit te voeren. Ik ben ook gedurende het project van probleem naar probleem gegaan. Voor iedere oplossing of idee waar ik mee kwam was er wel een obstakel of complicatie wat mij weer op een halt bracht. Ik ben wel blij met deze les in fysieke prototypes maken. Ik had nooit gedacht dat mij dit zou lukken en daardoor is het nog leuker dat er goed uit is gekomen. Ik ben trots op wat ik gemaakt heb.
Een belangrijke les die ik heb geleerd is dat het altijd goed is om voorbereid te zijn, vooral bij dit soort projecten waar veel verschillende materialen voor nodig zijn. Mijn plannen op papier zijn in mijn hoofd heel anders dan dat ze in de praktijk zijn, en zo ben ik vaak tegen problemen en tijdsverlies aan gelopen omdat ik de juiste materialen niet voor handen had. Ik ga dit onthouden voor al mijn projecten in de toekomst om efficiënter te kunnen werken.