WEEK 12/13 Mechanical Design, Machine Design
SLIDE & PRESENTATION:
The Cat Communication Robot
Our revised concept was to build a drawing robot inspired by the Polargraph Plotter, but with a unique twist. The idea was to reimagine it as a medium for cat-to-human communication.
Concept
Cats communicate in subtle and complex ways. What if we could build a machine that could "translate" a cat’s meows into written messages for their human companions?
We imagined a robot that could recognize different cat vocalizations like meows asking for food, attention, or a clean litter box, and interpret them. Then, it would draw or write a message on a piece of paper or wall, effectively becoming a "feline secretary."
While the actual voice recognition part was too advanced for this week’s scope, we focused on the mechanical design that would allow for such expressive drawing.
MECHANICAL DESIGN:
Polargraph Plotter
The original Polargraph works by using two motors mounted at the top corners of a surface. These motors control the length of two cords or belts, which suspend a pen in between them. By precisely changing the lengths of these cords, the pen moves smoothly across a 2D surface, plotting images or text.
We adopted this basic idea, but adapted the design to match the aesthetics and thematic goals of the FitnessCat.
In the back there’s a space for paper roll.
Custom Pen Holder
-
Pen Holder with Rack and Pinion System
I designed a custom pen holder featuring a rack and pinion system. This setup is controlled by a servo motor, allowing the pen to be lifted and lowered precisely. This is essential for drawing clean lines and separating strokes.
-
Whisker-Inspired Sliding Mechanism
To reinforce the "cat" theme, we added sliding counterweights that mimic the shape and movement of cat whiskers. These are attached to a timing belt system, which adds visual charm and helps balance the pen holder's motion.
-
Frame & Mounting
The motors are mounted on a vertical frame, similar to a traditional Polargraph. We used light plywood and 3D-printed parts to keep the structure simple and easy to assemble.
Here’s the prototyping process:
CONTROL:
Hardware Components
Required Components
- Arduino Uno R3
- 2× 28BYJ-48 Stepper Motors
- 2× ULN2003 Driver Boards
- 1× Small Servo Motor (SG90 or similar)
- Power Supply (5-12V DC, at least 1A)
- Jump Wires
- Drawing Surface
- Gondola (pen holder)
- Dented Belts (for transmission)
- Counterweights
- Rack and Pinion System (for pen up/down movement)
Hardware Setup
Arduino and Motor Setup
- Gather the Arduino Uno R3, two 28BYJ-48 stepper motors with ULN2003 driver boards, and a small servo motor.
- Prepare a breadboard for connecting components during testing phase.
- Connect the external lab power supply to provide consistent power to the motors.
Transmission System
- Install dented belts for transmitting movement from the stepper motors to the gondola.
- Add counterweights on one side to balance with the gondola weight, ensuring smooth movement.
- The servo motor connects to a rack and pinion system that precisely controls the pen's up/down movement.
Wiring
Arduino to Stepper Motor Connections
- Left Stepper (ULN2003 Driver Board)
- IN1 → Arduino Pin 8
- IN2 → Arduino Pin 9
- IN3 → Arduino Pin 10
- IN4 → Arduino Pin 11
- VCC → 5V (external power supply)
- GND → GND (common ground with Arduino)
- Right Stepper (ULN2003 Driver Board)
- IN1 → Arduino Pin 4
- IN2 → Arduino Pin 5
- IN3 → Arduino Pin 6
- IN4 → Arduino Pin 7
- VCC → 5V (external power supply)
- GND → GND (common ground with Arduino)
Arduino to Servo Connections
- Signal → Arduino Pin 12
- VCC → 5V (external power supply)
- GND → GND (common ground with Arduino)
Power Supply Connections
- Connect the external lab power supply to provide 5V to the stepper motor driver boards and servo
- Ensure common ground between the power supply and Arduino
- The 28BYJ-48 motors typically draw 150-200mA each at 5V
- The servo may draw up to 500mA during operation
Connection Notes
- Make sure the stepper motor wires are connected in the correct order to the ULN2003 driver boards
- The common ground connection between Arduino and power supply is essential
- If using a higher voltage power supply (e.g., 12V), make sure to use a voltage regulator to provide 5V to the components
- When testing, secure all wires properly to prevent accidental disconnection
Installation:
Test Software
We had to add some weights for stable movements
Test Codes
References and Resources
Before implementing the full IPAD solution, it's essential to test the hardware components individually. The following Arduino test sketch allows you to verify the connections and proper functioning of both stepper motors and the servo.
// Polargraph Components Test Sketch
// Tests 28BYJ-48 stepper motors and servo on specified pins
#include <Stepper.h>
#include <Servo.h>
// Define stepper parameters
const int stepsPerRevolution = 2048; // 28BYJ-48 steps per revolution with gear reduction
Servo penServo;
// Initialize left stepper on pins 8, 10, 9, 11 (this order is important for proper rotation)
Stepper leftStepper(stepsPerRevolution, 8, 10, 9, 11);
// Initialize right stepper on pins 4, 6, 5, 7 (this order is important for proper rotation)
Stepper rightStepper(stepsPerRevolution, 4, 6, 5, 7);
// Servo setup on pin 12
int servoPin = 12;
int penUp = 90; // Adjust these angles based on your setup
int penDown = 140;
void setup() {
// Set stepper motor speed (RPM)
leftStepper.setSpeed(10); // 10 RPM is a good starting speed for testing
rightStepper.setSpeed(10);
// Initialize servo
penServo.attach(servoPin);
penServo.write(penUp); // Start with pen up
// Initialize serial for debugging
Serial.begin(9600);
Serial.println("Polargraph Components Test");
Serial.println("Commands: 'L' - Left stepper, 'R' - Right stepper, 'U' - Pen up, 'D' - Pen down, 'B' - Both steppers");
}
void loop() {
// Check if there's any incoming serial data
if (Serial.available() > 0) {
char command = Serial.read();
switch (command) {
case 'L':
case 'l':
// Test the left stepper motor with 1/4 rotation in each direction
Serial.println("Testing left stepper - 1/4 rotation clockwise");
leftStepper.step(stepsPerRevolution / 4); // 512 steps = 1/4 rotation
delay(500);
Serial.println("Testing left stepper - 1/4 rotation counter-clockwise");
leftStepper.step(-stepsPerRevolution / 4);
break;
case 'R':
case 'r':
// Test the right stepper motor with 1/4 rotation in each direction
Serial.println("Testing right stepper - 1/4 rotation clockwise");
rightStepper.step(stepsPerRevolution / 4);
delay(500);
Serial.println("Testing right stepper - 1/4 rotation counter-clockwise");
rightStepper.step(-stepsPerRevolution / 4);
break;
case 'U':
case 'u':
// Move the servo to pen-up position
Serial.println("Pen up");
penServo.write(penUp); // 90 degrees by default
break;
case 'D':
case 'd':
// Move the servo to pen-down position
Serial.println("Pen down");
penServo.write(penDown); // 140 degrees by default
break;
case 'B':
case 'b':
// Test both steppers simultaneously for coordinated movement
Serial.println("Testing both steppers simultaneously");
// Move both steppers forward simultaneously
for (int i = 0; i < (stepsPerRevolution / 8); i++) {
leftStepper.step(1);
rightStepper.step(1);
}
delay(500);
// Move both steppers backward simultaneously
for (int i = 0; i < (stepsPerRevolution / 8); i++) {
leftStepper.step(-1);
rightStepper.step(-1);
}
break;
}
}
}
How to Use the Test Software
- Connect the Arduino to your computer via USB.
- Make sure all hardware connections match the wiring diagram.
- Open the Arduino IDE and upload the sketch.
- Open the Serial Monitor (Tools → Serial Monitor, set to 9600 baud).
- Send the following single-character commands to test each component:
L
to test the left stepper motor (connected to pins 8,9,10,11)R
to test the right stepper motor (connected to pins 4,5,6,7)U
to move the servo to pen-up positionD
to move the servo to pen-down positionB
to test both stepper motors simultaneously
What to Look For During Testing
- Stepper Motors: Should rotate smoothly without stuttering or skipping steps
- Servo: Should move reliably between up and down positions
- Power Supply: Should provide stable voltage and current during operation
- Temperature: Components should not overheat during testing
IPAD Software Installation
This polargraph setup uses the IPAD (Improved Polargraph Art Device) firmware from https://github.com/zanedrys/IPAD. Follow these steps to install and configure the software:
Step 1: Install Required Software
- Download and install the Arduino IDE from arduino.cc
- Download and install Processing from processing.org
- Clone or download the IPAD repository from GitHub
Step 2: Install Required Arduino Libraries
- Open the Arduino IDE
- Go to Sketch → Include Library → Manage Libraries
- Search for and install the following libraries:
- AccelStepper (for improved stepper motor control)
- Servo (for pen control)
Step 3: Upload the IPAD Firmware
- Open the IPAD_Firmware.ino file from the downloaded repository
-
Modify the pin assignments in the code to match your specific setup:
// Modify these lines to match your pin connections // Left stepper on pins 8,9,10,11 #define LEFT_STEP_PIN1 8 #define LEFT_STEP_PIN2 9 #define LEFT_STEP_PIN3 10 #define LEFT_STEP_PIN4 11 // Right stepper on pins 4,5,6,7 #define RIGHT_STEP_PIN1 4 #define RIGHT_STEP_PIN2 5 #define RIGHT_STEP_PIN3 6 #define RIGHT_STEP_PIN4 7 // Servo on pin 12 #define SERVO_PIN 12
-
Make sure the Arduino is connected to your computer via USB
- Select the correct board (Arduino Uno) and port in the Arduino IDE
- Upload the firmware to your Arduino
Step 4: Configure and Run the IPAD Processing Controller
- Open Processing
- Open the IPAD_Controller.pde file from the downloaded repository
- In the IPAD_Controller.pde file, find the configuration section and make sure:
- The COM port matches your Arduino's connection
- The machine dimensions match your physical setup
- The motor specifications match the 28BYJ-48 steppers
- Run the Processing sketch to open the IPAD control interface
IPAD software control interface showing drawing controls
IPAD Software Implementation
Using IPAD with Your Hardware
- The IPAD software provides a much more advanced control system than the test sketch
- Key features of IPAD when used with your hardware:
- Vector drawing support
- Advanced path planning
- Better motor control and acceleration handling
- GUI interface for easy control
Important IPAD Configuration Options
When working with the IPAD software, pay special attention to:
- Machine Settings in Processing Controller
- Set the correct COM port for your Arduino
- Configure the machine width and height
- Set the motor steps per revolution (2048 for 28BYJ-48)
- Adjust the microstepping settings if you modified the firmware
- Motor Settings
- Set the correct motor speed (start with 500-800 steps/min for the 28BYJ-48)
- Set acceleration values (typically 100-200 steps/sec² for 28BYJ-48)
- If motors skip steps, reduce speed and increase power supply current
- Pen Settings
- Configure servo up/down positions (typically between 70-150 degrees)
- Set pen lift and lower delay (200-500ms recommended)
IPAD software settings panel showing configuration options
The software was constantly crashing and not letting us proceed so we came up with a solution:
We took the test file from before and added:
TRIANGLE:
// Draw a triangle in the center of the canvas
void drawTriangle()
{
Serial.println(F("Drawing Triangle"));
// Calculate a centered triangle
float centerX = CANVAS_WIDTH / 2;
float centerY = CANVAS_HEIGHT / 2;
float size = min(CANVAS_WIDTH, CANVAS_HEIGHT) / 6; // Smaller triangle (was /4)
// Calculate vertices
float x1 = centerX;
float y1 = centerY - size;
float x2 = centerX - size * 0.866; // sin(60°) = 0.866
float y2 = centerY + size * 0.5; // cos(60°) = 0.5
float x3 = centerX + size * 0.866;
float y3 = centerY + size * 0.5;
// Draw triangle
drawLine(x1, y1, x2, y2);
drawLine(x2, y2, x3, y3);
drawLine(x3, y3, x1, y1);
// Lift pen
penUp();
Serial.println(F("Triangle complete"));
}
CIRCLE
// Draw a circle in the center of the canvas
void drawCircle()
{
Serial.println(F("Drawing Circle"));
float centerX = CANVAS_WIDTH / 2;
float centerY = CANVAS_HEIGHT / 2;
float radius = min(CANVAS_WIDTH, CANVAS_HEIGHT) / 8; // Smaller circle (was /5)
// Number of segments to approximate the circle
const int segments = 36; // More segments = smoother circle
// Move to starting point with pen up
penUp();
float startX = centerX + radius;
float startY = centerY;
moveTo(startX, startY);
// Put pen down to start drawing
penDown();
// Draw circle as a series of short lines
for (int i = 1; i <= segments; i++)
{
float angle = 2 * PI * i / segments;
float x = centerX + radius * cos(angle);
float y = centerY + radius * sin(angle);
moveTo(x, y);
}
// Lift pen
penUp();
Serial.println(F("Circle complete"));
}
HERE’S THE FULL CODE FOR THE VSCODE+PLATFORMIO platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino
monitor_speed = 115200
lib_deps =
arduino-libraries/Servo@^1.1.8
arduino-libraries/Stepper@^1.1.3
main.cpp
#include "Polargraph_Test.h"
#include <math.h>
// Initialize stepper and servo objects
Stepper leftStepper(STEPS_PER_REVOLUTION, LEFT_MOTOR_PIN1, LEFT_MOTOR_PIN2, LEFT_MOTOR_PIN3, LEFT_MOTOR_PIN4);
Stepper rightStepper(STEPS_PER_REVOLUTION, RIGHT_MOTOR_PIN1, RIGHT_MOTOR_PIN2, RIGHT_MOTOR_PIN3, RIGHT_MOTOR_PIN4);
Servo penServo;
// Current position tracking
float currentX = CANVAS_WIDTH / 2;
float currentY = CANVAS_HEIGHT / 2;
void setup()
{
// Set stepper motor speeds
leftStepper.setSpeed(MOTOR_SPEED_RPM);
rightStepper.setSpeed(MOTOR_SPEED_RPM);
// Initialize servo
penServo.attach(SERVO_PIN);
penServo.write(PEN_UP_ANGLE); // Start with pen up
// Initialize serial for debugging
Serial.begin(115200);
Serial.println(F("Polargraph Components Test"));
printInstructions();
}
void loop()
{
// Check if there's any incoming serial data
if (Serial.available() > 0)
{
char command = Serial.read();
switch (command)
{
case 'L':
case 'l':
testLeftMotor();
break;
case 'R':
case 'r':
testRightMotor();
break;
case 'U':
case 'u':
penUp();
break;
case 'D':
case 'd':
penDown();
break;
case 'B':
case 'b':
testBothMotors();
break;
case 'T':
case 't':
drawTriangle();
break;
case 'C':
case 'c':
drawCircle();
break;
case '?':
printInstructions();
break;
}
}
}
void testLeftMotor()
{
// Test the left stepper motor with 1/4 rotation in each direction
Serial.println(F("Testing left stepper - 1/4 rotation clockwise"));
leftStepper.step(STEPS_PER_REVOLUTION / 4);
delay(500);
Serial.println(F("Testing left stepper - 1/4 rotation counter-clockwise"));
leftStepper.step(-STEPS_PER_REVOLUTION / 4);
}
void testRightMotor()
{
// Test the right stepper motor with 1/4 rotation in each direction
Serial.println(F("Testing right stepper - 1/4 rotation clockwise"));
rightStepper.step(STEPS_PER_REVOLUTION / 4);
delay(500);
Serial.println(F("Testing right stepper - 1/4 rotation counter-clockwise"));
rightStepper.step(-STEPS_PER_REVOLUTION / 4);
}
void penUp()
{
// Move the servo to pen-up position
Serial.println(F("Pen up"));
penServo.write(PEN_UP_ANGLE);
delay(300); // Give time for the servo to move
}
void penDown()
{
// Move the servo to pen-down position
Serial.println(F("Pen down"));
penServo.write(PEN_DOWN_ANGLE);
delay(300); // Give time for the servo to move
}
void testBothMotors()
{
// Test both steppers simultaneously for coordinated movement
Serial.println(F("Testing both steppers simultaneously"));
// Move both steppers forward simultaneously
Serial.println(F(" Forward motion..."));
for (int i = 0; i < (STEPS_PER_REVOLUTION / 8); i++)
{
leftStepper.step(1);
rightStepper.step(1);
}
delay(500);
// Move both steppers backward simultaneously
Serial.println(F(" Backward motion..."));
for (int i = 0; i < (STEPS_PER_REVOLUTION / 8); i++)
{
leftStepper.step(-1);
rightStepper.step(-1);
}
Serial.println(F("Test complete"));
}
void printInstructions()
{
Serial.println(F("Commands:"));
Serial.println(F(" L - Test Left stepper"));
Serial.println(F(" R - Test Right stepper"));
Serial.println(F(" U - Pen up"));
Serial.println(F(" D - Pen down"));
Serial.println(F(" B - Test Both steppers"));
Serial.println(F(" T - Draw Triangle"));
Serial.println(F(" C - Draw Circle"));
Serial.println(F(" ? - Show this help"));
}
// Convert Cartesian coordinates to string lengths (distance from each motor)
void convertToSteps(float x, float y, int &leftSteps, int &rightSteps)
{
// Calculate string lengths using Pythagorean theorem
float leftStringLength = sqrt(x * x + y * y);
float rightStringLength = sqrt((MOTOR_DISTANCE - x) * (MOTOR_DISTANCE - x) + y * y);
// Convert to steps (this is a simplified conversion, might need calibration for your setup)
leftSteps = leftStringLength * (STEPS_PER_REVOLUTION / (2 * PI * 10)); // Assuming 10mm pulley radius
rightSteps = rightStringLength * (STEPS_PER_REVOLUTION / (2 * PI * 10));
}
// Move to a specific position with pen up
void moveTo(float x, float y)
{
Serial.print(F("Moving to: X="));
Serial.print(x);
Serial.print(F(", Y="));
Serial.println(y);
int leftSteps, rightSteps;
int currentLeftSteps, currentRightSteps;
// Calculate current position in steps
convertToSteps(currentX, currentY, currentLeftSteps, currentRightSteps);
// Calculate target position in steps
convertToSteps(x, y, leftSteps, rightSteps);
// Calculate step differences
int leftStepDiff = leftSteps - currentLeftSteps;
int rightStepDiff = rightSteps - currentRightSteps;
// Move steppers
// We'll move steppers alternately to make smoother movement
int maxSteps = max(abs(leftStepDiff), abs(rightStepDiff));
for (int i = 0; i < maxSteps; i++)
{
if (i < abs(leftStepDiff))
{
leftStepper.step(leftStepDiff > 0 ? 1 : -1);
}
if (i < abs(rightStepDiff))
{
rightStepper.step(rightStepDiff > 0 ? 1 : -1);
}
}
// Update current position
currentX = x;
currentY = y;
}
// Draw a line between two points
void drawLine(float x1, float y1, float x2, float y2)
{
// Move to start position with pen up
penUp();
moveTo(x1, y1);
// Put pen down to start drawing
penDown();
// Move to end position with pen down
moveTo(x2, y2);
}
// Draw a triangle in the center of the canvas
void drawTriangle()
{
Serial.println(F("Drawing Triangle"));
// Calculate a centered triangle
float centerX = CANVAS_WIDTH / 2;
float centerY = CANVAS_HEIGHT / 2;
float size = min(CANVAS_WIDTH, CANVAS_HEIGHT) / 6; // Smaller triangle (was /4)
// Calculate vertices
float x1 = centerX;
float y1 = centerY - size;
float x2 = centerX - size * 0.866; // sin(60°) = 0.866
float y2 = centerY + size * 0.5; // cos(60°) = 0.5
float x3 = centerX + size * 0.866;
float y3 = centerY + size * 0.5;
// Draw triangle
drawLine(x1, y1, x2, y2);
drawLine(x2, y2, x3, y3);
drawLine(x3, y3, x1, y1);
// Lift pen
penUp();
Serial.println(F("Triangle complete"));
}
// Draw a circle in the center of the canvas
void drawCircle()
{
Serial.println(F("Drawing Circle"));
float centerX = CANVAS_WIDTH / 2;
float centerY = CANVAS_HEIGHT / 2;
float radius = min(CANVAS_WIDTH, CANVAS_HEIGHT) / 8; // Smaller circle (was /5)
// Number of segments to approximate the circle
const int segments = 36; // More segments = smoother circle
// Move to starting point with pen up
penUp();
float startX = centerX + radius;
float startY = centerY;
moveTo(startX, startY);
// Put pen down to start drawing
penDown();
// Draw circle as a series of short lines
for (int i = 1; i <= segments; i++)
{
float angle = 2 * PI * i / segments;
float x = centerX + radius * cos(angle);
float y = centerY + radius * sin(angle);
moveTo(x, y);
}
// Lift pen
penUp();
Serial.println(F("Circle complete"));
}
Estimated BOM (bill of materials)
Item | Quantity | Unit Price | Total |
---|---|---|---|
3D Printing material (PLA/PETG) | 1 spool | ~20€ | ~20€ |
MDF (12mm) | 1 sheets | ~15€ | ~15€ |
Arduino Uno | 1 | 29.5€ | 29.50€ |
Servo (SG90) | 1 | 3.30€ | 3.30€ |
Dented belt (GT2) | 1 | 17.50€ | 17.50€ |
Stepper + ULN2003 | 2 motors set | 21.25€ | 21.25€ |
Breadboard | 1 board | 2,25€ | 2,25€ |
Jumping wires | 1 pack | 3.50€ | 3.50€ |
Power supply DC 5V | 1 | 8.50€ | 8.50€ |
Total | ~121€ |
FILES
3D
CHECKLIST:
Group assignment:
PART 1/2
- Design a machine that includes mechanism + actuation + automation + application
- Build the mechanical parts and operate it manually
- Document the group project
PART 2/2
- Actuate and automate your machine
- Document the group project
Individual assignment:
- Document your individual contribution
Learning outcomes:
- Work and communicate effectively as a team
- Design, plan and build a machine
- Analyse and solve technical problems
- Recognise opportunities for improvements in the design
Have you answered these questions?
- Documented the machine building process to the group page
- Documented your individual contribution to this project on your own website
- Linked to the group page from your individual page as well as from group page to your individual pages
- Shown how your team planned, allocated tasks and executed the project (Group page)
- Described problems and how the team solved them (Group page)
- Listed possible improvements for this project (Group page)
- Included your design files (Group page)
- You need to present your machine globally and/or include a 1 min video (1920x1080 HTML5 MP4) + slide (1920x1080 PNG) (Group page)