Monday, December 31, 2007

Capaciflector

If you look at even relatively simple animals, like bumblebees, they are equipped with loads of complimentary sensors (vision, hearing, chemoreception, and touch). It seems to me the lofty goal of the robotics hobbyist to build a sizable robot that doesn't run into jutting coffee tables, moving cats, and other confounding domestic obstacles, let alone does anything remotely interesting, is to have a similar variety and multitude of sensors (not to mention being able to interpret all the signals).

Most robotics hobbyists know sensors react differently to different targets. The Cruiser's IR sensors can't detect a messy stack of papers or a bag of trash and it detects cardboard boxes about an inch farther away than semi-clear plastic boxes. Unless the cardboard is colored black. In information security, the key word is correlation: from multiple intrusion detectors in an intrusion detection system to determine if a hacker is up to no good. Clearly animals correlate their senses. The other night one of our cats was camped out on the bed next to me. I knew this because I could feel his warmth and the pressure of the sheet on my leg from his weight. I could move my leg and detect him. I never had to look.

The other thing in intrusion detection is you can't just stick one sensor on one computer host or network subnet. You have deploy sensors everywhere to see the whole picture or you will miss really important stuff. Surely the same is true in robotics? But the more sensors you add, the more cost, complexity, and required computing power you're dealing with (picture a robot with 10,000 IR detectors and driving circuitry). I was wondering if there was some simple, elegant, and economical way to use an electrostatic field to detect proximity.

Enter the capaciflector. Maybe everyone's heard of this but me. It was developed at Goddard Space Flight Center, NASA. A particularly attractive feature is the ability to use the robot's shell as the sensor(s) achieving an economy of purpose, and potentially giving the robot obstacle detection in essentially all directions and with whatever level of granularity you desire. I would think even a small robot with a basic microcontroller could gain a lot of perception without much processing cost. A few interesting tidbits on the capaciflector here. More articles on the subject here, here and here. Here's a capaciflector camera. But will this type of sensor work like I hope?

The big question is whether you can detect objects at any reasonable distance, say, 6 inches. For some reason the capaciflector reminds me of lateral lines on fish, but this is an active rather than passive sensor, and detects objects, not just living beings. Even if the distance is limited, this approach could provide another type of touch sense, like the hairs on our arms, and offer a last resort collision detection. Something, anything better than bumpers...

Have a happy and safe New Year!

Saturday, December 29, 2007

Obstacle Avoidance

Spent some time over the last couple of days programming obstacle avoidance into the Cruiser. (I really need a better name, any ideas?) So far what I've come up with isn't stellar but it works in most situations, though is kind of dumb sometimes, as you can see in the video. The bot is deciding what direction to turn and whether to do quarter turn or full turn based on whether the IR sensors are past a threshold. There's two pair in front, left, right, as well as two that point sort of rearwards (I'm ignoring those).



I'm sure it could be improved upon, but I want to try a couple of different experiments next. One involves using a neural network for obstacle avoidance (how will this work in an 8MHz 8-bit processor? I did some experimenting on a C64 back in the day and even using good ol' BASIC V2 it wasn't bad I guess).

Another experiment I'd love to try is navigating a maze corridor by steering to the middle between two walls. The eventual goal is maze solving and while we're at it, why not see how the little guy fares in a competition of some type, right? There's actually a competition in April... right when I'm planning to go four wheeling in Moab. But I'm getting a head of myself

Friday, December 28, 2007

Motor Control (Part 2)

Ok, well, if I get any of this wrong let me know. I haven't spent a lot of time in the AVR ATmega8 data sheets, and have only skimmed through this AVR PWM tutorial, but here goes...

Among the other things you can do, PWM-wise, you can create phase-correct PWM signals using a 16-bit counter, which is what the developer did who wrote the motor control example program (he said so in the comments). The long and short of it is that you use Timer1 (TCNT1), two Output Compare Registers (OCR1A and OCR1B). Two timer counter control registers (TCCR1A and TCCR1B) control TCNT1 and how the waveform generation operates.

The developer set TCCR1A to 0x0A2 (10100011). From the data sheet:
TCCR1B is set to 0x01. Here's the info on that from the data sheet:
So, the relevant settings being made are:

// Clear OC1A/B on Compare Match (set output low)
COM1A1 = 1; COM1A0 = 0;
COM1B1 = 1; COM1B0 = 0;

// Select clk/1 as source, no prescaling
CS12 = 0; CS11 = 0; CS10 = 1;

// Waveform Gen Mode 3, Phase-correct, 10-bit
WGM13 = 0; WGM12 = 0; WGM11 = 1; WGM10 = 1;

The data sheet gives you the truth tables for COM1B and WGM bits as they affect operation of the waveform generation. The example program's comments claimed it was setting Mode 2, Phase-corrected 9-bit but that is in contrast to the data sheet. Odd. At any rate, that takes care of the mode and configuration of the PWM.

Now, OCR1A and OCR1B are set to whatever desired value to achieve a particular duty cycle. Then TCNT1 is reset and off we go. The OCR1A/B registers are continually compared to TCNT1 and when there's a match, the corresponding Output Compare Pin (OC1A / PB1 and OC1B / PB2) is dropped low.
A lower compare value in OCR1A means more frequent drop-outs on the OC1A pin, thus a lower duty cycle, while a higher compare value means higher duty cycle. (At least that is how it works conceptually, but there are details I haven't tackled, yet)

In the example program (motor_test2.c) from Microrobot, the motor_init() function sets all this up (I've tweaked it a little to hopefully make more sense -- but take the comments with a grain of salt):

Distilling all this to the most fundamental information: to make the motors drive forward, basically do this after the init routine above:

OCR1AH=1; OCR1AL=100;
OCR1BH=1; OCR1BL=100;

The OC1A/B output pins go through the NAND gates mentioned previously and ultimately to input Pin1 and Pin2 of the Sanyo LB1630 bi-directional motor controller. It appears to always be the case that Pin1 = ~Pin2.
So how, exactly, do we get the motors to go reverse and forward simply by setting the high byte of OCR1A/B to 0x01... ?

I think we are always alternating between forward/reverse signals and we are essentially inverting the duty cycle for 0x00..0xFF (getting a reverse signal more often than a forward signal) versus 0x100..0x1FF (getting a forward signal more than a reverse signal). That means at 0x00, the motor is getting forward/reverse equally, which explains why the motors buzz at this setting. It also means we aren't saving a lot of energy by using PWM.

Also confusing is whether we are really using a 9- or 10-bit counter. Maybe I'll solve these mysteries in part 3.

Meanwhile I've managed to get the bot to do some very stupid, basic obstacle avoidance. So I am making some progress towards building a maze-solving bot.