Monday, November 11, 2013

Ultrasonic, Man!

These HC-SR04 ultrasonic ranging modules work brilliantly. They have a cone of about 40-60 degrees in front of them where pretty much anything - ceiling, coffee cup, pen, cloth, hand - will bounce the signal back and give a clear, clean, to-the-centimeter distance reading of the closest obstruction.

The only exception seems to be hitting smooth surfaces at high incident angles - in which case the return echo is bounced too well, and physically misses the receiver.

Did I mention I'm building a droid? Technically, a child's toy for Christmas, though I want it finished long before then. Actually, I'm building multiple "robots" at the moment, but this one is worth documenting.

eBay and the internet is making this a much easier task than it used to be. For $25, I got a complete 4wd "smart car chassis". I'm really hoping it arrives this week, since most of the rest of the pieces are already here and working.
This follows my current approach to robotics: Start with the sensors. It doesn't matter how fast you can go, if you don't know where you are.

This droid will have at least three major 'external' sensors:
* Ultrasonic Ranging Module
* Digital Compass / magnetometer
* Infrared Receiver

as well as a couple of internal ones:
* Temperature
* Time
* Power Levels (maybe)

I've had each of these working individually now, but I'm learning one of the hard rules of Arduino development - combining devices together with one microcontroller gets exponentially difficult, due to limited shared resources. Making all of those parts work together at once is taking some programming art. I've got it covered, though.

A new approach to programming toys.

When I was but a little programmer, I really wanted one of these:

To the point that I read and practically memorized the manual, while standing in the shop. I couldn't physically have one, but at least I could carry away the idea. In many ways that toy embodied programming as it was in the early 80's.

But as brilliant as it was (I should find out who designed it, and drop them a line... ooh, Nolan Bushnell might has been involved...) programming has changed considerably. I do not think an exact recreation of that toy would be beneficial to an understanding of modern computers. Here's what I mean:

Vincent implemented what was essentially a stripped-down BASIC (or perhaps LOGO) without loops or conditionals. A simple series of instructions like "Forward 80" or "Left 2x60" that would inevitably lead to a tumble down the stairs, which is why I assume that not many survive.

A robot like that, even with IF and REPEAT statements, spends most of it's time doing 'nothing' but waiting for the timer on the current command to expire. Such droids are deaf, dumb, and insensible for most of their lives. And they act like it.

The only way to make such a 'bot respond to two things at once is essentially to write your own mini-scheduler for each unique combination. Fun!

But modern programming is all event driven. Not even multitasking, anymore. Node.js has shown us what happens if you stay single-threaded but make every call non-blocking - performance increases, and resource use decreases.

So I have reduced that concept to it's essentials. My droid's "brain" is composed of 128 "signal" slots. Reading a signal is identical to reading a value out of an array, but changing a signal will cause any "codes" attached to that signal to execute, either "now" or "later".

The "later" timeout is probably going to be globally set to 1/10th of a second in early versions, but could be faster for droids that need more temporal resolution. What is critical is that the 'later' timeout is reset if another write to the signal is performed. (The 'now' codes are still executed immediately.)

There's an excellent reason for all this which involves a lot of computing science. With just those two 'event' types, we get a universal system.

A "code" is a set of arithmetic instructions almost identical to the standard accumulator logic of a pocket calculator, plus an if/skip statement.

Loops are apparently not implemented, but any code can write another value to the signal which triggered it, which will cause it to trigger again. A classic "If signal>0 then signal = signal-1" will keep the code 'looping' until the counter gets to zero.

Infinite loops are not a bug in this environment. They are an essential way of getting things done. The interpreter is designed so that every signal could be "looping" simultaneously.

This creates a network of event-driven fragments of code. There are no explicit functions calls either... code simply triggers other code by writing to signals. There are no parameters to pass - needed values are read out of the signal array.

If you're into Comp. Sci, this is an extreme mash-up of core OCCAM and Javascript concepts.

This all sounds a lot more complicated than it will appear. "Codes" are simple lists of calculator arithmetic instructions (with the 128 signal registers being equivalent to memories) And each "Signal" is just two lists of codes, to run now and later. That's it. Universal turing machine.

I'm hoping I can go entirely "symbolic" for this. (English is an assumption... "pre-linguistic" programming is possible.) Since only 128 signals and 64 code scripts are possible, each can be assigned a unique "icon" instead of number - to be redrawn by the droid's owner to suit their conceptions of what it means or does.

This "digital nervous system" can be patched and changed in real-time without touching all the other signals or codes. Improvements to the droids "program" can be made in-the-field with a remote control, without the tether of a programming cable or IDE. (Hey kids! Who wants to use an Integrated Development Environment? It's totally fun! Where are you going?)

The droid will slowly accumulate it's responses over weeks and months (stored in EEPROM) not the "tabula rasa" approach of Vincent, who lost his memory on every reset and battery change.

No matter what cool new tricks you teach it, the droid should never forget that if it can't see the floor right in front of it's face, it should stop going forward. (That's the third law of robotics!) Or what to do when power is low. Or how to fire the Lasers!

Toys are tools to spur the imagination, and our understanding of the world. Good toys are ones that can be woven into existing play, that can offer possibilities rather than constricting choices. That is a very fine line to walk when dealing with robots. I think the answer is to be very clear about limitations, but be as free as possible within them. Pre-approved capabilities, but not pre-approved uses.

I'll be releasing the code as soon as it's done. If you have an Arduino-based "collision avoidance robot" (not the official arduino robot - I don't have one of those...) made out of a Leonardo/Atmega32u4, random cheap sensor modules, and a couple of motors, then you essentially have the same platform I'm building for. I personally think a compass is critical, (more than axis encoders) and you might even want to go for a full 6 or 9 DOF accelerometer/gyro/compass module. (GPS is probably way too much... probably...)

Oh, I've also written a "Beeps" module which makes a wonderful range of droid-sounding noises. I am genuinely astonished at the personality that a few warbled squeaks can imbue. I let it randomly generate "phrases" for a while, and kept the best sounding ones.

No comments:

Post a Comment