Desk Roomba

I. Description

Profile view of the Desk Roomba

The Desk Roomba aims to autonomously collect small debris off the surface of a desk. An ultrasonic sensor mounted on the front of the vehicle measures the distance away the surface the Roomba will traverse is. A simple thresholding statement allows the Roomba to determine whether an edge is in sight. As an edge is detected, the on-board LEDs will display a pattern and an audio tune will be heard; the vehicle then reverses and returns to sweep a new area without falling off the edge of the desk. Bluetooth capability allows the user to make minute adjustments to the vehicle's trajectory and can change the speed of the vehicle, in turn effecting the speed of the sweep. An LED and audio interrupt is added to denote the detection of an edge.

II. Setup

Structural Assembly

Customized Shadow Bot Chassis View from the front of the Roomba showing the connections with the ball-in-socket Lego components

In order to accommodate the sweeping capability of the Desk Roomba, only the base plate of the Shadow Bot Chassis is used to secure the two DC motors. The spacers provided in the kit are repurposed to hold two ball-in-socket Lego components for better weight distribution. The image above shows the view from the nose of the Desk Roomba, demonstrating the connection and placement of the ball-in-socket Lego components, as well as the inverted position of the Shadow Bot chassis.

Sweeper

This project used Swiffer Duster sheets to take advantage of their inherent ability to collect debris, however any sort of rotary brush would work in this application. The sheets were attached to the axles of the motors to sweep as the vehicle runs. A small divider is placed between the two sweepers to prevent entanglement of the brush fibers. The sweeper and its divider can be seen in an image in the previous section.

Breadboards Top view

Bottom view

Above, depicts the two breadboards attached to the top and bottom of the Shadow Bot chassis. The top breadboard is used to house the mbed, speaker, bluetooth module, and H-Bridge; the bottom breadboard is used to hold the ultrasonic sensor for edge detection.

HOW TO

With the modified Shadow Bot chassis and repurposed ball-in-socket supports, snap the supports into place at the front of the vehicle. Remove the adhesive to the larger breadboard and place on top of the chassis, so that at least one inch overhangs the edge of the chassis; the smaller breadboard should be anchored to the overhang of the larger breadboard. This creates a ledge for the ultrasonic to be attached to and allows the vehicle to detect an edge before the ball-in-socket supports encounter it.

Sweeper axle connection A straw is used as an axle for the sweeper. The Swiffer Duster is sewn onto the straw, with small slits being cut on either side of the straw to accommodate for the larger motor stem. A combination of thread and super glue were used to secure this component as shown in the image above. After assembling and securing the two individual sweepers on each motor, a divider should be placed to prevent entanglement, as well as allow for the motors to independently move.

III. Hardware

Speaker

mbedSpeaker
p18+
gnd-

Bluetooth

mbedAdafruit BLE
gndgnd
Vin (3.3-5V)Vin
ncRTS
gndCTS
p14TXO
p13RXI

H-Bridge

mbedH-BridgeLeft MotorRight Motor
VoutVM
Vin (3.3-5V)Vcc
A01+
A02-
B02-
B01+
gndgnd
p26PWMA
p25Ain2
p24Ain2
VoutStby
p23Bin1
p22Bin2
p21PMWB

Ultrasonic Sensor

mbedHR-SR04
Vin (3.3-5V)Vcc
gndgnd
p6trig
p7echo

IV. Additional Parts Used

Listed below are the specific materials used for this iteration of this project. Materials for the sweeper and divider, as well as the means to support the configured Shadow Bot chassis can all be changed to fit your needs.

V. Video

VI. Code

main.cpp

#include "mbed.h"
#include "motordriver.h"
#include <stdio.h>
#include  "Speaker.h"
#include "rtos.h"
#include "ultrasonic.h"

BusOut myled(LED1,LED2,LED3,LED4);
Serial blue(p13,p14);
Motor right(p21, p22, p23, 1); // pwm, fwd, rev, has brake feature
Motor left(p26, p25, p24, 1);

// Debugging tools
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
Serial pc(USBTX, USBRX);

Speaker speaker(p18);

double distance;
double holdDistance;
int status;

float defaultLeft = -0.6;
float defaultRight = -0.6;
float vl = -0.6;
float vr = -0.6;
float temp;


/*
Function is called when there is a massive distance 
differential detected in dist() denoting an edge detected
*/
void movementInterrupt() {
    //avoid abrupt speed changes
    left.speed(0);
    right.speed(0);
    wait(0.5);
    
    //goes backwards for 0.5s
    left.speed(-1 * defaultLeft);
    right.speed(-1 * defaultRight);
    wait(0.5);
    
    //avoid abrupt speed changes
    left.speed(0);
    right.speed(0);
    wait(0.5);

    // turn 90
    left.speed(0.8);
    right.speed(-0.8);  
    wait(0.5);
    
    //avoid abrupt speed changes
    left.speed(0);
    right.speed(0);
    wait(0.5);

    //goes forwards for 0.5s
    left.speed(defaultLeft);
    right.speed(defaultRight);
    wait(0.5);
    
    //avoid abrupt speed changes
    left.speed(0);
    right.speed(0);
    wait(0.5);
    
    // turn 90
    left.speed(0.8);
    right.speed(-0.8);  
    wait(0.6);
    
    // return to default speed
    left.speed(defaultLeft);
    right.speed(defaultRight);
    wait(0.5);
}

/*
Will create an audio and LED notification, called 
when an edge is detected 
*/
void speakerInterrupt() {
    led1 = 1;
    wait(0.05);
    led2 = 1;
    wait(0.05);
    led3 = 1;
    wait(0.05);
    led4 = 1;
    wait(0.05);
    led1 = !led1;
    led2 = !led2;
    led3 = !led3;
    led4 = !led4;
    for (int i = 0; i < 3; i++) {
        speaker.PlayNote(969.0, 0.3, 5.0);
        speaker.PlayNote(800.0, 0.3, 5.0);
        
    }
}
/*
Function is called when checkDistance() detects a distance differential
*/
void dist(int distance) { 
    // code executes when distance has changed 
     //pc.printf("Distance %d mm\r\n", distance);

    if (abs(distance - holdDistance) > 100) {
        //pc.printf("MOVEMENT INTERRUPT\n");
        movementInterrupt();
        left.speed(defaultLeft);
        speakerInterrupt();
    } else {
        led1 = 0;
    }
    holdDistance = distance;
}

// ultrasonic intialization -- much proceed dist() declaration
ultrasonic mu(p6, p7, .1, 1, &dist);

/*
checkDistance() run constantly probing for distance differentials
*/
void thread1(void const *args) {
    // ultrasonic sensor 
    while(true) {
        mu.checkDistance(); 
        //Thread::wait(1000);
    }
}

//Thread thread;
int main() {
    Thread t1(thread1);

    // Default speed
    left.speed(vl);
    right.speed(vr);
    wait(1);
        
    // Initialize ultrasonic sensor
    mu.startUpdates();//start measuring the distance
    
    char bnum=0;
    char bhit=0;
    while(1) {
        if (blue.getc()=='!') {
            if (blue.getc()=='B') { //button data packet
                bnum = blue.getc(); //button number
                bhit = blue.getc(); //1=hit, 0=release
                if (blue.getc()==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
                    //myled = bnum - '0'; //current button number will appear on LEDs
                    switch (bnum) {
                        // Let up and down arrow control speed of the sweeper
                        // Let right and left do motor correction control
                        case '1': //number button 1
                            if (bhit=='1') {
                               movementInterrupt();
                               left.speed(defaultLeft);
                               speakerInterrupt();
                                wait(0.1);
                            } 
                            break;
                        case '2': //number button 1
                        if (bhit=='1') {
                           left.speed(defaultLeft);
                           right.speed(defaultRight);
                        } 
                        break;
                        case '5': //button 5 up arrow
                            if (bhit=='1') {
                                led1 = !led1;
                                wait(0.5);
                                if (vl > -1.0 && vl < 0.0) {
                                     vl = vl - 0.1;
                                }
                                if (vr > -1.0 && vl < 0.0) {
                                    vr = vr - 0.1;
                                }
                            } 
                            break;
                        case '6': //button 6 down arrow
                            if (bhit=='1') {
                                led2 = !led2;
                                if (vl < 0.0 && vl > -1.0) {
                                     vl = vl + 0.1;
                                }
                                if (vr < 0.0 && vl > -1.0) {
                                    vr = vr + 0.1;
                                }
                            }
                            break;
                        case '7': //button 7 left arrow
                            if (bhit=='1') {
                                temp = vl;
                                vl = vl - 0.1;
                                left.speed(vl);
                                wait(1);
                            } else {
                                // Resets speed to default
                                vl = temp;
                            }
                            break;
                        case '8': //button 8 right arrow
                            if (bhit=='1') {
                                temp = vr; 
                                vr = vr - 0.1;
                                right.speed(vr);
                                wait(1);
                            } else {
                                // Resets speed to default
                                vr = temp;
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        left.speed(vl);
        right.speed(vr);
    }
}

Links to Libraries

Authors: Hope Hong, Matthew Lee


Please log in to post comments.