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 |
|
| |
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
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 5200mAh Lithium Ion Battery |
. |
DROK DC Motor Driver, L298 Dual H Bridge, 12V, 24V, 7A, PWM regulator |
|
IR Receiver and Remote (Standard with Arduino Starter Kits) |
|
A4998 Stepper Controller |
|
Nema 11 Stepper Motor |
|
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);
}