Andy K
/
Roomba
Roomba robot class
Revision 0:b26b94a6a065, committed 2010-12-01
- Comitter:
- AjK
- Date:
- Wed Dec 01 19:20:43 2010 +0000
- Commit message:
- 0.1 Untested
Changed in this revision
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