top of page

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.

IMG_0014.JPG

VIDEO

Please excuse the cracked phone screen. Thank you! 

If video fails to load click here: 

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

ballbot_1.png
ballbot_2.png

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;
    }    
  }

bottom of page