Archive for the ‘Roomba’ category

PCB Fabrication Comments and New Roomba Controller Board

September 23, 2009

Since I last posted pictures of my Roomba controller board, I’ve created several other PCBs (not Roomba-related) and improved my design, toner transfer, etching, and soldering techniques. I was particularly nervous about putting the board into my robot, considering the amount of vibration and shock, so I decided to redo it.

New Roomba controller
New Roomba controller PCB
Shiny traces
Roomba art
PCB text

First problem: the copper traces were much to fine. During the toner transfer (TT), a couple of these tiny wires were missing or incomplete. Even worse, once I tried to solder the complete wires, the heat of my soldering iron burned up the wire if held there too long. I’ve discovered it’s favorable to make wires as wide as possible, even at the expense of breaking clearance rules (i.e., I changed my DRC clearance setting from 10mil to 5mil). It’s much easier to break shorts between traces after toner transfer by scraping off the toner with a razor blade. Even if a short is overlooked before etching, it’s possible to break the connection by scratching away excess copper.

Secondly, I read online that Brother printers (which I have) are inadequate for TT because the toner has a much higher “melting point,” which is hard to reach with an ordinary electric iron. Apparently a portion of toner is made up of plastic, and the goal of TT is to melt it so it bonds to the copper board. The toner is stuck to both the board and the paper, so you remove the paper by soaking it in hot water. For this new board, I printed on an HP printer with much better TT results. Further, I read that glossy magazine covers or magazine pages can be used instead of expensive photo paper. I achieved a nearly flawless transfer using _free_ spring break vacation brochures I found posted around school.

Spring break paper printouts

Thirdly, the iron doesn’t always transfer toner evenly and there’s no way to know for sure before you remove the paper. My girlfriend spotted a $15(!) personal laminator for sale at Aldi. Hobbyists mention their laminators frequently online but I never planned to buy one because they commonly cost between $30 and $120… I cautiously assumed you get what you pay for, but a $15 loss would not ruin me. Fortunately, it works great and it’s faster and easier than an iron, giving far better results. As before, I place the layout images on freshly scrubbed and alcohol-cleaned copper board, but instead of ironing, I pass it through the laminator at least 12 times (probably overkill, but one pass seems insufficient… I’ll experiment a bit later), and then soak the board. It’s not actually laminating, so there’s no need to use any special plastic pouches–it’s just applying heat and pressure. To increase the pressure, I taped the board to a folded paper six sheets thick. The extra thickness sometimes causes a jam, but I simply push the board through.

Laminator

Etching started as a very messy process, but I’ve worked out a clean and effective procedure. I fill up a plastic container with hot tap water. Then I put on rubber gloves, put the board into a reliable ziploc sandwich bag, and carefully pour a meager amount of ferric chloride acid into the bag. Seal the bag completely and place it in the hot water. Now the etching is contained, it’s being warmed, and it can be continuously agitated without touching the acid. If the water cools, I replace it as necessary until the board is etched. When I remove the board, I go out over the grass in my yard and carefully take the board out of the bag, then immediately pour water over the board and my gloved hand to rinse off the acid clinging to the board. Then I place the now-clean board directly into the water to dilute any remaining acid. Next, I liberally pour backing soda into the bag to neutralize the acid and hopefully leave the byproducts more basic than neutral. At this point, the residue seems to be “liquid rust” so it’s important not to spill it anywhere. I pull off my gloves and seal them in the bag, then throw out the bag. I’m not sure this is the best way to dispose of the byproducts, but I do try to use as little acid as possible, it should be less harmful once neutralized and it’s probably somewhat like throwing away rusty metal and copper. I’ve read some sites that suggest pouring the neutralized liquid down the drain and taking the precipitate to a waste management center, but I’m not sure this is much better.

Finally, I learned one more thing through error with this new Roomba board. When I removed the toner, I used nail polish remover as suggested on the web. As you can see in the pictures, the toner from the HP printer smudged all over the bare PCB, although it did clean off the copper traces. Using both acetone-based and acetone-free nail polish remover, the toner clung to the exposed board. Later I tried using my scrubber to mechanically remove the toner without any chemicals… this worked well, as is apparent in the upper-right portion of the board.

Regarding the tiny Roomba graphic in the corner of the board: I opened the official Roomba manual PDF in Inkscape and found a sketch of the Roomba itself as vector art. Before printing the layout, I scaled the graphic to fit the corner, placed it, and tiled the entire layout over the 8.5″x11″ canvas. It etched extremely well =)

Roomba Progress, 8/4/09

August 4, 2009

I recently updated the Roomba’s microcontroller program a little bit, then I decided to finally get to work on a printed circuit board (PCB) for the PIC. I was able to design the PCB with open source gEDA tools.

Here’s the schematic:
Roomba Controller Circuit

…and here’s the PCB layout:
Roomba Controller PCB Layout

I used the well-known “print layout on glossy photo paper, iron onto copperclad board, bathe in ferric chloride, scrub off toner with nail polish remover, drill with dremel tool” method to fabricate my board. Here it is before soldering:
Etched PCB

…and here I tilted it so the copper traces catch the light:
Etched PCB, Light Reflecting on Copper

I (poorly) soldered all of the components into place:
PCB, Components Soldered
…the underside:
PCB, Soldering Under Board

I learned quite a bit from my mistakes on this PCB. The traces I used are too thin and a couple were broken by either the toner transfer process or during the etch. Next time I’ll use thicker lines and iron it longer. I also tried to patch the lines with sharpie marker, which worked to some extent, but left some ugly black and gray stains all over the board. Some of the thin traces also burned up when I tried to solder in my jumper wire, so I won’t use the same solid copper wire next time. The big nasty solder blob is a repair to one of the broken traces.

Roomba Progress, 3/30/09

March 30, 2009

This week I did some work behind the scenes, but there’s nothing I can show off in terms of video or pictures.  I have essentially wrapped up my C++ class with some glue code to make it useable from within CMUCL.  The Roomba class itself is useful for controlling the Roomba in a C++ program (as demonstrated by my wiimote example), but it also conveniently organizes the Roomba functionality for Lisp programs.  The C++ class declaration is as summarized below:

class Roomba
{
private:
    ...
public:
    int connect(char *serialDevice);
    int disconnect();
    int launchThread();    // Thread for microcontroller comms
    int killThread();
    
    // Movement style 1 (Direct movement)
    int turnAndForward(float angle, float dist);
    // Movement style 2 (Car)
    int setVelocity(float vel);
    int setSteeringAngle(float angle);
    // Movement style 3 (Independent wheels, velocity-based)
    int setMotorVelocities(float velLeft, float velRight);
    // Movement style 4 (Independent wheels, distance-based)
    int moveMotors(float distLeft, float distRight);
    
    void getStatus(RoombaStatus *rs);
    float getApproxX();
    float getApproxY();
    float getApproxHeading();
};

I’ve used CMUCL’s Alien interface to enable foreign function calls to the C++ code.  C++ name mangling is a nuissance that prevents clean interfacing with Alien, so I elected to write a C++ wrapper that defines un-mangled functions (extern “C”)  that act on a single static Roomba object.  This wrapper compiles into a shared object (a.k.a. dynamic-link library or DLL) that can be manipulated in CMUCL.  Roomba object functions can be called from Lisp like this:

(turnAndForward 9.0 2.5) ;; Rotate 9 units, forward 2.5
(setf vL -1.0)
(setf vR 1.0)
(setMotorVelocities vL vR) ;; Rotate left, full speed

Unfortunately, I have nothing to show in this update because I haven’t written any Lisp programs that to take advantage of the new interface.  In addition to writing this interface, I’ve begun writing a final paper about my work.  My goals for next week are to write some interesting Lisp code based on a competitive Cognitive Robotics scenario I’m writing up in my paper, to try out some SNePS reasoning on top of Lisp, and possibly some additional hardware work (integrating the new battery, adding a webcam, and making a PCB for the microcontroller circuit).

Roomba Progress, 3/16/09

March 16, 2009

After establishing control over the Roomba through a wifi SSH connection, the next step was to begin working towards the same functionality from within Lisp.  I looked through SWIG’s documentation (tool for providing glue between different languages) and read about CMUCL’s Alien Object system for supporting foreign function calls.  Before completing this connection to Lisp, I began working on a class to wrap up all the functionality necessary for talking to the Roomba.  The fruit of my efforts so far is a partially-implemented class that currently supports all of the capabilities of my previous debug program.  I was quickly able to write a new debug program that creates a Roomba object and a connection to a Wii remote so that a user can move the Roomba by tilting the remote.  The Wiimote affords finer control than the arrow keys and the video below shows the result:

The remaining portion of the class consists of four different methods of controlling the Roomba, position estimation that will attempt to approximate the Roomba’s current x-y displacement and change in heading since it turned on.  The four movement methods are intended to make the Roomba movement feel different:

  1. Turn-and-forward:  This should feel closest to human movement.  Each step consists of first rotating the Roomba toward its desired target, and then moving a specified distance.  Either the turn angle or the distance can be zero, and a negative distance means backward.
  2. Velocity plus steering angle: This should feel like the way a car drives. The Roomba maintains a constant velocity and can be steered left or right, as though by a steering wheel.
  3. Independent motor velocity: This mode is closest to the way the Roomba is actually controlled.  Each motor turns at a different speed to produce linear and rotational movement.
  4. Independent motor distance: This mode will allow each motor to move a specified distance, then stop.

I will attempt to interface this class to Lisp through the Alien system and begin working on autonomous behaviors.  Soon it will begin looking more like a cognitive robot. I additionally need to incorporate a camera and use OpenCV to perform image processing.

Roomba Progress, 3/7/09

March 7, 2009

The robot is now fully wireless!  It’s amazing that I’ve gotten this far without a major setback like having something expensive burn out (knock on wood).

Since Monday, I have mounted the motherboard to the lid of the Roomba and squeezed the breadboard inside.  The breadboard doesn’t entirely fit, so the lid does not close all the way. Sometime soon I would like to solder the microcontroller circuit to a perfboard or a custom PCB so the circuit will fit inside.

Next, I soldered some wires to the battery terminals inside the Roomba to bring power up to the motherboard and its supply.  When I purchased the supply on eBay, the seller did not send me a short piece of wire that connects the supply to the motherboard’s power switch pins, so until I implement a better solution I have resorted to starting the motherboard by crossing the power switch pins with a coin.

These two changes mean the robot is now mobile.  Here’s some pictures and video clips:

One concern I have right now is that the robot appears to be quite zippy in the first minute of driving and noticeably slower as time goes on.  I fear that the computer may eat through the Roomba’s battery alarmingly fast.  If this is true, I can either get more batteries for the robot or remove the computer.  Since the motivation for having an entire on-board computer was to enable the robot to be a fully autonomous cognitive agent, it would be a shame to scale back the processing power.  As a precaution, last night I purchased a lead acid battery with almost twice the capacity of the original Roomba battery.  It will way almost four pounds and will be physically bulky, but it will triple the juice.

On the other hand, I can certainly scale back the processing by using any programmable device with a serial port (e.g., Gameboy Advance, PDA, graphing calculator, Cybiko, etc).  The drawback is that I would then need to wirelessly link to a base station computer that would run SNePS and execute vision algorithms.  I hope it doesn’t come to that, but it is appealing to consider the low-power design of something like a Gameboy… the Gameboy Advance SP lasts for something like 15 hours on its own rechargeable battery.

Whatever the case, it’s a relief to have the bulk of the electrical work done so I can focus on software.

Roomba Progress, 3/2/09

March 2, 2009

Last week I did some more testing, cut a hole in the Roomba’s circuit board housing, reassembled the whole thing (removing some unnecessary brushes and vacuum-related parts) so I can run the wheel motors without worrying about disturbing the electronics.

From there, I moved back to the Roomba’s onboard computer.  For weeks it has been powered by a generic ATX supply which means it could only use AC wall power.  I wired its so-far-unused OPUS DC-to-DC supply to a 12V bench supply and had some intermittent success–it would work for about 15 minutes at a time after which I assume the 12V supply overheated, though everything was fine again after it cooled off.  In an effort to provide better DC power, I cut the cord of an old 18V laptop supply and wired it to the OPUS.  The laptop supply stays cool and allows the computer to run indefinitely.  This should be useful for powering the computer when the Roomba battery is in the charger, so I hope to attach matching power plugs to the laptop supply and the battery terminals and put a power jack on the OPUS so that I can quickly swap supplies.  I’m also brainstorming ways of “hot-swapping” the supplies so I can place the computer on AC power without shutting it down.

My final step was to get my debug program to run on the Roomba’s computer and add a “manual mode” that allows me to easily drive it around with the arrow keys.  I’m now able to boot up the computer without attaching a display or keyboard, SSH into its ad-hoc wireless network and drive it around. See the video below.

TO DO:

  • Wire the OPUS supply to the battery
  • Securely mount the supply, computer, and breadboard to the Roomba
  • [Possibly] integrate plugs and jacks into the power wiring
  • Move ahead with Lisp, SNePs, cameras, and OpenCV

Roomba Progress, 2/23/09

February 23, 2009

Not much progress this week.  I’ve just connected all the I/O wires to the breadboard and written a little program to control the outputs and interactively view the input states.  Everything “works” on the desk right now, but I’ll record a video once I’ve tucked away all the wires so it can roam free.

Roomba Progress, 2/16/09

February 16, 2009

As of February 16th, quite a bit has changed. Firstly, I’ve finished reverse engineering the Roomba circuit board and spent some time getting reacclimated to PIC microcontroller assembly language.  This took longer than I had hoped, but a week ago today I put a PIC 18F4550 MCU into a breadboard and began actual coding.  Gradually I brought the various subsystems online as I worked toward decent functionality for the robot.  Simultaneously, I finished up the process of assigning general purpose I/O pins to the Roomba’s peripherals.  Here’s is a link to my reverse-engineering spreadsheet:

View ‘Roomba Reverse-Engineering Spreadsheet’

Fast-forward to this weekend:  I now have the PIC receiving serial commands.  If I send the single-byte command ‘S’, the PIC responds with a five-byte status packet organized as follows:

struct StatusPacket {
byte type = ‘S’;
byte flags1;        // 8 sensor bits
byte flags2;        // 4 more bits
byte leftEncoder;    // keep a circular counter of encoder position…
byte rightEncoder;    // … increment when bot is being moved FW, decrement for REV
}

When I send five-byte command of the following format…

struct CommandPacket {
byte type = ‘C’;
byte flags;        // 2 L/R direction bits, 2 motors, 3 leds, 1 led color
byte speakerTone;    // 8-bit frequency (map to 16-bit, C-scale frequencies?)
byte leftMotor;        // 8-bit duty
byte rightMotor;    // 8-bit duty
}

… the Roomba updates the states of various motor and LED pins, and updates the duty cycle values of the main wheel motors.  The speed of the wheel motors can be varied via a duty cycle which provides power to the motor pin for the fraction (MotorDuty/255) of the internal timer’s overflow period.  Low duty values result in a slow speed, high values result in high speed.  Note that the speaker tone is non-essential so I have not implemented it yet.

With all of this in place, I began soldering to the Roomba control board:

You can click individual images to get a bigger view.  Click the resulting image to view full-size.  The second-last image shows my first test of the Roomba connected to the PIC.  The PIC is monitoring the state of one of the infrared sensors, sending its status as a single bit in the Status packet.  When I place my hand in front of the sensor, one of the bytes changes from ‘R’ to ‘Z’, then back to ‘R’ when my hand is removed.  This is a huge step because the small PC that will sit on top of the Roomba now has a means to obtain information about the Roomba’s sensors.  When it sees that there is an obstacle in front of the sensor, it can stop moving forward and turn to avoid the obstruction.

February 2nd Update

February 2, 2009

This week I painstakingly disconnected all of the wires attached to the Roomba’s PCB, documented each connection, unscrewed a few components, and I finally extracted the PCB.  I had originally hoped enough of the circuit board would be exposed so I could avoid the hassle, but no such luck.

cimg3652cimg3664

cimg3672

cimg3675

The board is relatively simple; it seems to be no more than a bunch of driver circuits for its motors and sensors. Yet I’m inexperienced at reverse-engineering electronic circuits.  Surprisingly, the process was time consuming, but not too difficult.  I now have a spreadsheet containing information about which CPU pins interface with which other parts of the circuit.  I believe I now have as much data as I can possibly obtain through inspection, so next I plan to reconnect it to the Roomba peripherals and run it in debug mode.  Debug mode will allow me to determine what the CPU must do to operate the Roomba.  Afterward, I should be able to remove the original CPU and replace it with a microcontoller.

On the PC front, I set up a wireless adapter on the motherboard and configured VectorLinux to connect to an ad-hoc network automatically.  From another computer, I can now SSH into the Roomba computer.  I’ve also installed CMUCL (Common Lisp) and placed a copy of SNePs on the CF card. Next I need to power the board from the Roomba battery using the automotive ATX powersupply I purchased and write a program to communicate with the microcontroller.

cimg3673cimg3674

Cognitive Robot – Summary up to January 26th

February 2, 2009

This is the first of many (fingers crossed) frequent (toes crossed, too) posts detailing the progress of my cognitive robot.  I will use this blog to document the development process, share my project with friends and classmates, and to aid me in making weekly presentations about the robot.

Here’s a summary of what’s happened so far:  This semester, I registered for a “Cognitive Robotics” seminar in which students are required to buy/aquire a robot and somehow program it to perform an interesting task through reasoning.  It was suggested that we buy a suitable robot over winter break so we could begin working at the beginning of the semester.  I chose to put my electrical engineering skills to use hacking together my own custom robot to save money and gain flexibility.

Over the break I bought a first-generation iRobot Roomba to use as a starting point. At about $30, it was cheap, but I still have a lot of extra work ahead of me getting it to the point where it can reason. In short, newer Roombas have a serial port that allows external computers to tell them what to do, and iRobot’s Create is even better because it is intended to be a workhorse robot. Instead, I must open up my Roomba, learn how it works, rip out it’s brain (CPU), and replace it with my own microcontroller brain.  The microcontroller will then talk to a small computer mounted on top of the Roomba, enabling the Roomba to do the computer’s bidding.  It gets a little more complex than that, but not much. Next I’ll outline that extra complexity, so skip it if you aren’t interested.

I think about my robot in three layers: the Roomba & microcontroller, the PC running a C application, and a Lisp application.  The microcontroller solely collects commands from the PC via its serial port, it carries out these commands in the form of moving the Roomba, and it sends sensor data back up to the PC.  The PC is a small FlexATX motherboard with an integrated processor and 4GB compact flash card.  The PC runs VectorLinux Light (based on Slackware).  It will run standard applications and I will be setting up an SSH server and wifi so I can log into robot while it is online. The PC will have one or more cameras directly installed to supplement the sensory input acquired by the Roomba.  The planned C application will process the video and sensory input to medium-level tasks such as object recognition, movement planning, and obstacle avoidance.  Hopefully, the middle layer (‘behavioral’ layer?) will be robust enough to provide meaningful facts to the highest layer (‘cognitive’ layer?). By this point, Lisp and SNePs will be used to process facts and beliefs in order to enslave mankind :P.  I don’t know a great deal about knowledge representation and reasoning, so with any luck, the details of the cognitive layer will materialize in the coming weeks.

By classtime on January 26th, I had purchased all of the parts I need at the moment and presented a summary of cost and showed some pictures of my progress:

  • Roomba            ~$45
  • Battery              ~$33.49
  • Rapid Charger      $15
  • 4GB CF card        $45.62 – ($40) = $5.62
  • CF-to-IDE             $3
  • FlexATX mobo   ~$40 – ($20??) = $20
  • Car ATX Supply    $7.75
  • Total:                ~$130

I had installed Linux on the CF card, verified that the Roomba was undamaged, and begun disassembling it. The next step was to extract the circuit board inside the Roomba and begin reverse-engineering its functionality. I have some notes written by a team that hacked a Gen. 1 Roomba years ago, so I know that the motor drivers are active-low.  That means I can begin writing my PIC microcontroller code and designing its circuit even before I am ready to solder to the Roomba itself.  My plans for the robot are to implement some form of stereopsis (3D image processing) using one or more cameras and to run Lisp directly on the robot.


Design a site like this with WordPress.com
Get started