Category Archives: Robots

My First Raspberry Pi HAT

I’m a bit late in reporting on this, because much of the work happened over the Labour Day weekend, waiting in ferry lineups and such.  I spent too much time poring over datasheets, double- and triple-checking my design, and while I’m still not sure that it’ll work, I’m going ahead with the first revision of my first Raspberry Pi HAT.

My first HAT is intended to be a part of the Office Robot.  But I can see some other potential uses for it, so I tried to make the design a little more flexible.

Designed Features:

  • Mono microphone input
  • 3.7W stereo speaker output
  • SPI peripheral connector, with an interrupt and reset line
  • I2C peripheral connector, with shared interrupt and reset lines
  • 5V power input
  • Power control button

I am confident that the level-shifted peripheral connectors will work properly, as I’ve prototyped both on a breadboard.  It’s the audio stuff I’ve never played with before, that I’m nervous about.  But even if those bits don’t work properly, the HAT will still be a lot cleaner than the breadboard covered in jumper wires.

I’ve got my fingers crossed, but if I have to build Version 2, I’m okay with that, too.

 

Measuring wheel speed

Each wheel on the robot is paired with a slotted disc, which passes through an optical sensor.  There are 20 slots on each disc, which translates to 20 “on” pulses per rotation.  However, it’s easier for me to count both the “on” and “off” pulse edges, so I’m dealing with 40 pulse edges per each wheel rotation.  I’m going to call these ticks as that’s a lot easier to say.
DSC_9248But ultimately, I don’t care about ticks.  I do care about speed, though.  So I’m going to start there, and figure out what I need in order to calculate that.

Simply stated:

speed=\frac{distance}{time}

or:

speed=\frac{1 tick}{timeSinceLastTick}

or, if I throw some averaging in there:

speed=\frac{numTicks}{elapsedTime}

I can already see that there’s going to be a problem when the speed approaches zero, as there are no ticks to measure the timings.  So I’m going to start by measuring both the number of ticks that have occurred, and the amount of time that’s passed.  If too much time has passed, I’ll consider the speed to be zero.

// Store up to 10 "tick" (or "no-tick") events
const uint8_t NUM_SAMPLES = 10;

// Keep track of how many of the "tick" or "no-tick" events have happened.
uint8_t _tickCount[NUM_SAMPLES];
volatile uint8_t _totalTicks = 0;

// Keep track of the event timestamps
uint32_t _timings[NUM_SAMPLES];

// Some pointers to the arrays above.
volatile uint8_t _oldestIndex = 0;
volatile uint8_t _newestIndex = NUM_SAMPLES - 1;

When a tick occurs, the system calls an interrupt:

ISR(PCINT1_vect) {
    uint8_t newState = PINC & (_BV(PINC2) | _BV(PINC3));
    uint64_t nowStamp = micros(); // timestamp in µs
    uint8_t changes = newState ^ _encoderState;
    _encoderState = newState;

    if (changes & (_BV(PINC2))) {
        _totalTicks = _totalTicks - _tickCount[_oldestIndex] + 1;
        _tickCount[_oldestIndex] = 1;
        _timings[_oldestIndex] = nowStamp;

        // Move the pointers along, overflowing back to zero if needed.
        _newestIndex = _oldestIndex;
        _oldestIndex++;
        if (_oldestIndex >= NUM_SAMPLES) {
            _oldestIndex = 0;
        }
    }
}

If a tick didn’t happen, we inject a zero into the mix:

// Called when... nothing happened!
void nothingHappened() {
    cli();
    // Overwrite the "oldest" item in the averaging loop, and adjust pointers.
    _totalTicks = _totalTicks - _tickCount[_oldestIndex] + 0;
    _tickCount[_oldestIndex] = 0; // nothing happened!
    _timings[_oldestIndex] = micros();

    _newestIndex = _oldestIndex;
    _oldestIndex++;
    if (_oldestIndexB >= NUM_SAMPLES) {
        _oldestIndexB = 0;
    }
    sei();
}

And finally, in order to calculate the current speed:

double getSpeed() {
    cli(); // Make sure the interrupt doesn't fire while we're in here.
    uint8_t totalTicks = _totalTicks;
    uint64_t oldestTime = _timings[_oldestIndex];
    uint64_t newestTime = _timings[_newestIndex];
    sei(); // Set the interrupts free!

    // To get the time difference, we can't simply subtract,
    // because micros() overflows every 70 minutes or so.
    // Implementation of getTimeDiff is left as an exercise
    // to the reader.
    uint64_t timeDiff = getTimeDiff(oldestTime, newestTime);

    if (totalTicks == 0 || timeDiff == 0 || timeDiff > 10000000) {
        return 0.0;
    } else {
        return (float)((totalTicks - 1) * 1000000) / (float)(timeDiff);
    }
}

There’s a little more to it, but you’ve got the idea.  It’s just a bunch of code that watches how far we’ve gone, another bunch that watches the clock, and at the end of the day, it’s just simple physics:

speed=\frac{distance}{time}

Interface board gets some feature creep

Yes, the parts count keeps going up.

A board I’m working on that’ll sit atop a Raspberry Pi.  It’ll replace the mass of jumper wire that’s currently serving the same purpose.  This board is primarily for the robot, but I have a couple of other usecases in mind.  Besides, I get three copies of the board from the PCB house, so I might as well make it slightly multi-purpose.

Now it has an I2S audio codec chip.  I’ve never tried to do anything with digital audio before, so I’ll probably end up with a Version Two at some point in the future.

foo

So far, it’s got:

  • Yet another ATMEGA328p microcontroller.  This one could easily be something with less horsepower, as it’s just there to manage the power supply and try to make sure bad things don’t happen.
  • Connection for “Motion Controller” board
  • Connection for I2C peripherals (the camera pan/tilt and a few other accessory things will attach to this bus)
  • Microphone input
  • Speaker output
  • Power toggle button

I think I should go to bed though, before this gets too many more features!

Why two motor controllers?

Someone at work asked me why I put two separate motor controller boards on the robot. Well, it would have been very easy to do so.  And in my original prototype, I had done exactly that, using an Arduino UNO and the fantastic Adafruit Motor Shield.  My motor controller boards use the same H-bridge chip as Adafruit’s motor shield, but that’s where the similarities end.

The core of the Dual Motor Controller is the ATMEGA328P microcontroller.  Among this chip’s many talents: six of the pins can output a PWM signal.  But two of them are special.  Two of them can go ultrasonic without messing up the other timers!

eagle

It’s those two, in the middle, highlighted in bright red.

These two can run a PWM frequency around 32kHz, which is well within spec for the TB6612FNG motor driver, but it’s conveniently outside the hearing range for most humans.  You know that “hum” you sometimes get when electric motors aren’t going at full speed?  This gets rid of that!  It’ll annoy all the neighbourhood dogs, though.

But there’s more!

Having a separate board for the front and rear motors made it possible to mount the optical encoders directly to the same board as the controller.  A slotted disc on each wheel passes through an infrared break-beam detector, and results in a number of pulses that the microcontroller can count, which correlates to the speed of the wheel.  (I can only measure speed and distance with these sensors.  I’m only able to infer the direction.)

And finally:

Building two separate boards also saved me a little bit of money on the PCB.  OSH Park does a great job of manufacturing PCBs for me, but custom PCBs are certainly not the cheapest things in the world.  At $5.00 US per square inch, they’re about the only thing more expensive than Vancouver real estate.  But you get three boards for that price.   So having a need for more than one board certainly makes sense to me!

Office Robot Modules

I originally wanted to design and build all the parts for this robot on a single PCB.  I figured that would look nicer.  But I’m really glad that I’ve opted for a modular approach to the whole thing.  It’s made it so that I can focus on one problem at a time, and it makes it easy to replace and/or reuse components.

Here’s a diagram of all the modules that will eventually be part of the robot.  Colour indicates what’s been done so far, and what remains.

OfficeBot Architecture

Blue

I’ve completed building the Motion Controller and Dual Motor Controller boards.  They’ll need some firmware changes to support additional boards, but aside from a minor hardware issue on the Motion Controller (which I’ve been able to work around by using other hardware for the testing, these are looking pretty decent!

Pink

Prototyped, or in-progress.  I’ve built a website that’s currently being served up by the robot itself.  That’ll be moved to a terrestrial web server, eventually.  The connections between the Pi and the rest of the hardware is now breadboarded.  Although it looks hideous with all those jumper wires, it does work nicely.  But I need to sort out an issue with the power supply before I can have the PCB manufactured, so it might just be a little while for that.  I can live with the ugly wires (for a little while).

Orange

What was I thinking?!

I designed the Motion Controller board with support for analog distance measurement sensors and collision switches, as well as lighting control for illumination and hazard lights.  What robot would be complete without a whole whack of blinkenlights?

Some parts of the Office Robot

A few quick snaps of the Office Robot.  The motor control boards are essentially complete (working out the kinks in the firmware, still).  The connection between the motor control boards and the web interface (courtesy of a Raspberry Pi) is obviously still pretty much crap.  But it does work, and I’ve transferred the schematic to Eagle.  All those jumper wires, and pretty much everything that’s plugged into that breadboard will be replaced with a single PCB!

DSC_9236

The motor control boards are a little prettier.  There’s one for each set of wheels, and an interface board in the middle.

DSC_9222

The Office Robot

At my office, it’s pretty common practice to work from home.  But when I’m working from home, I lose touch with what’s going on at work.  And we have a few people on the team who live in a completely different province.  What if we could have a robot that could be controlled over the Internet, and provide a way for people to remotely interact with each other?

Continue reading

The Tiny Desk Robot

I’m working on a tiny robot that’ll crawl around my desk at work, and provide endless hours of amusement.  The design is starting to take shape, but this is where I’m at so far:

Screen Shot 2015-08-05 at 14.23.56

 

I’m in the process of prototyping the wheels and gears, to see whether they’ll actually work.  I’m not sure about the bottom:

Screen Shot 2015-08-05 at 14.27.39

As you can see, it’s a differential-drive robot.  I’ve gone completely overboard on the number of IR sensors, but I want to have fun with it.  I’d like to be able to have this thing perform line following, collision detection (or prevention), and cliff detection.  So it can zip around the top of my desk without a care in the world!