Introduction: Mini Crossbow Controlled by Joystick Shield

About: RAS is the IEEE chapter that brings together students interested in emigrating knowledge in robotics, in the tangent and intersection areas, as well as creating and realizing ideas and projects for the enterta…

In this project we made a mini crossbow made in 3d printer controlled by a joystick shield compatible with Arduino

Step 1: Materials

  1. Intel Edison
  2. Arduino Expansion Board
  3. Joystick Shield v2.4
  4. 3 servo motors
  5. 9 jumpers
  6. Hot melt glue gun
  7. Safety match
  8. 2 metal hair clips
  9. rubber band

Step 2: Make Crossbow in 3d Printer

Print and mount the mini crossbow. The trigger is held in place with a 2/56" x 1/2" screw and it uses metal hair clips for the bow and Q-tips for the crossbow bolts.

The center of the hair clip was removed by just bending it back and forth a few times to snap it off and then the clips are just slid into the cut outs.

It can also be built with Popsicle sticks, has many tutorials on the internet teaching to do so. You only need to have a mechanical trigger that will be controlled by turning the servo motor.

Fix the motors, one for controlling the x axis, the other to control the y axis and third to control the trigger.

Step 3: The Code

/**
*  Mini Crossbow controlled by joystick shield v2.4
*  by RAS IEEE UFABC - 11/07/2015
*/  
#include <Servo.h><br><br>Servo servo_hor;
Servo servo_vert;
Servo servo_trig;<br>
#define LOG Serial.print
#define bt_change 4
#define bt_fire 2
#define led_log 13
#define servo_trig_start 90
#define servo_trig_end 0
#define analog_x 0
#define analog_y 1
#define time_shoot 700
#define time_execution 0

unsigned long running_time = 0;<br>boolean open_fire = 0;
int status_ = 2;
int bow_pos[2] = {90, 125}; // {servo_hor, servo_vert}
void setup() {

	pinMode(analog_x, INPUT_PULLUP);   <br>	pinMode(analog_y, INPUT_PULLUP);
	pinMode(bt_change, INPUT);
	pinMode(bt_fire, INPUT);

	Serial.begin(115200);

	servo_hor.attach(6);
	servo_vert.attach(5);
	servo_trig.attach(3);

	servo_hor.write(90);
	delay(300);
	servo_vert.write(125);
	delay(300);
	servo_trig.write(servo_trig_start);
	delay(300);

}
void loop() {

	if (!digitalRead(bt_change)) {
		(status_ >= 2) ? status_ = 0 : status_++;
		digitalWrite(led_log, 1);
		delay(50);
		digitalWrite(led_log, 0);
		delay(50);
		digitalWrite(led_log, 1);
		delay(50);
		digitalWrite(led_log, 0);
		delay(50);
	}

	switch (status_) {

		case 0:	      // servo horizontal adjust
			bow_pos[0] = analogRead(analog_x);
			bow_pos[0] = map(bow_pos[0], 0, 1023, 0, 179);
			break;
		case 1:	      // servo vertical adjust
			bow_pos[1] = analogRead(analog_y);
			bow_pos[1] = map(bow_pos[1], 0, 1023, 100, 150);
			break;
		default:	  // stoped
			if (!digitalRead(bt_fire)) {
				open_fire = true;
				delay(150);
			}
			break;
	}

	if (millis() - running_time > time_execution) {
			servo_hor.write(bow_pos[0]);
			servo_vert.write(bow_pos[1]);
		if (open_fire) {
			servo_trig.write(servo_trig_end);
			delay(time_shoot);
			servo_trig.write(servo_trig_start);
			delay(time_shoot);
			open_fire = !open_fire;
		}
		running_time = millis();<br>	}<br>	LOG("EixoX -> motor: ");
	LOG(bow_pos[0]);
	LOG("\n");
	LOG("EixoY -> Servo: ");
	LOG(bow_pos[1]);
	LOG("\n");
	LOG("Button Change: ");
	LOG(status_);
	LOG("\n");
	LOG ("Button Fire: ");
	LOG(open_fire);
	LOG("\n");
}