Posted by: ViennaMike | April 10, 2012

Recommended: Udacity’s CS373: Programming a Robotic Vehicle

I haven’t posted recently because I haven’t had time to mess with my robots.  Instead, my free time has been taken up with learning more theory, via Udacity’s free 7-week class.  There will be a new session starting next month, and I highly recommend that you check it out.

The class gives a broad but hands-on introduction to key robotic concepts and algorithms.  It covered localization,  filtering (monte-carlo, Kalman, and particle filters), pathfinding (intro to A*, dynamic programming, etc.), PID (Proportional Integrated Differential) control, and something called graph SLAM (Simultaneous Localization and Mapping). If you’re already well-versed in one or more of these, you probably won’t learn anything new on that subject, but if you’ve only a passing or no familiarity, the course is great.

The format for Udacity’s courses is what really stands out: short 5-10 minute videos with a question or short programming assignment at the end.  It’s a slightly higher tech Khan academy: mostly an electronic whiteboard and pen, but some videos from Google’s autonomous vehicle and the DARPA challenge.  The programming is done in python and submitted directly from the web page (although I recommend an IDE for the weekly homework programming).

Beyond the robotics course, I think this is starting on the path to the future of college education.  I think it’s much like newspapers and the print Encyclopaedia Britannica.   They have valuable features that the online experience can’t duplicate, but the cost differential is just too great to sustain the old model.  When you can offer a college level course to thousands of students at once, on-line, and crowd-source support to partially make up for the lack of direct, 1 on 1 help, it’s hard to imagine that, in 10-30 years, this won’t be the future of a college degree.  Now, it’s not there yet.  This was a beta run, and the numerous glitches and automated grading problems made that abundantly clear.  In addition, there’s a lot to work out, especially for non-tech courses.  But, compared to $10-$50K per year for a college resident degree?  I think I may have seen the future of education.

Make Magazine’s blog had an interesting item on how researchers in the U.K. have automated a long, repetitive process by using Lego Mindstorms NXT robots. The researchers are working on automated bones, and building up the material involves repeatedly dunking the substrate in various liquids in a certain order.  Rather than buy expensive equipment dedicated to this application, they put some Mindstorms robots together and programmed them.

A second item of interest comes from Udacity’s Programming a Robotic Car course.  The course is in beta (as are all their courses) and still has some rough edges (e.g., in the automated grading of programming homework), but the course is fascinating and well-taught.  I find it to be good value for the time committed and the courses are free.  In any event, there’s an interesting video showing a visualization one of the cars in the DARPA challenge detecting the barriers in the maze it’s in and using it’s A* pathfinding algorithm to determine its path.  The video also shows the car dealing with a complete roadblock and parking itself.

Posted by: ViennaMike | February 24, 2012

An Open HW/SW API for Your Car

Today’s post is a bit of a diversion, but I think it will be of interest to almost everyone interested in hobby robotics.  Rather than about robotic vehicles, it’s about a new system in development that will let us develop our own apps based on data from the full-sized car you drive around in.  About 5 years ago in my day job, I argued the future of in-vehicle electronics would include an automaker supported read-only interface to the data bus, available to third party developers to build upon.  Many auto company engineers I worked with stated this would never happen and never be supported.  Well, for some car companies, #define  NEVER  5

Introduction

“Many companies are already offering tools to hook into the driver’s interface, but for the most part they have limited availability for hobbyists and developers. What if the system was designed from the ground up to be open source and to give insight into the vehicle itself?”  This sounds like a Maker’s daydream, but it’s about to be reality, at least for Ford owners.  Ford Motor Company and Bug Labs have teamed up to produce the OpenXC Platform, now in limited beta testing.

This will provide read-only access via USB to many vehicle parameters in real-time, allowing developers, including hobbyists, to write applications running on whatever hardware they choose to interface.  The system is currently in limited beta testing.  According to press reports, beta testers include the University of Michigan, MIT, Stanford, Weather Underground, and India’s HCL Technologies.

Background

All modern cars use a data bus, the CAN bus, for exchanging information between the various electronic controller modules and other devices found on today’s cars.  One device on the bus provides a port for accessing the bus.  It is often found somewhere near the driver under the dashboard.  This On Board Diagnostics II (OBD-II) port is required by law, as it is used to check for proper operation of air pollution control equipment.    However, once it was required, automakers began using it as a general diagnostics port.  There are standard codes for much of the data, however automakers are not required to support most of these codes, and also typically add proprietary codes. The codes and their availability also vary by model and model year.

the OpenXC Platform

Based on my reading of the project's website,  the project provides a read-only interface (called the CAN translator module) that takes data from the OBD-II port, translates it into non-proprietary codes, and makes it available over a USB port.  Apparently the hardware in the reference implementation uses a ChipKit board, which uses a PIC microcontroller but can run Arduino code, along with a network shield.   They state that the initial testers have access to the C code, but I'm wondering if it will be released to hobbyists, as it may give insights into Ford's proprietary codes (they imply as much, stating that automakers might just supply compiled code).  You can plug whatever you want into the USB port, but they are developing a reference implementation built around an Android tablet computer.

While there are over 100 data elements available from the OBD-II, they are starting with support for just a subset, which can be found on the project's Signal Translation Specification page.  They include:

  • steering wheel angle
  • engine_speed (RPM)
  • vehicle speed
  • accelerator pedal position
  • brake pedal status
  • odometer
  • fuel level
  • fuel consumed since restart
  • windshield wiper status
  • latitude and longitude (presumably only for GPS-equipped vehicles)

As I mentioned above, codes vary by make, model, and year.  Currently, the system is said to support Ford 2011/2012 Focus, 2012 Mustang, 2012 Fiesta, and 2011 Figo.  While limited to Fords at present, they hope that this becomes a broader de facto standard.

I think this is a taste of exciting things to come, and I'd love to get my hands on a developer kit.

Picture from http://openxcplatform.com/developers/vehicle-interface/assembly.html,  used under Creative Commons Attribution 3.0 License.

Posted by: ViennaMike | February 19, 2012

Measurement Precision versus Control Precision

Spent some time today chasing down a problem that’s probably obvious to experienced developers, but it wasn’t to me, and I’ll guess to other newcomers.  There’s obviously a limit to both the position and heading precision that can be obtained purely through odometry based on wheel encoders.  For distance traveled in a short delta of time, the precision is a function of the smallest fraction of wheel rotation you can measure and the wheel diameter.  For heading, it’s also a function of the wheelbase (the distance between the wheels on each side).  The heading precision tends to be much poorer than the distance.   For example, if I can measure 1/8th of a revolution of a 1″ diameter wheel, I can measure increments of 1/8 x pi x 1 = 0.39 inches.  If the wheelbase is 4 inches, and I’m using tank style steering, then the smallest heading increment I can measure is pi * ( 1/8 * 1) / 4 = 0.098 radians or about 5.6 degrees.  That lack of precision is one factor in the errors that can build up very quickly when making a number of turns.  (Slippage can also be a major contributor to the error).   [The Using Dead Reckoning section in Enabling Your Robot to Keep Track of It's Position from Ridgesoft has a good explanation of this]

When trying to use dead reckoning to turn, you typically can’t get the measured heading to exactly match the desired heading due to these precision limits, so you have to set a window defining “close enough.”  So far, so good.  In my case, I’m using interrupts to count clicks on each of two wheel encoders, so I could be sure not to miss a unit.  All was working well.  In tests, I’d see 0 or 1 click of the encoder on each wheel each time my Arduino code executed the main loop and updated the position and heading.  I set my “close enough” threshold accordingly.  Then I added doubled the resolution on the encoders and added a lot of serial.print() commands when in debugging mode.  Suddenly my formally working robot, which now had more precise navigation, would go haywire.  It would often work fine, but at other times it would spin around in multiple circles when turning to the next waypoint or avoiding an obstacle.

It took a lot of debugging to figure out the problem. With interrupts now occurring with twice the frequency, and the execution loop slowing down due to numerous serial print statements, there were often 3-4 encoder clicks per update.   This meant that the robot was sometimes turning 4x more than the maximum precision of my measurements between execution of the appropriate code in the main loop.  Therefore it would sometimes, by luck, hit within the good enough window when turning, but other times it would be below the window on one pass and above it the next, and therefore keep turning and turning until by luck it hit within the window.  My control precision was only 1/4 of my measurement precision.

I’ve done three things to adjust:

  1. Ensure that don’t have the debugging serial.print() statements in except when doing a “bench test.”  (see the use of the #if preprocessor directive if you’re new to C or Arduino programming).  That speeds up loop execution.
  2. Slow down the turning speed of the robot.  By turning slower I can get the control precision to more closely match the measurement precision.
  3. Relax the window slightly, making control a bit sloppier, but ensuring I don’t miss the window if adjustments 1 and 2 weren’t sufficient.

Posted by: ViennaMike | February 8, 2012

The Coming World of 3D Printing

Cube 3D PrinterWithin a decade or two, 3D printers may do for physical objects what digitization did for books, movies, and music.  Another phase of the revolution is coming, with the digital world moving more into the physical.  Along one front there’s the Internet of Things, as physical objects become “smart” and linked to the Internet.  At the other front there’s digital home printing of physical 3D objects, from jewelry to replacement parts, and even candy sculptures.

3D printers are starting to get some mainstream media attention, including an appearance on the Colbert Report and a recent ABC News article. Like computers before them, they’ve already broken out of the business world and are moving into the consumer market.  I’d say we’re now moving past the early Altair phase and about to enter the Apple II explosion.  MakerBot is on their 3rd generation with their new Replicator.  Meanwhile the competition for the home market is heating up, with competitors like the Cube and the larger, but still rather pricey 3D Touch.  Meanwhile the iModela takes a different approach.  It’s a desktop CNC milling machine rather than an additive printer.   Except for the 3D Touch, the prices aren’t that far away from the $1298 that the original Apple II would have set you back when it was introduced, WITHOUT adjusting for inflation.

Make no mistake, this won’t be a passing fad.  Like a lot of technology, it may take a bit longer to get established than the hype would suggest, but its going to happen.  Stories are often a much better way to make a point than facts and figures, and thanks to Cory Doctorow’s ability to write and willingness to release his material under a Creative Commons license, there’s a great 1-page story on the disruption these things are going to cause (there’s also an audio version):

Printcrime by Cory Doctorow

(Originally published in Nature Magazine, January 2006)

The coppers smashed my father’s printer when I was eight. I remember the hot, cling-film-in-a-microwave smell of it, and Da’s look of ferocious concentration as he filled it with fresh goop, and the warm, fresh-baked feel of the objects that came out of it.

The coppers came through the door with truncheons swinging, one of them reciting the terms of the warrant through a bullhorn. One of Da’s customers had shopped him. The ipolice paid in high-grade pharmaceuticals — performance enhancers, memory supplements, metabolic boosters. The kind of thing that cost a fortune over the counter; the kind of thing you could print at home, if you didn’t mind the risk of having your kitchen filled with a sudden crush of big, beefy bodies, hard truncheons whistling through the air, smashing anyone and anything that got in the way.

They destroyed grandma’s trunk, the one she’d brought from the old country. They smashed our little refrigerator and the purifier unit over the window. My tweetybird escaped death by hiding in a corner of his cage as a big, booted foot crushed most of it into a sad tangle of printer-wire.

Da. What they did to him. When he was done, he looked like he’d been brawling with an entire rugby side. They brought him out the door and let the newsies get a good look at him as they tossed him in the car, while a spokesman told the world that my Da’s organized-crime bootlegging operation had been responsible for at least twenty million in contraband, and that my Da, the desperate villain, had resisted arrest.

I saw it all from my phone, in the remains of the sitting room, watching it on the screen and wondering how, just *how* anyone could look at our little flat and our terrible, manky estate and mistake it for the home of an organized crime kingpin. They took the printer away, of course, and displayed it like a trophy for the newsies. Its little shrine in the kitchenette seemed horribly empty. When I roused myself and picked up the flat and rescued my peeping poor tweetybird, I put a blender there. It was made out of printed parts, so it would only last a month before I’d need to print new bearings and other moving parts. Back then, I could take apart and reassemble anything that could be printed.

By the time I turned eighteen, they were ready to let Da out of prison. I’d visited him three times — on my tenth birthday, on his fiftieth, and when Ma died. It had been two years since I’d last seen him and he was in bad shape. A prison fight had left him with a limp, and he looked over his shoulder so often it was like he had a tic. I was embarrassed when the minicab dropped us off in front of the estate, and tried to keep my distance from this ruined, limping skeleton as we went inside and up the stairs.

“Lanie,” he said, as he sat me down. “You’re a smart girl, I know that. Trig. You wouldn’t know where your old Da could get a printer and some goop?”

I squeezed my hands into fists so tight my fingernails cut into my palms. I closed my eyes. “You’ve been in prison for ten years, Da. Ten. Years. You’re going to risk another ten years to print out more blenders and pharma, more laptops and designer hats?”

He grinned. “I’m not stupid, Lanie. I’ve learned my lesson. There’s no hat or laptop that’s worth going to jail for. I’m not going to print none of that rubbish, never again.” He had a cup of tea, and he drank it now like it was whisky, a sip and then a long, satisfied exhalation. He closed his eyes and leaned back in his chair.

“Come here, Lanie, let me whisper in your ear. Let me tell you the thing that I decided while I spent ten years in lockup. Come here and listen to your stupid Da.”

I felt a guilty pang about ticking him off. He was off his rocker, that much was clear. God knew what he went through in prison. “What, Da?” I said, leaning in close.

“Lanie, I’m going to print more printers. Lots more printers. One for everyone. That’s worth going to jail for. That’s worth anything.”

Creative Commons License Deed

Attribution-NonCommercial-ShareAlike 2.5

You are free:

* to Share — to copy, distribute, display, and perform the work
* to Remix — to make derivative works

Under the following conditions:

* Attribution. You must attribute the work in the manner specified by the author or licensor.

* Noncommercial. You may not use this work for commercial purposes.

* Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

* For any reuse or distribution, you must make clear to others the license terms of this work.

* Any of these conditions can be waived if you get permission from the copyright holder.

Disclaimer: Your fair use and other rights are in no way affected by the above.

This is a human-readable summary of the Legal Code (the full license)

My first robot, MARV-1, uses a small, commercial tracked chassis.  It uses dead reckoning from wheel encoders (only) for navigation, and a single front-mounted ultrasonic sensor for obstacle avoidance.  While I could get fancier on sensors and tweak the control more (e.g., add proportional feedback between the wheel encoders and the motor PWM control to keep on course better), I figure I’m nearing the end of the development and testing I want to do on this first robot.

For MARV-2, my second robot,  I want to build a new vehicle with GPS and other sensor systems suitable for outdoor navigation, and I want something that covers ground more quickly.  I figure an R/C conversion will fit the bill.  I’ve started looking into this, and it seems that it’s not too difficult.  It also seems that it’s easier on a “hobby” class R/C vehicle than a cheap toy one.  Many hobby class cars, it seems (from my online research) utilize standard 3-wire servo connections, sometimes with an electronic controller between the R/C unit and the drive and steering controls.  Cheaper toy cars have a circuit board you need to cut wires from and solder new connections on.

AVC 2010 Poster

Poster for Sparkfun's 2010 AVC competition

Sparkfun Electronics runs an annual Autonomous Vehicle Competition, and several competitors from past years have blogs with useful information for developing autonomous vehicles from R/C cars.  Three blog postings that seem to provide a lot of good information are Overdue AVC Specifications, Team Zyzzyx” SparkFun AVC 2011 Ground Entry, and Data Bus: the Nickel Tour.

The video podcast The Latest in Hobby Robotics has several videos on modifying R/C cars.  The two I’ve found that are most relevant are The Latest in Hobby Robotics 17, which focuses on modifying higher end cars and The Latest in Hobby Robotics 18, which demonstrates modding a cheaper toy-style R/C car.

An additional link that’s worth pointing out, especially if you’re modifying a toy R/C car, is Autonomous R/C Car – Part 1 – Reverse Engineering Signals.

I suspect it will be a while before I wrap up work on MARV-1 and have the time to start MARV-2, but the information these other hobbyists provide a lot of good guidance for getting started.

Posted by: ViennaMike | January 30, 2012

An Introduction and Example of Finite State Machines

Finite State Machines (FSM) are often an excellent design pattern for robot control software. As I was developing my first robotic vehicle, I started with just modifying and expanding upon some sample code I found online.  This worked for a robot moving around at random, avoiding obstacles.  But once I wanted to add positioning and navigation, it became difficult to keep track of where the logic should be at each step and each time the main control loop executed.  I realized that a state machine approach was the solution, and it’s worked out beautifully.

What is a Finite State Machine?  You can find the formal definition here at Wikipedia, but as David Stonier-Gibson puts it in his tutorial:

The formal, mathematical definition of an FSM is such brain numbing, eye popping mumbo jumbo I feel certain that 9 out of 10 electronic engineering and IT students switch off in the first 5 minutes of the FSM lecture series, never to ever benefit from the power of FSMs in their work. This is not difficult stuff, it’s just made to look difficult by the academics!

The basic concept of an FSM is that the system is, at any time, in a specific, pre-defined state.  Multiple states are defined, along with the internal or external events that cause the system to transition from one state to another.  The functions that need to be performed for each transition from one state to another are then determined, and, of course, you have functions to be performed when in a given state.  Not all events trigger a state transition, some are processed and handled with the system staying in the same state.  It’s easiest to explain by example.  A good, short tutorial with examples can be found in the online article Application Design Patterns: State Machines, along with some useful design hints.  Below, I use the state-machine model I developed for my MARV-1 autonomous dead-reckoning vehicle as an example.

State Machines can be represented in several ways.  One approach is a state transition matrix.  Below is the matrix for the code for my MARV-1 autonomous vehicle:

State Transition Matrix

The topmost row shows the seven states that the robot can be in.  The leftmost column shows the internal and external events that can cause a change from one state to another.  For example, “Button 1 pressed” is an external event.  If MARV-1 is currently in the Off state, it transitions to the Orienting state.  If it’s in any other state, it transitions to Off.  “Completed calculating next heading” would be an internal event that causes a transition from the Orienting state to the Turning state.  If, instead, the last waypoint in the list had already been processed, then there would be a transition from the Orienting to the Off state.

In C/C++/Arduino code, states are typically coded using the Switch command.  Each Case ends with a break;, since the system can only be in one state at a time.  There can be code to run each time a state is entered for the first time and code to run when you exit a particular state.  This code can be dependent on the specific transition, e.g., the exit code from Orienting to Off is different than from Orienting to Turning.  I found it easier to use exit code rather than entrance code wherever possible, because then I didn’t have to set a flag and check each time through the main loop to determined if I was entering a state for the first time or not.

In fact, 95 percent of the code in the main Loop for my MARV-1 vehicle is inside a single Switch statement.  The exceptions are checking for the Button 1 press, since that must be done in every state, and updating position and orientation, since, with the exception of the Off state, that must always be done.

You’ll notice that most of the cells in the state transition matrix are empty.  That’s because most events only affect one or two states.  That means that you don’t need to check for those events when in any of the other states.   The state machine design pattern makes coding simpler and much, much easier to follow.  It also  allows you to change out the details within a state (inside a specific case in your code) without affecting the rest of your code.  The exception to this is the transition triggers themselves and the exit processing code.

Another way of designing or documenting your Finite State Machine is with a state machine diagram.  Here’s the same information for MARV-1, presented in pictorial form:

State Machine Diagram

In the case of MARV-1, I started my planning figuring on an Off state and an On state.  Of course, the On state quickly was subdivided into more.  Since MARV-1 uses tank-style turns and always either moves in a straight line or turns in place, it was logical to have a Turning state and a Traveling state.  As I worked on the code, I found it made sense to break out the Orienting from the Turning, even though the Orienting is just some calculations that complete in a single pass through the main Loop.  Similarly, it became easier to code to break the obstacle avoidance maneuvering into 3 states, one for each step in the 3 step obstacle avoidance approach I decided on:  Back up, turn right, go forward a ways, hopefully clearing the original obstacle.  As you can see from the table or picture, if MARV-1 is still pointing towards an obstacle after turning, it goes back to the Avoid:Backing state, as it does if it detects an obstacle while moving forward.

Finite State Machines are a simple and effective concept for robot software, and I encourage you to plan out your next project using this approach.

Posted by: ViennaMike | January 28, 2012

Some Debugging Frustration

My first robot, MARV-1 (Mike’s Autonomous Robotic Vehicle #1), is doing fine at avoiding obstacles, but it gets easily confused and sometimes gets literally spinning in circles.

I need to try to trace the cause of the endless spinning. My hypothesis is that I have the tolerance parameter for turns set too tight, so with the lack of precision in the heading, it can get in a mode where it’s never getting close enough to the desired heading to stop turning.

UPDATE: My hypothesis was incorrect. The problem was that while I normalize the robot’s heading to always be between -Pi and +Pi radians, I wasn’t normalizing the new target heading of (heading – Pi/4 radians) to turn away from the obstacle. So if that every was less than -Pi, the heading could never be close to the target heading, and the robot kept spinning.

I may also try to modify the marking on the gears so that I get a pulse every 1/8th of a wheel rotation rather than every 1/4.

UPDATE: This worked, and does seem to improve navigation, but errors still build up quickly on the heading, and hence position, as they tend to do with only dead reckoning for navigation.

I also need to modify the obstacle avoidance routine. Right now, when MARV-1 detects an obstacle it backs up, rotates right about 45 degrees, and then tries to move forward about 2 feet before recalculating a new heading and distance to the next waypoint. When MARV-1 is pointed to the right of the waypoint, this results in it turning away even further. I think I’ll try to have it turn in whatever direction is closer to the heading to the next waypoint.

Posted by: ViennaMike | January 27, 2012

Move now, don’t delay(); the metro library

The classic “hello world” of the Arduino world includes something like:

void loop()
{
  digitalWrite(ledPin, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(ledPin, LOW);    // sets the LED off
  delay(1000);                  // waits for a second
}

Simple sample code for robotic vehicles may include something similar, such as

//Move Forward for 10 seconds
advance (255,255);
delay(10000);

where the advance function is previously defined. This approach, using delay(), works fine until you want your robot to do something else while moving, like check sensors for obstacles, or see if a button was pushed to turn it off, or updating its position based on sensor input. The problem of course, is that while the delay is running, the cpu does nothing (although it will process interrupts). So clearly using delay() for this purpose is not a good idea.

Rather than having your code sit idle at a point in the loop function, spinning its figurative wheels, you want the software to continue looping through the main loop, but stopping when a set time is reached. One approach is to use a timer interrupt. Have your code continue through the loop, but set an interrupt service routine that sets a flag, signifying the time has elapsed and it’s time to stop doing what you were doing (e.g., moving forward) and do something else. An introduction to timers and interrupts can be found on the Let’s Make Robots site, and you should also check the Arudino reference page on interrupts .  If you’d like to keep things simpler, there are Arduino libraries for using timer interrupts as well.

An alternative approach is to use the metro library.  The metro library provides an alternative to using timer interrupts.  Because it does not use interrupts, the code in your loop will need to check to see if the timer has expired or not.  The sample code below works on my robot that uses an Arduino-compatible Romeo controller and RP5 chassis.  It was based on the example provided by DFRobot but adds a) using switch 1 on the Romeo board as a start/stop switch and b) instead of using delay(), it uses the Metro library.

The key section of the code is the nextMovement function. It’s called every time the main loop executes. A timer called movementMetro was already initialized as part of the setup. This nextMovement function checks if the timer has gone off, and if it has, changes the movement case to the next in line and resets the value for the appropriate time. One tricky part is that the timer value is for the NEXT movement, not the one in the movement just completed.

void nextMovement (int next,unsigned long wait) // Set case and delay for next movement
  {
    if (movementMetro.check() == 1) {
      movement = next;
      movementMetro.interval(wait);
    }
  }

Here’s the full, working code. When run, you need to push button 1 once the code is loaded. The robot then moves forward, turns, move forward, reverses, turns, and reverses again, with pauses between each movement. You can stop and restart the cycle by using switch 1.

#include <Metro.h>

// Setup movement timer using the Metro library
Metro movementMetro = Metro(4000);

// Buttons vars

const int key_S1_5 = 7;

int state = false; // Off if 0, On if 1

int buttons_check(){
 // This function checks button 1 and returns
 // 0 if no button pressed, 1 if pressed
 // Priorities: S1, S2, S3, S4, S5
 int w = analogRead(key_S1_5);

#define vS2 130
 if ( w < vS2/2 ){
  return 1;
}
 return 0;
}//End buttons_check()

 // Set up for running motors
int E1 = 5;  // digital output pin sending PWM power to the motor
int E2 = 6;  // digital output pin sending PWM power to the motor
int M1 = 4;  // controls is motor moves forward or backwards
int M2 = 7;  // controls is motor moves forward or backwards

void forward(byte a,byte b)		//Move forward
        {
          analogWrite(E1,a);
          digitalWrite(M1,HIGH);
          analogWrite(E2,b);
          digitalWrite(M2,HIGH);
        }

void stop(void)                    	//Stop
        {
          digitalWrite(E1,LOW);
          digitalWrite(E2,LOW);
        }

void backward (byte a,byte b)		//Move backward
        {
          analogWrite (E1,a);
          digitalWrite(M1,LOW);
          analogWrite (E2,b);
          digitalWrite(M2,LOW);
}

void Left (byte a,byte b)		//Turn left
        {
          analogWrite (E1,a);
          digitalWrite(M1,LOW);
          analogWrite (E2,b);
          digitalWrite(M2,HIGH);
        }
void Right (byte a,byte b)		//Turn right
        {
          analogWrite (E1,a);
          digitalWrite(M1,HIGH);
          analogWrite (E2,b);
          digitalWrite(M2,LOW);
        }
int movement = 1; // movement controls which movement (forward, turn, etc.)

void nextMovement (int next,unsigned long wait) // Set case and delay for next movement
  {
    if (movementMetro.check() == 1) {
      movement = next;
      movementMetro.interval(wait);
    }
  }

void setup(){
    for(int i=4;i<=7;i++)
    pinMode(i, OUTPUT);
    Serial.begin(9600);
}// End setup
void loop(){

// This section checks button 1, which functions as stop/start switch, initially stopped
 int button = buttons_check();
 if ( button == 1 ) {
 // Button 1 has been pressed
  state = !state;
 }
 Serial.println(state);

 // Whenstopped after running, reset to original start mode
 if (state == false) {
   stop(); //Stop
   movement = 1;
   movementMetro.interval(4000);
 }
 else {
   Serial.println(movement);

 // Each case sets movement command, signals next movement, and resets timer for duration OF NEXT MOVEMENT
   switch (movement) {
     case 1:
       forward(255,255); //Forward at full speed
       nextMovement(2, 5000);
       break;
     case 2:
       stop(); //Stop
       nextMovement(3, 650);
       break;
     case 3:
       Right(255,255);  //Right at full speed
       nextMovement(4, 5000);
       break;
     case 4:
       stop(); //Stop
       nextMovement(5, 4000);
       break;
     case 5:
       forward(255,255); //Forward at full speed
       nextMovement(6, 5000);
       break;
     case 6:
       stop(); //Stop
       nextMovement(7, 4000);
       break;
     case 7:
       backward(255,255); //backward at full speed
       nextMovement(8, 5000);
       break;
     case 8:
       stop(); //Stop
       nextMovement(9, 650);
       break;
     case 9:
       Left(255,255);  //Left at full speed
       nextMovement(10, 5000);
       break;
     case 10:
       stop(); //Stop
       nextMovement(11, 4000);
       break;
     case 11:
       backward(255,255); //backward at full speed
       nextMovement(12, 5000);
       break;
     case 12:
       stop(); //Stop
       nextMovement(1, 4000);
       break;
   }
 }
}// End loop

Nothing fancy, but it was my start on getting my project underway and moving beyond using delay().

Posted by: ViennaMike | January 24, 2012

Wheel Encoders

In order to estimate position and orientation using dead reckoning, you have to measure the rotation of your wheels (or the motor shaft or gear driving the wheels).   This means using some sort of shaft or wheel encoder.  The RP5 has a gear that rotates 4x for every wheel rotation, and a hole in it which they indicate can be used to count gear rotations using some sort of optical (infrared) encoder.

One can get much more precision by using more holes/slots or more markings, as discussed in this thread on homemade encoders.  Also, having two offset sets of marks allows one to do quadrature encoding and determine the direction of travel as well. For my first robot, I’m just using a rough encoder, with 4 counts per wheel revolution.

In looking in the chassis, there’s not a lot of room. As a result, I decided I’d use a small transmissive sensor, rather than a reflective sensor.  Both have an IR emitter and an IR photo detector.  For reflective units, they both face the same direction, and the detector measure IR reflected back to the sensor.  For a transmissive or interrupt sensor, the two units are separated by a gap, and the detector picks up IR passing through the gap. So far, so good.

I ended up using Vishay transmissive optical sensors (model TCST1202) I purchased from DigiKey.  I found a ciruch  and wiring them up based on the circuit posted by Aniss1001 in the “Homemade wheel encoder“  thread on the Arduino forum.

encoder circuit diagram

Encoder circuit diagram - for a different encoder, but it worked fine

I built the circuit on a prototyping breadboard for testing and got a surprise.  The circuit worked fine, but the gear is transparent to IR!  It turns out that nylon and most plastics used for inexpensive gears are pretty transparent to IR.  I first tried creating an opaque section with a black marker, but while that worked on paper, it didn’t adhere well enough to the gear.  I ended up using a piece of black tape.  Once that worked, I cut some small circuit boards down to size and built the encoders, practicing my soldering skills.

I just used hot glue to mount the encoders.  The encoder boards stick up above the chassis base, so I’m using standoffs to raise the plastic plate with the Romeo controller and other devices.  Here’s a picture of one of the encoders before mounting,, and then mounted on the chassis:

Homemade wheel encoder

Homemade wheel encoder

Mounted encoder

UPDATE: If you don’t want to build your own, I just discovered these pre-built transmissive encoder boards.

Older Posts »

Categories