Devices & Components
Arduino Nano
1.5mm metal rod
dupont connectors
heatshrink tubing
2.1x5.5mm jack plug
wires
resistors 330Ω
resistors 680Ω
20mm rubber band
M2x10 self taping screws
FR207 rectifier diode
M5*20 countersunk screw
RFP30N06LE mosfet
9V power supply (2.5 amps minimum)
HC-05 Bluetooth module
MG-90s servos
resistors 10kΩ
LM2596 buck converter
type 130 dc motors
Hardware & Tools
3D printer
pliers
soldering iron
wire stripper
screwdriver
crimping tool
multimeter
Software & Tools
Windows 10
Project description
Code
Arduino code
arduino
code to upload to the arduino . The code remain the same whether you choose to control the turret via the android app or a PC .
1#include <Servo.h> 2 3//-----Declare servos and variables 4Servo recoil_servo; 5Servo pan_servo; 6Servo tilt_servo; 7 8const byte pan_limit_1 = 0; 9const byte pan_limit_2 = 180; 10const byte tilt_limit_1 = 65; 11const byte tilt_limit_2 = 180; 12const byte recoil_rest = 180; // Angle of the servo when at rest 13const byte recoil_pushed = 125; // Angle the servo need to reach to push the dart 14 15//-----Variables related to serial data handling 16byte byte_from_app; 17const byte buffSize = 30; 18byte inputBuffer[buffSize]; 19const byte startMarker = 255; 20const byte endMarker = 254; 21byte bytesRecvd = 0; 22boolean data_received = false; 23 24//-----Variable related to motor timing and firing 25bool is_firing = false; 26bool can_fire = false; 27bool recoiling = false; 28 29unsigned long firing_start_time = 0; 30unsigned long firing_current_time = 0; 31const long firing_time = 150; 32 33unsigned long recoil_start_time = 0; 34unsigned long recoil_current_time = 0; 35const long recoil_time = 2 * firing_time; 36 37const byte motor_pin = 12; 38boolean motors_ON = false; 39 40//8===========================D 41 42void setup() 43{ 44 //-----define motor pin mode 45 pinMode(motor_pin, OUTPUT); 46 digitalWrite(motor_pin, LOW); 47 48 //-----attaches servo to pins 49 recoil_servo.attach(9); 50 pan_servo.attach(10); 51 tilt_servo.attach(11); 52 53 //-----starting sequence 54 recoil_servo.write(recoil_rest); 55 pan_servo.write(90); 56 delay(1000); 57 tilt_servo.write(105); 58 59 60 Serial.begin(9600); // begin serial communication 61} 62 63//8===========================D 64 65void loop() 66{ 67 getDataFromPC(); 68 set_motor(); 69 if (data_received) { 70 move_servo(); 71 set_recoil(); 72 set_motor(); 73 } 74 fire(); 75} 76 77//8===========================D 78 79void getDataFromPC() { 80 81 //expected structure of data [start byte, pan amount, tilt amount, motor on, firing button pressed, end byte] 82 //start byte = 255 83 //pan amount = byte between 0 and 253 84 //tilt amount = byte between 0 and 253 85 //motor on = 0 for off - 1 on 86 //firing button pressed = 0 for not pressed - 1 for pressed 87 //end byte = 254 88 89 if (Serial.available()) { // If data available in serial 90 91 byte_from_app = Serial.read(); //read the next character available 92 93 if (byte_from_app == 255) { // look for start byte, if found: 94 bytesRecvd = 0; //reset byte received to 0(to start populating inputBuffer from start) 95 data_received = false; 96 } 97 98 else if (byte_from_app == 254) { // look for end byte, if found: 99 data_received = true; // set data_received to true so the data can be used 100 } 101 102 else { // add received bytes to buffer 103 inputBuffer[bytesRecvd] = byte_from_app; //add character to input buffer 104 bytesRecvd++; // increment byte received (this act as an index) 105 if (bytesRecvd == buffSize) { // just a security in case the inputBuffer fills up (shouldn't happen) 106 bytesRecvd = buffSize - 1; // if bytesReceived > buffer size set bytesReceived smaller than buffer size 107 } 108 } 109 } 110} 111 112//8===========================D 113 114void move_servo() { 115 116 byte pan_servo_position = map(inputBuffer[0], 0, 253, pan_limit_2, pan_limit_1);//convert inputbuffer value to servo position value 117 pan_servo.write(pan_servo_position); //set pan servo position 118 byte tilt_servo_position = map(inputBuffer[1], 0 , 253, tilt_limit_2, tilt_limit_1); //convert inputbuffer value to servo position value 119 tilt_servo.write(tilt_servo_position); //set pan servo position 120} 121 122//8===========================D 123 124void set_recoil() { 125 126 if (inputBuffer[3] == 1) { //if fire button pressed 127 if (!is_firing && !recoiling) { //and not already firing or recoiling 128 can_fire = true; //set can fire to true (see effect in void fire()) 129 } 130 } 131 else { // if fire button not pressed 132 can_fire = false; //set can fire to false (see effect in void fire()) 133 } 134} 135 136//8===========================D 137 138void set_motor() { 139 //-----start and stop motors using MOSFET transisitor . 140 141 if (inputBuffer[2] == 1) { //if screen touched 142 digitalWrite(motor_pin, HIGH); //turn motor ON 143 motors_ON = true; 144 } 145 else { //if screen not touched 146 digitalWrite(motor_pin, LOW); //turn motor OFF 147 motors_ON = false; 148 149 } 150} 151 152//8===========================D 153 154void fire() { //if motor byte on, turn motor on and check for time it has been on 155 156 if (can_fire && !is_firing && motors_ON) { 157 //if (can_fire && !is_firing) { 158 firing_start_time = millis(); 159 recoil_start_time = millis(); 160 is_firing = true; 161 } 162 163 firing_current_time = millis(); 164 recoil_current_time = millis(); 165 166 if (is_firing && firing_current_time - firing_start_time < firing_time) { 167 recoil_servo.write(recoil_pushed); 168 } 169 else if (is_firing && recoil_current_time - recoil_start_time < recoil_time) { 170 recoil_servo.write(recoil_rest); 171 } 172 else if (is_firing && recoil_current_time - recoil_start_time > recoil_time) { 173 is_firing = false; 174 } 175 176} 177
python files
The executable and android app can be found here : https://www.littlefrenchkev.com/bluetooth-nerf-turret
Arduino code
arduino
code to upload to the arduino . The code remain the same whether you choose to control the turret via the android app or a PC .
1#include <Servo.h> 2 3//-----Declare servos and variables 4Servo 5 recoil_servo; 6Servo pan_servo; 7Servo tilt_servo; 8 9const byte pan_limit_1 10 = 0; 11const byte pan_limit_2 = 180; 12const byte tilt_limit_1 = 65; 13const 14 byte tilt_limit_2 = 180; 15const byte recoil_rest = 180; // Angle of the servo 16 when at rest 17const byte recoil_pushed = 125; // Angle the servo need to reach 18 to push the dart 19 20//-----Variables related to serial data handling 21byte 22 byte_from_app; 23const byte buffSize = 30; 24byte inputBuffer[buffSize]; 25const 26 byte startMarker = 255; 27const byte endMarker = 254; 28byte bytesRecvd = 0; 29boolean 30 data_received = false; 31 32//-----Variable related to motor timing and firing 33bool 34 is_firing = false; 35bool can_fire = false; 36bool recoiling = false; 37 38unsigned 39 long firing_start_time = 0; 40unsigned long firing_current_time = 0; 41const long 42 firing_time = 150; 43 44unsigned long recoil_start_time = 0; 45unsigned long 46 recoil_current_time = 0; 47const long recoil_time = 2 * firing_time; 48 49const 50 byte motor_pin = 12; 51boolean motors_ON = false; 52 53//8===========================D 54 55void 56 setup() 57{ 58 //-----define motor pin mode 59 pinMode(motor_pin, OUTPUT); 60 61 digitalWrite(motor_pin, LOW); 62 63 //-----attaches servo to pins 64 recoil_servo.attach(9); 65 66 pan_servo.attach(10); 67 tilt_servo.attach(11); 68 69 //-----starting sequence 70 71 recoil_servo.write(recoil_rest); 72 pan_servo.write(90); 73 delay(1000); 74 75 tilt_servo.write(105); 76 77 78 Serial.begin(9600); // begin serial communication 79} 80 81//8===========================D 82 83void 84 loop() 85{ 86 getDataFromPC(); 87 set_motor(); 88 if (data_received) { 89 90 move_servo(); 91 set_recoil(); 92 set_motor(); 93 } 94 fire(); 95} 96 97//8===========================D 98 99void 100 getDataFromPC() { 101 102 //expected structure of data [start byte, pan amount, 103 tilt amount, motor on, firing button pressed, end byte] 104 //start byte = 255 105 106 //pan amount = byte between 0 and 253 107 //tilt amount = byte between 0 and 108 253 109 //motor on = 0 for off - 1 on 110 //firing button pressed = 0 for not 111 pressed - 1 for pressed 112 //end byte = 254 113 114 if (Serial.available()) { 115 // If data available in serial 116 117 byte_from_app = Serial.read(); //read 118 the next character available 119 120 if (byte_from_app == 255) { // look 121 for start byte, if found: 122 bytesRecvd = 0; //reset byte 123 received to 0(to start populating inputBuffer from start) 124 data_received 125 = false; 126 } 127 128 else if (byte_from_app == 254) { // look for end 129 byte, if found: 130 data_received = true; // set data_received 131 to true so the data can be used 132 } 133 134 else { // 135 add received bytes to buffer 136 inputBuffer[bytesRecvd] = byte_from_app; //add 137 character to input buffer 138 bytesRecvd++; // 139 increment byte received (this act as an index) 140 if (bytesRecvd == buffSize) 141 { // just a security in case the inputBuffer fills up (shouldn't happen) 142 143 bytesRecvd = buffSize - 1; // if bytesReceived > buffer size set bytesReceived 144 smaller than buffer size 145 } 146 } 147 } 148} 149 150//8===========================D 151 152void 153 move_servo() { 154 155 byte pan_servo_position = map(inputBuffer[0], 0, 253, 156 pan_limit_2, pan_limit_1);//convert inputbuffer value to servo position value 157 158 pan_servo.write(pan_servo_position); //set pan servo position 159 byte tilt_servo_position 160 = map(inputBuffer[1], 0 , 253, tilt_limit_2, tilt_limit_1); //convert inputbuffer 161 value to servo position value 162 tilt_servo.write(tilt_servo_position); //set 163 pan servo position 164} 165 166//8===========================D 167 168void set_recoil() 169 { 170 171 if (inputBuffer[3] == 1) { //if fire button pressed 172 if 173 (!is_firing && !recoiling) { //and not already firing or recoiling 174 can_fire 175 = true; //set can fire to true (see effect in void fire()) 176 } 177 178 } 179 else { // if fire button not pressed 180 can_fire = 181 false; //set can fire to false (see effect in void fire()) 182 } 183} 184 185//8===========================D 186 187void 188 set_motor() { 189 //-----start and stop motors using MOSFET transisitor . 190 191 192 if (inputBuffer[2] == 1) { //if screen touched 193 digitalWrite(motor_pin, 194 HIGH); //turn motor ON 195 motors_ON = true; 196 } 197 else { //if 198 screen not touched 199 digitalWrite(motor_pin, LOW); //turn motor OFF 200 201 motors_ON = false; 202 203 } 204} 205 206//8===========================D 207 208void 209 fire() { //if motor byte on, turn motor on and check for time it has been on 210 211 212 if (can_fire && !is_firing && motors_ON) { 213 //if (can_fire && !is_firing) 214 { 215 firing_start_time = millis(); 216 recoil_start_time = millis(); 217 218 is_firing = true; 219 } 220 221 firing_current_time = millis(); 222 recoil_current_time 223 = millis(); 224 225 if (is_firing && firing_current_time - firing_start_time < 226 firing_time) { 227 recoil_servo.write(recoil_pushed); 228 } 229 else if (is_firing 230 && recoil_current_time - recoil_start_time < recoil_time) { 231 recoil_servo.write(recoil_rest); 232 233 } 234 else if (is_firing && recoil_current_time - recoil_start_time > recoil_time) 235 { 236 is_firing = false; 237 } 238 239} 240
python files
The executable and android app can be found here : https://www.littlefrenchkev.com/bluetooth-nerf-turret
Downloadable files
HC-05 Bluetooth module wiring
Here is the HC-05 Bluetooth wiring . This piece of wiring include a voltage divider to allow the 5V coming out of the arduino to be stepped down to about 3.3V for the HC-05 Receiver pin .
HC-05 Bluetooth module wiring

wiring main diagram
Here is the main wiring diagram . The wiring is divided small sectionS linked together using dupont connectors . This is for ease of assembly .
wiring main diagram

HC-05 Bluetooth module wiring
Here is the HC-05 Bluetooth wiring . This piece of wiring include a voltage divider to allow the 5V coming out of the arduino to be stepped down to about 3.3V for the HC-05 Receiver pin .
HC-05 Bluetooth module wiring

Comments
Only logged in users can leave comments