16.4 - Implementation

16.4 - Implementation

Fabrication/Assembly:

All structural components of the vehicle were manufactured using ABS (Acrylonitrile Butadiene Styrene) through 3D printing, with an infill density of 60% to balance strength and weight. The use of ABS provides sufficient mechanical robustness and moderate flexibility, which is beneficial for components subjected to repeated deformation, such as the adjustable wheels.

Threaded connections and structural interfaces were reinforced using brass threaded inserts (M3) to improve durability and prevent wear in frequently assembled/disassembled joints. These inserts were used to mount the servo motor holder to the main chassis, as well as to support the elevated platform for the motor driver.

The system was assembled in a modular manner, with each adjustable wheel constructed as an independent unit. Each wheel module consists of:

  • Six coupler links

  • Six wheel blades

  • One sliding track

  • One slider block

The linkage joints within each wheel were connected using M3 screws (16 mm) and matching nuts, serving as rotational shafts. To ensure smooth revolute motion, each joint hole was designed with a 0.2 mm clearance relative to the shaft diameter, reducing friction and preventing binding during deformation.

To maintain structural integrity near the motor interface, limit blocks were installed on both sides of each wheel assembly. These blocks were secured using three M2.5 × 12 mm screws, which pass through the limit block, sliding track, and motor shaft. This configuration ensures a stable mechanical connection between the motor and wheel, as well as a constrained minimum wheel radius to prevent interference between adjacent blades during contraction.

The deformation of the wheels is driven by a centrally located rack-and-pinion mechanism. Two racks are symmetrically positioned above and below the pinion gear. Each rack is constrained to linear motion along slots in the chassis using:

  • Three M3 × 20 mm screws per rack

  • Custom 3D-printed ABS washers to maintain alignment and ensure stability

This symmetric rack arrangement ensures that both sides of the vehicle deform uniformly. The left and right wheel modules are mechanically identical and are actuated independently by two DC motors, allowing controlled and synchronized shape transformation. The central pinion gear is rigidly mounted to the servo motor horn using four M2 screws, ensuring precise alignment between the gear and motor axis. Additionally, an M2.5 screw is used to secure the pinion along the axial direction, preventing unwanted longitudinal movement during operation.

Each DC motor is mounted to the chassis using three M3 × 20 mm screws, providing a rigid and stable connection. The servo motor holder is attached to the main body using M3 brass inserts, and its base includes an M4 mounting hole to accommodate an optional caster wheel for additional support and mobility.

The motor driver (L298N module) is mounted on an elevated platform above the chassis using the same type of brass inserts, allowing for organized wiring and improved accessibility.

 

Electronics/Circuit:

One of the major challenges with the robot was supplying adequate power. The DC motors used were rated for 12 Volts, but the 12V battery we were able to source were too large to be feasible. In order to utilize 9V batteries, it was necessary to utilize separate power sources for the servo motor, DC motors, and Arduino. One 9V battery supplied power to the DC motors through an L298 H-Bridge motor driver, which also provided primary power to the Arduino. Another 9V battery powered the servo motor. A power bank (not shown in the diagram below) supplemented the Arduino power.

image-20260502-025352.png
Circuit Diagram

 

Software Development:

The robot uses an Arduino Uno powered by a 9V battery. The Arduino controls DC motors via interfacing with a motor driver. Just like in build assignment 2, it takes input from a joystick to control the speed and direction of the wheels. The Arduino also controls the servo motor to alter the wheel radius. When the joystick button is pushed, it toggles the servo between 0 and 60 degrees which correspond to low radius and high radius respectively.

#include <Servo.h> // ===== L298 Setup ===== const int ENA = 5; const int IN1 = 6; const int IN2 = 7; const int ENB = 9; const int IN3 = 10; const int IN4 = 11; // ===== Servo Setup ===== const int SERVO_PIN = 3; Servo myServo; int servoAngle = 0; // ===== Joystick Setup ===== const int JOY_X = A2; const int JOY_Y = A1; const int JOY_SW = 2; const int CENTER = 512; const int DEADZONE = 180; // Button Press Setup bool lastButtonState = HIGH; bool currentButtonState = HIGH; unsigned long lastDebounceTime = 0; const unsigned long debounceDelay = 50; unsigned long lastPrintTime = 0; const int printInterval = 200; // ms // ===== Functions to Control the Car ===== void stopCar() {   digitalWrite(ENA, LOW);   digitalWrite(ENB, LOW);   digitalWrite(IN1, LOW);   digitalWrite(IN2, LOW);   digitalWrite(IN3, LOW);   digitalWrite(IN4, LOW); } void moveForward() {   digitalWrite(IN1, HIGH);   digitalWrite(IN2, LOW);   digitalWrite(IN3, HIGH);   digitalWrite(IN4, LOW);   digitalWrite(ENA, HIGH);   digitalWrite(ENB, HIGH); } void moveBackward() {   digitalWrite(IN1, LOW);   digitalWrite(IN2, HIGH);   digitalWrite(IN3, LOW);   digitalWrite(IN4, HIGH);   digitalWrite(ENA, HIGH);   digitalWrite(ENB, HIGH); } void turnLeft() {   digitalWrite(IN1, LOW);   digitalWrite(IN2, HIGH);   digitalWrite(IN3, HIGH);   digitalWrite(IN4, LOW);   digitalWrite(ENA, HIGH);   digitalWrite(ENB, HIGH); } void turnRight() {   digitalWrite(IN1, HIGH);   digitalWrite(IN2, LOW);   digitalWrite(IN3, LOW);   digitalWrite(IN4, HIGH);   digitalWrite(ENA, HIGH);   digitalWrite(ENB, HIGH); } // ===== Toggle between 0 and 85 degrees on the servo ===== void toggleServo() {   if (servoAngle == 0) {     servoAngle = 85;   } else {     servoAngle = 0;   }   myServo.write(servoAngle);   Serial.print("Servo angle: ");   Serial.println(servoAngle); } // ===== Setup ===== void setup() {   pinMode(ENA, OUTPUT);   pinMode(IN1, OUTPUT);   pinMode(IN2, OUTPUT);   pinMode(ENB, OUTPUT);   pinMode(IN3, OUTPUT);   pinMode(IN4, OUTPUT);   pinMode(JOY_SW, INPUT_PULLUP);   stopCar();   myServo.attach(SERVO_PIN);   myServo.write(servoAngle);   Serial.begin(115200);   Serial.println("Joystick debug mode started."); } // ===== loop  ===== void loop() {   int xValue = analogRead(JOY_X);   int yValue = analogRead(JOY_Y);   int xOffset = xValue - CENTER;   int yOffset = yValue - CENTER;   String state = "STOP";   // ---------- Control the car's movements ----------   if (abs(xOffset) < DEADZONE && abs(yOffset) < DEADZONE) {     stopCar();     state = "STOP";   } else {     if (abs(yOffset) >= abs(xOffset)) {       if (yOffset < -DEADZONE) {         moveForward();         state = "FORWARD";       } else if (yOffset > DEADZONE) {         moveBackward();         state = "BACKWARD";       }     } else {       if (xOffset < -DEADZONE) {         turnLeft();         state = "LEFT";       } else if (xOffset > DEADZONE) {         turnRight();         state = "RIGHT";       }     }   }   // ---------- Read the Joystick Button ----------   bool reading = digitalRead(JOY_SW);   if (reading != lastButtonState) {     lastDebounceTime = millis();   }   if ((millis() - lastDebounceTime) > debounceDelay) {     if (reading != currentButtonState) {       currentButtonState = reading;       if (currentButtonState == LOW) {         toggleServo();       }     }   }   lastButtonState = reading;   delay(10); }