Things used in this project

Hardware components:
Core
Particle Spark Core
×1
Pololu - Micro Breadboard
×1
Pololu - TB6612FNG Dual Motor Driver Carrier
×1
Pololu - 50:1 Micro Metal Gearmotor HP (625 RPM)
×2
Pololu - 22T Track Set
×1
Pololu - 4-AAA Battery Holder
×1
22AWG Stranded Hook-up Wire
×1
NiMH AAA Batteries
×1
Double sided foam tape (to mount AAA battery pack)
×1

Custom parts and enclosures

Particle Sumo Bot Dozer Blade 1
The main part of the dozer blade, minus second color Spark logo.
Particle Sumo Bot Dozer Blade 2
The secondary part of the dozer blade, second color Spark logo insert
Dozer Blade Riser
This is just a little spacer to raise up the dozer blade. Adjust the height of the blade to your own personal taste!
Generic Dozer Blade
This is the dozer blade without a logo. Great for single color printers or to customize yourself!
Particle Sumo Chassis (Outdated - use MOD3)
This is the main sumo bot chassis which motors just snap into to and wheels and dozer blade bolt right on. Designed for a 4AA battery holder, but shown in this project with a 4AAA holder just because. You could also use a large single cell LiPo pack.
Particle Sumo Chassis (MOD3)
I noticed that the tracks on the original spark-sumo-chassis.stl design would bow out in the front when the tracks pulled on the wheels. The motor mounts were a little weak, and with added play in the motor shaft and wheel there was nearly 5 degrees of tilt. This chassis is the 3rd modification I did that toes in the front wheels, and moves the rear wheels up 2mm to compensate for the front wheels actually moving forward as well. Subsequently I had to increase the nose by 3mm for dozer-blade to track clearance. I also changed one of the accessory mounting holes to a rectangle cut out to allow me to easily remove the battery pack cable. This came in handy moving the battery pack between several designs! Overall, this chassis ROCKS!

Schematics

TB6612 Motor Driver Pinout
Solder in a male header to the right side. Wires go on the left side.
There is no need to use multiple GNDs, just the bottom right GND is fine.
VCC goes to 3V3 output on the Spark Core.
VMOT goes to BATT+ from the Battery Pack.
BATT+ also goes up to VIN on the Spark Core.
Spark Core GND is connected to BATT- and GND of the Motor Driver.
AO0/AO1 goes to the left motor, BO0/BO1 goes to the right motor.
PWMA on the Motor Driver will align with A6 and PWMB will align with A0.
Tb6612
TB6612 and Spark Core Wiring
Img 8613

Code

Particle Sumo Bot FirmwareC/C++
This is the firmware that gets flashed to the Spark Core. Copy/Paste this into a new application at https://build.particle.io and flash to your Core. Through the use of one Spark.function(), all commands to control the robot can be sent in a comma delimited string. The format is `x,yyy,zzz,` where x = direction commands: f b l or r, y = the speed in percentage and z = the duration in milliseconds. E.g., `f,100,500,` or `r,50,100,`
/* 
    A0 - PWMB (speed right)
    A1 - BIN2 (direction bits)
    A2 - BIN1
    
    A3 - /STBY (motor enable)
    
    A4 - AIN1 (direction bits)
    A5 - AIN2
    A6 - PMWA (speed left)
*/

#define STBY A3
#define MOTOR_L 0
#define MOTOR_R 1
#define FWD 0
#define RVS 1
#define BIN1 A2
#define BIN2 A1
#define AIN1 A4
#define AIN2 A5
#define PWM_L A6
#define PWM_R A0

int _speed = 0;
int _duration = 0;
bool _new_command = false;

void setup() {
    
    Serial.begin(9600);
    
    int pin;
    for (pin=A0; pin<=A6; pin++) {
        pinMode(pin, OUTPUT); 
    }
    for (pin=A0; pin<=A6; pin++) {
        digitalWrite(pin, LOW); 
    }
    
    enableMotors(true);
    
    Spark.function("cmd",cmdRobot);
}

void loop() {
    if (_new_command == true) {
        setSpeed(MOTOR_L, _speed);
        setSpeed(MOTOR_R, _speed);
        delay(_duration);
        setSpeed(MOTOR_L, 0);
        setSpeed(MOTOR_R, 0);
        _new_command = false;
    }
}

int cmdRobot(String c) {
    // c format: x,yyy,zzz,
    // x = direction (f/b/l/r)
    // y = speed in percentage
    // z = duration in milliseconds
    //
    // fblr, forward, backward, left turn, right turn
    
    int start = 0;
    int end = 0;
    int speed = 0;
    int duration = 0;
        
    if (c.charAt(0) == 'f') {
        setDirection(MOTOR_L, FWD);
        setDirection(MOTOR_R, FWD);
        Serial.println("F");
    }
    else if (c.charAt(0) == 'b') {
        setDirection(MOTOR_L, RVS);
        setDirection(MOTOR_R, RVS);
        Serial.println("B");
    }
    else if (c.charAt(0) == 'l') {
        setDirection(MOTOR_L, RVS);
        setDirection(MOTOR_R, FWD);
        Serial.println("L");
    }
    else if (c.charAt(0) == 'r') {
        setDirection(MOTOR_L, FWD);
        setDirection(MOTOR_R, RVS);
        Serial.println("R");
    }
    
    start = c.indexOf(',');
    if (start != -1) {
        end = c.indexOf(',', start+1);
        if (end == -1) {
            return 2;
        }
    }
    else {
        return 1;
    }
    
    speed = c.substring(start+1,end).toInt();
    
    start = end;
    end = c.indexOf(',', start+1);
    if (end == -1) {
        return 3;
    }
    
    duration = c.substring(start+1,end).toInt();
    
    Serial.print("Speed: ");
    Serial.println(speed);
    Serial.print("Duration: ");
    Serial.println(duration);
    
    _speed = speed;
    _duration = duration;
    _new_command = true;
    
    return _duration;
}

void enableMotors(bool enable) {
    if (enable) digitalWrite(STBY, HIGH); // enable motor output
    else digitalWrite(STBY, LOW); // disable motor output
}

void setDirection(bool motor, bool dir) {
    if (motor == MOTOR_L) {
        if (dir == RVS) {
            digitalWrite(AIN1, LOW);
            digitalWrite(AIN2, HIGH);
        }
        else if (dir == FWD) {
            digitalWrite(AIN2, LOW);
            digitalWrite(AIN1, HIGH);
        }
    }
    else if (motor == MOTOR_R) {
        if (dir == FWD) {
            digitalWrite(BIN1, LOW);
            digitalWrite(BIN2, HIGH);
        }
        else if (dir == RVS) {
            digitalWrite(BIN2, LOW);
            digitalWrite(BIN1, HIGH);
        }
    }
    else {
        digitalWrite(AIN1, LOW);  // disable all motors
        digitalWrite(AIN2, LOW);
        digitalWrite(BIN1, LOW);
        digitalWrite(BIN2, LOW);
    }
}

void setSpeed(bool motor, int speed) {
    if (motor == MOTOR_L) {
        analogWrite(PWM_L, map(speed,0,100,0,255) );
    }
    else if (motor == MOTOR_R) {
        analogWrite(PWM_R, map(speed,0,100,0,255) );
    }
    else {
        analogWrite(PWM_L, 0);  // stop all motors
        analogWrite(PWM_R, 0);
    }
}
Pebble Watch Simply.js AppJavaScript
This is a simple app to control the Particle Sumo Bot from your Pebble Watch. Install Simply.js on your Pebble, host this script somewhere that will give you a URL (a Public Dropbox link works well), and paste that link into the Simple.js app settings. UP is forward, DOWN is reverse. SELECT is left turn, LONG PRESS SELECT is right turn.
var DEVICE_ID = 'YOUR_DEVICE_ID';
var ACCESS_TOKEN = 'YOUR_ACCESS_TOKEN';

simply.on('singleClick', function(e) {
  console.log(util2.format('single clicked $button!', e));
  var command = '';
  if ('up' == e.button) {
    command = 'f,100,500,';
    simply.subtitle('FORWARD!');
  } else if ('select' == e.button) {
    command = 'l,100,100,';
    simply.subtitle('LEFT!');
  }
  else if ('down' == e.button) {
    command = 'b,100,500,';
    simply.subtitle('REVERSE!');
  }
  else {
    return;
  }

  ajax(
    {
      url: 'https://api.particle.io/v1/devices/' + DEVICE_ID + '/cmd?access_token=' + ACCESS_TOKEN,
      method: 'post',
      type: 'json',
      data: { a: command }
    },
    function(e){ console.log('ajax success: ' + e); },
    function(e){ console.log('ajax failure: ' + e); }
  );
});

simply.on('longClick', function(e) {
  console.log(util2.format('long clicked $button!', e));
  var command = '';
  if ('select' == e.button) {
    command = 'r,100,100,';
    simply.subtitle('RIGHT!');
  }
  else {
    return;
  }
  ajax(
    {
      url: 'https://api.particle.io/v1/devices/' + DEVICE_ID + '/cmd?access_token=' + ACCESS_TOKEN,
      method: 'post',
      type: 'json',
      data: { a: command }
    },
    function(e){ console.log('ajax success: ' + e); },
    function(e){ console.log('ajax failure: ' + e); }
  );
});

simply.setText({
  title: 'Particle bot',
  body: 'Press buttons to control the bot!',
}, true);
Node.js WASD Key Driving ScriptJavaScript
This Node.js script allows you to drive the Sumo Bot from the W,A,S,D keys on your keyboard.
Save the script as bot.js in some directory on your computer.
Make sure Node.js is installed!
Run `npm install sparkjs` in the directory you saved bot.js in.
Run `npm install prompt` in the same directory.
Run the script with `node bot.js`
Login to your Particle account, and then enter the device name of the Spark Core you used on your Particle Sumo Bot. There's no need to enter the long DEVICE ID. Keep in mind this name is case sensitive. If you forgot what your device name is, you can use https://build.spark.io to find out.
Have fun!
"use strict";

var spark = require('spark');
var prompt = require('prompt');

var logged_in = false;
var DEVICE_NAME = "";

spark.on('login', function() {
  
  var stdin = process.stdin;
  stdin.setRawMode( true );
  stdin.resume();
  stdin.setEncoding( 'utf8' );
  stdin.on( 'data', function( key ){
    // ctrl-c ( end of text )
    if ( key === '\u0003' ) {
      console.log("EXITING NOW!");

      setTimeout(function(){
        process.exit();
      },1000);
        
    }

    if (logged_in) {
      if ( key === 'w') {
        console.log("Forward 500");
        spark.callFunction(DEVICE_NAME, 'cmd', 'f,100,500,');
      }
      else if ( key === 'a') {
        console.log("Left 100");
        spark.callFunction(DEVICE_NAME, 'cmd', 'l,100,100,');
      }
      else if ( key === 's') {
        console.log("Reverse 500");
        spark.callFunction(DEVICE_NAME, 'cmd', 'b,100,500,');
      }
      else if ( key === 'd') {
        console.log("Right 100");
        spark.callFunction(DEVICE_NAME, 'cmd', 'r,100,100,');
      }
    }
      
    // echo the keypress, if desired
    //process.stdout.write( key );
  });

});

// 
// Setting these properties customizes the prompt. 
// 
prompt.message = "SPARK LOGIN: ".cyan;
prompt.delimiter = "".cyan;
// 
// Start the prompt 
// 
prompt.start();

// 
// Get three properties from the user: username, password and device name (no need to type in that long ID) 
// 
prompt.get({
properties: {
      username: {
        description: "What's your username?".cyan
      },
      password: {
        hidden: true,
        description: "Now gimme da password!".red
      },
      device_name: {
        description: "What's the DEVICE NAME?".green
      }
    }
  }, function (err, result) {
  // 
  // Log the results. 
  // 
  // console.log('Command-line input received:');
  // console.log('  username: ' + result.username);
  // console.log('  password: ' + result.password);
  // console.log('  device_name: ' + result.device_name);

  spark.login({ username: result.username, password: result.password }, function(err, body) {
    logged_in = true;
    console.log('API call login completed on callback:', body);
  });

  DEVICE_NAME = result.device_name;

});

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Life Saver
Intermediate
  • 3,635
  • 72

Work in progress

Detect road accident, raise SOS, share location, share & monitor vital health stats during accident using Pebble. #SaveLife

Life Saver

Team Enigma

Pebble controlled DIY SmartGarage with the Sparkcore
Intermediate
  • 7,298
  • 97

Full instructions

Build it yourself and control your garage door with the Pebble Smartwatch and the Sparkcore

Smartwatch car remote
Intermediate
  • 11,070
  • 72

Full instructions

Controlling a car using a Pebble watch, an Android phone and an Arduino

RunTracker One
Intermediate
  • 924
  • 17

Work in progress

Go running with only one device - your smartwatch - and still enjoy all your music, GPS tracking, and more!

RunTracker One

Team Wesley Crushers

PebbleCannon
Intermediate
  • 941
  • 17

Vanquish your foes, control a nerf gun with your pebble watch.

WatchBot
Intermediate
  • 2,483
  • 31

Full instructions

Use the new Pebble Time watch to control a Sumobot using the accelerometer as a controller.

Add projectSign up / Login