13.5 - Implementation

13.5 - Implementation

 

in

mm

Jumping Height Requirement

18

457.2

 

 

 

 

lb

kg

Lower Weight Max

0.5

0.226796

 

 

 

Upper Weight Extraneous

1.5

0.680388

Motor Weight

 

0.091

 

 

 

Battery Weight

1.54

0.15

Battery Amazon

 

 

Total Upper Weight Mass

 

0.921388

 

 

 

 

Geometry (mm)

Geometry (cm)

Motor Shaft Radius

4

0.4

 

 

 

 

 

 

Stored Potential Energy

lbf

Newtons

Force

80

355.8576

 

cm

m

Distance Stretched

25.4

0.254

Rough k constant

1401.014173

 

 

 


 

Implementation

Fabrication & Assembly

  • Structural components: 3D-printed plastic parts

  • Energy storage: multiple rubber bands in parallel

  • Shafts and fasteners: steel hardware

The assembly required careful alignment of parallel members to reduce binding. Even small asymmetries in part geometry resulted in uneven loading during high-force operation.

[ADD MEDIA: assembly photos]

Actuation and Electronics

  • DC motor: Used to drive a pulley system that stretches the rubber bands

  • Stepper motor: Used to actuate the clutch release mechanism

  • Clutch: Interference-fit coupling to an 8 mm shaft

The DC motor handled slow energy accumulation, while the stepper motor provided precise control over release timing.

Software and Control

Robot3.png

 

Robot4.png

 

Summary

Control logic was minimal by design. The DC motor was driven until a desired preload was achieved, after which the stepper motor disengaged the clutch, triggering the jump. No closed-loop sensing was implemented.

List of Components

Electronic Components

Purpose

LM2596 Buck Converter 

  • 12V input from battery, needed to be converted into 5V input for arduino

12V 5200mAh Lithium Ion Battery

  • The motor takes in 12V input, thus a 12V battery is required to get maximum torque out of the DC Motor

  • 5A is the amount of current used during stall. Since our system will require high loads while the jumping robot is being pult downward, we want to make sure our system can handle this loading case

 

DROK DC Motor Driver, L298 Dual H Bridge, 12V, 24V, 7A, PWM regulator

  • Needed motor driver to handle minimum 5

IR Receiver and Remote (Standard with Arduino Starter Kits)

  • Needed way to control jumping robot without touching robot, this ir receiver is a simple package requiring only 3 jumper wires to arduino

A4998 Stepper Controller

  • Stepper driver compatible with the nema 11 stepper motor

Nema 11 Stepper Motor

  • Connected to the A4998 Stepper Driver, we underestimated the torque rating of this motor leading to failure of the clutch release mechanism

 

 

 

Code Summary

 

IR Remote Command

Function

Button 1

Stops the DC motor from moving (idle state)

Button 2

Motor runs at max power clockwise

Button 3

Motor runs at max power counterclockwise

Button 4

Stepper Motor spins at orientation to disengage clutch

Button 5

Stepper motor spins to orientation to rearrange clutch

The Jumping Robot can be controlled by The Serial Monitor Input for debugging, but also has a boolean to switch it to the IR Remote state, allowing all the system to be controlled by the remote. 

 

Code Snippets (Shown Below)

IR Test (Main Code Used on Robot During Demo)

#include <IRremote.hpp>   // or <IRremote.h> depending on version #define IR_PIN 7 // Buttons Commands // 0xF609FF00 - UP // ---------- STEPPER (A4988, NEMA 11) ---------- MAKE SURE TO Calibrate Stepper Each Run // const int STEPPER_DIR_PIN  = 3; // const int STEPPER_STEP_PIN = 4; // const int baseStepsPerRev  = 200;  // 1.8° motor // const int microstepSetting = 1;    // set to 2/4/8/16 if MS pins used // const int stepsPerRev      = baseStepsPerRev * microstepSetting; // const unsigned int stepDelayMicros = 800; String motorStatus = "Idle"; String lastMotorStatus = "Idle"; String engagerStatus = "Engaged"; char SerialCharacter = 'b'; char lastSerialCharacter = 'b'; bool useSerial = false; int in1 = 8; int in2 = 9; int enA = 10; int speedValue = 255; uint32_t buttonVal; void setup() {   Serial.begin(9600);   // Start the receiver on chosen pin, enable onboard feedback LED   IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK); pinMode(enA, OUTPUT);   pinMode(in1, OUTPUT);   pinMode(in2, OUTPUT); } void loop() {    if (IrReceiver.decode()) {     Serial.print("Code: 0x");     buttonVal = IrReceiver.decodedIRData.decodedRawData;     Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);     IrReceiver.resume();   // ready for next code   }   // Reading Serial Monitor Data   if (Serial.available() > 0) {     SerialCharacter = Serial.read();     if (SerialCharacter != '\n' && SerialCharacter != '\r') {       Serial.print("Received: ");       Serial.println(SerialCharacter);   }   }   if(!useSerial){     SerialCharacter = 'z';     lastSerialCharacter = 'z';   }   if(buttonVal == 0xF30CFF00 || SerialCharacter  == 'b'){     setMotor("Idle", 0, true);   }else if(buttonVal == 0xE718FF00 || SerialCharacter == 'c'){     setMotor("RunDown", 255, true);   }else if(buttonVal == 0xA15EFF00 || SerialCharacter == 'a'){ // Change this one     setMotor("RunForward", 255, false);   }else if(buttonVal == 0xF708FF00){     engagerStatus = "Engaged";     //rotateStepperDegrees(120);   }else if(buttonVal == 0xE31CFF00){     engagerStatus = "Disengaged";    // rotateStepperDegrees(240);   }   lastSerialCharacter = SerialCharacter;   Serial.println("Motor Status: " +  motorStatus);   Serial.println("Engager Status: " + engagerStatus);   delay(1000); } void setMotor(String motorCommand, int speedVal, bool forward) {   // Current Spike Limiter - using Serial Monitor   if(useSerial && ((lastSerialCharacter == 'c' && SerialCharacter == 'a') || (lastSerialCharacter == 'a' && SerialCharacter == 'c'))){     analogWrite(enA, 0);     delay(500);   }   // Current Spike Limiter - using IR Reciever   motorStatus = motorCommand;   if(!useSerial && ((motorStatus == "RunDown" && lastMotorStatus == "RunForward") || (motorStatus == "RunForward" && lastMotorStatus == "RunDown"))){     analogWrite(enA, 0);     delay(500);     Serial.print("are you there");   }   digitalWrite(in1, forward ? HIGH : LOW);   digitalWrite(in2, forward ? LOW  : HIGH);   analogWrite(enA, speedVal);   Serial.println(motorCommand);   lastMotorStatus = motorCommand; } // void stepperMoveSteps(int direction, int steps) { //   digitalWrite(STEPPER_DIR_PIN, (direction >= 0) ? HIGH : LOW); //   for (int i = 0; i < steps; i++) { //     digitalWrite(STEPPER_STEP_PIN, HIGH); //     delayMicroseconds(stepDelayMicros); //     digitalWrite(STEPPER_STEP_PIN, LOW); //     delayMicroseconds(stepDelayMicros); //   } // } // void rotateStepperDegrees(int degrees) { //   int steps = stepsPerRev * (degrees/360); //   Serial.print("Stepper: 360 deg ("); //   Serial.print(steps); //   Serial.println("steps)"); //   stepperMoveSteps(1, steps); //   Serial.println("Stepper: done"); // }

Stepper Motor Test (Code to Test Stepper Motor - achieved full functionality)

// A4988 Stepper Test: rotate 360° forward, pause, rotate 360° back, pause const int DIR_PIN  = 3; const int STEP_PIN = 4; const int baseStepsPerRev  = 200;  // NEMA 11 typically 1.8° = 200 steps/rev const int microstepSetting = 1;    // set to 2/4/8/16 if you enabled microstepping const int stepsPerRev      = baseStepsPerRev * microstepSetting; const unsigned int stepDelayMicros = 800; // smaller = faster void stepperMoveSteps(int direction, int steps) {   digitalWrite(DIR_PIN, (direction >= 0) ? HIGH : LOW);   for (int i = 0; i < steps; i++) {     digitalWrite(STEP_PIN, HIGH);     delayMicroseconds(stepDelayMicros);     digitalWrite(STEP_PIN, LOW);     delayMicroseconds(stepDelayMicros);   } } void setup() {   pinMode(DIR_PIN, OUTPUT);   pinMode(STEP_PIN, OUTPUT);   digitalWrite(DIR_PIN, LOW);   digitalWrite(STEP_PIN, LOW); } void loop() {   // 360° forward   stepperMoveSteps(+1, stepsPerRev);   delay(1000);   // 360° back   stepperMoveSteps(-1, stepsPerRev);   delay(1000); }