BALL-BOT
3D Printed Spherical Robot
This mechatronics project is a 3D printable spherical robot that can be operated via an android app. The app acts as a joystick controller that sends commands to the robot through a bluetooth module. The joystick allows the user to control the directions that the wheels rotate and a slider mechanism controls the speed of the motors.
NOTE: This project is currently unfinished as the external spherical shell has yet to be created.
DESIGN
The design of this robot takes inspiration from the Star Wars droid BB-8 and the Sphero toy. It consists of two main bodies, the central driving vehicle and a separate external shell. Note that the vehicle sits freely inside the shell. The wheels come into contact with the shell and it is the force of friction between the two that allows for the wheels to rotate the shell like a hamster in a ball. Control of the motors operate similarly to that of a skid steered vehicle. To move forward, the two wheels spin in the same forward direction. To move backwards, the two wheels spin in the same backward direction. To steer, one wheel moves forward and the other moves backwards. The robot was designed using computer aided design (CAD) techniques to create a 3-D model. The components of the model were then 3-D printed and assembled.
​
Electronic Components: Arduino Mega, Motor Driver, Breadboard, 2 DC Motors, 12 Volt Battery
3-D Printed Components: Shell, 2 Wheels (each wheel is two parts), Base (divided into 4 quarters) , Electronics Base
CODE
Control of the robot was achieved through the use of an Arduino. The code needed for this robot can be seen below.
char controller;
int state = 0; // Controls motor direction
int duty = 0; // motor speed
int dutyA; // motor speed for motor A
int dutyB; // motor speed for motor B
​
void setup()
{
Serial.begin(9600); // set the baud rate to 9600, same should be of your Serial Monitor
DDRA = 255; // output
PORTA = 0; // initial state: off
DDRB = 255; // output
PORTB = 0; // initial state: off
pwm_init(); // function that initializes pwm
}
​
void loop() {
if (Serial.available()>0) // if bluetooth module receives input from controller
{
controller = Serial.read(); // receives controller input message
Serial.println(controller);
state = controller - 48; // converts from ASCII value to int value
motor_state(state); // calls function
motor_directionA(dutyA); // calls function
motor_directionB(dutyB); // calls function
motor_speed(controller); // calls function
}
}
// Iniializes motors
void pwm_init(void){
DDRL = 255;
TCCR5A = _BV(COM5A1) | _BV(COM5B1) | _BV(WGM52) | _BV(WGM50);
TCCR5B = _BV(CS51) | _BV(CS50);
OCR5A = 0;
OCR5B = 0;
}
// Determines the sign of the duty and controls the LEDs
void motor_state(int state) {
switch (state)
{
case 1: // FORWARD
PORTA = 0b00000001;
dutyA = duty;
dutyB = duty;
break;
case 2: // BACKWARD
PORTA = 0b00000010;
dutyA = -duty;
dutyB = -duty;
break;
case 3: // LEFT
PORTA = 0b00000100;
dutyA = -duty;
dutyB = duty;
break;
case 4: // RIGHT
PORTA = 0b00001000;
dutyA = duty;
dutyB = -duty;
break;
}
}
​
void motor_directionA(int dutyA) {
if (dutyA > 0) // if duty is positive
{
PORTB = 1;
}
else // if duty is negative
{
PORTB = 2;
}
OCR5A = duty; // relates the speed of the motor to the magnitude of the duty cycle
}
​
void motor_directionB(int dutyB) {
if (dutyB > 0) // if duty is positive
{
PORTB = PORTB + 4;
}
else // if duty is negative
{
PORTB = PORTB + 8;
}
OCR5B = duty; // relates the speed of the motor to the magnitude of the duty cycle
}
​
void motor_speed(char controller) {
switch (controller)
{
case 'A': // SLOW
duty = 50;
break;
case 'B': // MEDIUM
duty = 125;
break;
case 'C': // FAST
duty = 250;
break;
case 'D': // STOP
duty = 0;
PORTA = 0; // Turns off LEDs
break;
}
}