Project Goals

The goal of the project was to create a device that could fire small projectiles into three seperate containers. Mechanical limitations:

  • Built from lego, including motors and sensors
  • Must shoot at least two meters
  • Minimum scanning area of 180 degrees
  • Find up to three seperate targets and gauge the distance and torque required
  • Before firing, user confirmation is necessary

Software limitations:

  • C programming language with husarion/lego libraries
  • The microcontroller is a husarion RoboCore
  • Must take the input from the sensor and decide where potential targets lie
  • Calculate required torque for a given distance
  • Three operating modes(Auto, Manual and Calibration)

Design

The robot is made up of 3 motors, 1 ultrasonic sensor, 1 press button and 1 RoboCORE. Two motors are used in tandem to increase the firing torque, which helps with the precision of shots as well as increasing the range. The third motor provides the rotation of the firing lever and scanner.

The button serves two purposes. The first is as an endstop. The endstop is used to set the zero position during initialization of the catapult and to later recalibrate the printer as we found the motors can be unreliable. The second function is as a user confirmation before tasks such as firing projectiles that can result in serious injury or even death; use of plastic balls is strongly advised.

To prevent damage to the pieces during firing, rubber dampers are provided where there is contact.

Auto Mode

The auto mode includes a 180deg scan before deciding how many boxes there before and firing to each with user confirmation.

Manual Mode

The user inputs the angle of shot and distance of target. The rest is computed by the robot.

Calibration Mode

Allows easy calibration of most parameters.

Below you will found the code. #include <stdio.h>
#include <hFramework.h> #include <math.h> #include <Lego_Ultrasonic.h> #include "Lego_Touch.h" #define iMeas 190 #define tick 5 #define maxSens 225 //Maximum distance of target #define goldilock 5 //Range of distance of target #define minLen 5 //Minimum number of measurements to count as target void calibrationMode(); void autoMode(); void manualControl(); void setLever(); void setAbs(); void proximityScan(); void systemScan(); void targetingAndFire(); void calibrate(); void calibrationPhase(); void fire(int); void confirmPress(); void rotateAngle(int); int setPower(int); using namespace hSensors; Lego_Ultrasonic sens(hSens1); Lego_Touch sensor(hSens2); int dist[iMeas]; int box[4]={0,0,0,0}; void hMain(void){ printf("\r\n\n------Lady Fist Fire is getting ready, please hold------\r\n\n"); calibrate(); setAbs(); printf("\r\nWe are ready to get going, what mode would you like to enter?"); for (;;){ if (hBtn1.isPressed() == true){ sys.delay(500); if (hBtn2.isPressed() == true) {calibrationMode();} else {manualControl();} } if (hBtn2.isPressed() == true) {autoMode();} } } void setLever(){ hMot2.setPower(-200); hMot3.setPower(-200); sys.delay(180); hMot2.setPower(0); hMot3.setPower(0); } void proximityScan(){ printf("\r\n\n*****Starting Scan*****\r\n\n"); for (int i=0; i<iMeas; i++){ hMot6.rotRel(tick,600); sys.delay(100); dist[i] = sens.readDist(); printf("%d | ", dist[i]); } printf("\r\n\n*****Scan Finished*****\r\n\n"); } //Calculate potential boxes and parameters void systemScan(){ printf("\r\n\n*****Starting Calculations*****\r\n\n"); int n = 1; //Iterator int k = 0; //Iterator for (int j=0; j<iMeas; j++){ if((dist[j] < maxSens)&&(abs(dist[j] - dist[j+1]) < goldilock)){ k=1; printf("Found Potential Box"); while(abs(dist[j+k] - dist[j+k+1]) < goldilock){k++;} printf("\r\nLength(k) = %d, j = %d\r\n",k,j); if(k>minLen){ box[n]= (k/2)+j; n++; } j += k; } } printf("\r\n\n*****Calculations finished*****\r\n\n"); } int setPower(int dist){ int pow = 0; if (dist<=10){pow = 450;} else if (dist<=20){pow = 480;} else if (dist<=30){pow = 485;} else if (dist<=40){pow = 520;} else if (dist<=50){pow = 530;} else if (dist<=60){pow = 550;} else if (dist<=70){pow = 580;} else if (dist<=80){pow = 590;} else if (dist<=90){pow = 620;} else if (dist<=100){pow = 625;} else if (dist<=110){pow = 665;} else if (dist<=120){pow = 695;} else if (dist<=130){pow = 710;} else if (dist<=140){pow = 730;} else if (dist<=150){pow = 760;} else if (dist<=180){pow = 825;} else if (dist<=200){pow = 900;} else if (dist<=210){pow = 930;} else if (dist<=250){pow = 1000;} return pow; } void rotateAngle(int ang){ hMot6.rotRel(ang*5.65,400); } void confirmPress(){ int wait = 0; printf("Press the button to continue"); while(wait == 0){ LED1.toggle(); sys.delay(100); if (sensor.isPressed() == true) {wait = 1;} if (hBtn1.isPressed() == true) {rotateAngle(10);} if (hBtn2.isPressed() == true) {rotateAngle(-10);} } } void targetingAndFire(){ setAbs(); int pow = 0; //Shoot to targets for (int n=1;n<4;n++){ if (box[n] != 0){ printf("Rotation ticks %d\r\n",(tick*(box[n]-box[n-1]))); hMot6.rotRel((tick*(box[n]-box[n-1])),500); setLever(); printf("<<<ARMED>>>"); pow = setPower(dist[box[n]]); printf("Box[%d] = %d steps | distance %d\r\n",n,box[n],dist[box[n]]); confirmPress(); sys.delay(500); fire(pow); } else n++; } setAbs(); } void calibrate(){ for (int i = 0; i<5; i++){ sys.delay(60); printf("%d | ",sens.readDist()); } for(int i = 0; i < iMeas; i++){ dist[i]=0; } for(int i = 0; i < 4; i++){ box[i]=0; } } void setAbs(){ sys.delay(100); while (sensor.isPressed() == false){ hMot6.rotRel(1,500); } hMot6.rotRel(-950,400); sys.delay(100); } void fire(int power){ printf("\r\n<<<FIRE>>> power = %d\r\n\r\n",power); sys.delay(500); hMot2.setPower(power); hMot3.setPower(power); sys.delay(100); hMot2.setPower(0); hMot3.setPower(0); sys.delay(200); } void calibrationPhase(){ int Wait = 0; float pow = 0; rotateAngle(90); while(Wait == 0){ sys.delay(1000); if (hBtn1.isPressed() == true) { Wait = 1; } sens.readDist(); printf("\r\n<<<SCAN>>> "); confirmPress(); dist[0] = sens.readDist(); printf(" ---> Distance %d",dist[0]); setLever(); sys.delay(2000); pow = setPower(dist[0]); printf("\r\n<<<ARMED>>>"); confirmPress(); fire(pow); } Wait = 0; } void calibrationMode(){ printf("\r\n\n*****Entered Calibration Mode*****\r\n\n"); calibrationPhase(); setAbs(); calibrate(); printf("\r\n\n*****Exciting Calibration Mode*****\r\n\n"); } void autoMode(){ printf("\r\n\n*****Entered Automated Control*****\r\n\n"); proximityScan(); systemScan(); targetingAndFire(); hMot2.setPower(0); hMot3.setPower(0); calibrate(); printf("\r\n\n*****Exciting Automated Control*****\r\n\n"); } void manualControl(){ printf("\r\n\n*****Entered Manual Control*****\r\n\n"); int selfAng = 0; int selfPow = 0; int selfDist = 0; int wait = 0; getchar(); while (wait == 0){ printf("\r\nPlease enter angle of shot: "); scanf("%d",&selfAng); getchar(); printf("\r\nYou entered: %d" ,selfAng); if(selfAng <= 0) {printf("\r\nEnter a valid number\r\n");} else {wait = 1;} } wait = 0; while (wait == 0){ printf("\r\nPlease enter distance of shot: "); scanf("%d",&selfDist); getchar(); printf("\r\nYou entered: %d",selfDist); if(selfDist <= 0) {printf("\r\nEnter a valid number\r\n");} else {wait = 1;} } wait = 0; rotateAngle(selfAng); printf("\r\nAngle set | "); setLever(); printf("Lever set | "); selfPow = setPower(selfDist); printf("Power calculated | "); printf("<<<ARMED>>>"); confirmPress(); printf("Button pressed | "); fire(selfPow); printf("fire\r\n"); setAbs(); calibrate(); printf("\r\n\n*****Exciting Manual Control*****\r\n\n"); }