Roomba robot class

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Wed Dec 01 19:20:43 2010 +0000
Commit message:
0.1 Untested

Changed in this revision

MODSERIAL.lib Show annotated file Show diff for this revision Revisions of this file
Roomba/Roomba.cpp Show annotated file Show diff for this revision Revisions of this file
Roomba/Roomba.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b26b94a6a065 MODSERIAL.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Wed Dec 01 19:20:43 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AjK/code/MODSERIAL/#c11ea36f17f9
diff -r 000000000000 -r b26b94a6a065 Roomba/Roomba.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Roomba/Roomba.cpp	Wed Dec 01 19:20:43 2010 +0000
@@ -0,0 +1,127 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    
+    @file          Roomba.cpp
+    @purpose       http://mbed.org/forum/mbed/topic/1476
+    @version       0.1 (untested)
+    @date          Dec 2010
+    @author        Andy Kirkham    
+    @see           http://mbed.org/forum/mbed/topic/1476 
+*/
+
+#include "Roomba.h"
+
+void
+Roomba::init(PinName tx, PinName rx)
+{
+    state = Idle;    
+    uart = new MODSERIAL(tx, rx);
+    tick = new Ticker;
+    uart->attach(this, &Roomba::cbSerial, MODSERIAL::RxIrq);
+    tick->attach(this, &Roomba::cbTicker, 0.1);   
+}
+
+int
+Roomba::command(RoombaState cmd, int opts, char *opt, bool block) {
+    if (state != Idle) return (int)NotIdle;
+    
+    // Impose our state on teh system. Use a loop to
+    // make sure no interrupt "nips in" and alters 
+    // the state machine.
+    while (state != cmd) {
+        state = cmd;
+    }
+    
+    // Send command.
+    uart->putc(cmd);
+    
+    // Send any additional option bytes.
+    if (opts > 0) {
+        for (int i = 0; i < opts; i++) {
+            uart->putc(opt[i]);
+        }
+    }
+    
+    // Wait until the serial characters have left the Mbed.
+    // Only do this is arg block is true (which is the default).
+    if (block) while (uart->txIsBusy() || uart->txBufferGetCount() != 0);
+    
+    // Return state back to idle
+    state = Idle;
+    
+    return cmd;
+}
+
+int
+Roomba::cmdSensors(CallType type)
+{
+    if (type == Invoke) {
+        if (state != Idle) {
+            return (int)NotIdle;
+        }
+        
+        // We are already in interrupt context
+        // so no need to loop here, nothing is
+        // going to interrupt us.
+        state = CmdSensors;
+        
+        // Flush the buffers and send teh command+opt
+        uart->rxBufferFlush();
+        uart->putc(CmdSensors);
+        uart->putc(0); 
+        
+        // Leave state in CmdSensors so nothing else can use the
+        // serial port until the CmdSensors has completed. See
+        // below where the command end is detected and terminated.
+    }
+    
+    if (type == SerialCallback) {
+        if (state == CmdSensors && uart->rxBufferGetCount() == 26) {
+            sensors8bit[bumpsWheeldrops]        =  uart->getc();
+            sensors8bit[wall]                   =  uart->getc();
+            sensors8bit[cliffLeft]              =  uart->getc();
+            sensors8bit[cliffFrontLeft]         =  uart->getc();
+            sensors8bit[cliffFrontRight]        =  uart->getc();
+            sensors8bit[cliffRight]             =  uart->getc();
+            sensors8bit[virtualWall]            =  uart->getc();
+            sensors8bit[motorOvercurrents]      =  uart->getc();
+            sensors8bit[dirtDetectorLeft]       =  uart->getc();
+            sensors8bit[dirtDetectorRight]      =  uart->getc();
+            sensors8bit[remoteControlCommand]   =  uart->getc();
+            sensors8bit[buttons]                =  uart->getc();
+            sensors16bit[distance]              = (uart->getc() << 8) | uart->getc();
+            sensors16bit[angle]                 = (uart->getc() << 8) | uart->getc();
+            sensors8bit[chargingState]          =  uart->getc();
+            sensors16bit[voltage]               = (uart->getc() << 8) | uart->getc();
+            sensors16bit[current]               = (uart->getc() << 8) | uart->getc();
+            sensors8bit[temperature]            =  uart->getc();
+            sensors16bit[charge]                = (uart->getc() << 8) | uart->getc();
+            sensors16bit[capacity]              = (uart->getc() << 8) | uart->getc();             
+            
+            // All done, release teh serial port back to idle.
+            state = Idle;                       
+        }
+    }   
+    
+    return Ok;
+}
+
+
diff -r 000000000000 -r b26b94a6a065 Roomba/Roomba.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Roomba/Roomba.h	Wed Dec 01 19:20:43 2010 +0000
@@ -0,0 +1,142 @@
+/*
+    Copyright (c) 2010 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+    
+    @file          Roomba.h
+    @purpose       http://mbed.org/forum/mbed/topic/1476
+    @version       0.1 (untested)
+    @date          Dec 2010
+    @author        Andy Kirkham    
+    @see           http://mbed.org/forum/mbed/topic/1476 
+    @require       http://mbed.org/cookbook/MODSERIAL
+*/
+
+#ifndef ROOMBA_H
+#define ROOMBA_H
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+
+/**
+ * @brief Class efinition of a Roomba robot.
+ * @author Andy Kirkham
+ * @see http://mbed.org/forum/mbed/topic/1476
+ * @see http://mbed.org/cookbook/MODSERIAL
+ *
+ * <b>Roomba</b> manages communications with teh robot.
+ * It exports a simple API to send commands or read
+ * sensor data.
+ *
+ * This module requires MODSERIAL
+ */
+class Roomba {
+public:
+
+    // States (and commands)
+    enum RoombaState { 
+          Idle = 0
+        , GetSensors
+        , CmdStart = 128
+        , CmdBaud
+        , CmdControl
+        , CmdSafe
+        , CmdFull
+        , CmdPower
+        , CmdSpot
+        , CmdClean
+        , CmdMax
+        , CmdDrive
+        , CmdMotors
+        , CmdLeds
+        , CmdSong
+        , CmdPlay
+        , CmdSensors
+        , CmdForceSeekingDock        
+    };
+    
+    // Calltypes and return types
+    enum CallType {
+          NotIdle = -1
+        , Ok = 0
+        , Invoke = 1
+        , SerialCallback    
+    };
+    
+    
+    // Indexes into array to select what var
+    enum Sensor8bit {
+          bumpsWheeldrops = 0
+        , wall
+        , cliffLeft
+        , cliffFrontLeft
+        , cliffFrontRight
+        , cliffRight
+        , virtualWall
+        , motorOvercurrents
+        , dirtDetectorLeft
+        , dirtDetectorRight
+        , remoteControlCommand
+        , buttons
+        , chargingState
+        , temperature
+        , NumOf8bitSensors
+    };
+    
+    // Indexes into array to select what var
+    enum Sensor16bit {
+          distance
+        , angle
+        , voltage
+        , charge        
+        , current
+        , capacity        
+        , NumOf16bitSensors
+    };
+    
+    Roomba(PinName tx, PinName rx) { init(tx, rx); }
+    ~Roomba() { delete uart; delete tick; }
+    
+    int command(RoombaState cmd, int opts = 0, char *opt = (char *)NULL, bool block = true);
+    
+    uint8_t  sensor(Sensor8bit  idx) { return sensors8bit[idx]; }
+    uint16_t sensor(Sensor16bit idx) { return sensors16bit[idx]; }
+    
+    // Interrupt callback functions.
+    void cbSerial(void) { cmdSensors(SerialCallback); }
+    void cbTicker(void) { cmdSensors(Invoke); } ;
+    
+protected:
+    int state;
+    MODSERIAL *uart;
+    Ticker    *tick;
+    
+    // Internal methods
+    void init(PinName tx, PinName rx);
+    int  cmdSensors(CallType type);
+
+    // Sensor values. Populated with data
+    // via ticker/serial interrupts. Available
+    // to the user program via the .sensor() API
+    // function.
+    uint8_t  sensors8bit[NumOf8bitSensors];
+    uint16_t sensors16bit[NumOf16bitSensors];
+};
+
+#endif
diff -r 000000000000 -r b26b94a6a065 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Dec 01 19:20:43 2010 +0000
@@ -0,0 +1,46 @@
+
+#include "Roomba.h"
+
+DigitalOut myled(LED1);
+Roomba roomba(p9, p10);
+
+int main() {
+
+    // Examples of sending commands. Note that when
+    // teh function returns, if it was successful
+    // it returns the command code. Otherwise it 
+    // will return Roomba::NotIdle which means it
+    // couldn't send the command because the serial
+    // port was busy reading sensor data.
+    int result = roomba.command(Roomba::CmdPower);
+    if (result != Roomba::CmdPower) {
+        // Failed to send command because the 
+        // serial port was busy getting sensor data
+    }
+    
+    // A sure fire way to make the command happen.
+    while (roomba.command(Roomba::CmdPower) != Roomba::CmdPower);
+    
+    // Some commands have additional bytes, heres an example
+    char leds[3];
+    leds[0] = 0x01; // First byte sent
+    leds[1] = 0x05;
+    leds[2] = 0x76; // Last byte sent
+    roomba.command(Roomba::CmdLeds, 3, leds);
+        
+    // Sensors are read automartically. Here's how we
+    // get the wall sensor and voltage values.    
+    uint8_t  wall    = roomba.sensor(Roomba::wall);    
+    uint16_t voltage = roomba.sensor(Roomba::voltage);
+    
+    // Note, when reading sensor data make sure your variable
+    // is of the right type, either uint8_t for single byte
+    // and uint16_t for double byte variables. 
+      
+    while(1) {
+        myled = 1;
+        wait(0.2);
+        myled = 0;
+        wait(0.2);    
+    }
+}
diff -r 000000000000 -r b26b94a6a065 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Dec 01 19:20:43 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e