Thursday, February 27, 2014

It's always the Red Wire


There's that one thriller where the bomb squad guy has been chasing the same mad bomber for years, finds himself with the inevitable ticking clock in his lap, and remarks something like "I know him, it's always the red wire." and of course he is right. Apparently all hollywood mad bombers since were trained at the same technical school.

There is an underlying truth here... when you're building electronics devices, especially prototypes, there are a lot of wires. (And that, my friends, was an understatement.) There are some wires that it's fine to mix up - digital signals especially. Mistake data and clock lines and the worst that happens is some head-scratching. But there are other wires - like 12v high-current motor connections - which if you swap them with the digital lines, will cause the magic smoke to come out of expensive components and create intense sadness in you.

This is especially likely to happen at 2am, when the last thing left is to plug everything back together and put the case on. "I've done this a hundred times" you think, and you swap two otherwise identical looking leads, and you get smoke and sadness.

If you think that's an acute problem, consider electricians; where getting it wrong means potential death for yourself or the next guy who has to come along and work on the same wires. They mostly solve it using a very strict color-code for "Active", "Neutral" and "Earth" and if you don't follow it you can't be an electrician anymore. They take it that seriously.

So, here's a pro tip for people using those excellent "Dupont" IDC connectors for their Arduino Projects - the wires will generally arrive looking like this:



Oh, so pretty. And the instinct is to leave the ribbon unbesmirched. But here is the first thing you should do:



Immediately separate the cable into a couple of "sets" of wires with specific purpose.
My personal color scheme (constrained by the 'standard colour ordering' of these cables) goes:

Red and Brown: Low Voltage DC, usually the primary 5V (or 3.3) supply. Red is positive, Brown is negative, and helpfully those two colours occur next to each other on the ribbon! These days I like to do power distribution looms so it's obvious when everything's right. If you're really slick, you could twist the pairs to cancel inductive effects.

Orange: High Power DC/AC, like 12V or motor connections or 'raw' power inputs. Orange is the highest-visibility colour, reserved for the most dangerous wires. These are the ones that will kill your project if plugged in the wrong place.

Black: Signal Ground wires - electrically equivalent to brown, but preferentially for low-current 'reference ground' purposes. Signal ground should technically star-propagate from the uController (not the power supply) if you really care about the millivolts, because when significant currents flow in the brown power wires, end-to-end voltages start to differ (current times resistance) which can affect sensors and ADC. But if you get black and brown mixed up - the most likely of all - nothing exciting happens.

The rest are a mish-mash of colours that, in the dark, look pretty much like each other. Use for signal and logic lines and misc.

That's how I roll, anyway. Whatever scheme you pick, follow it religiously. Feel deep inner shame and sin if you violate it. That's why I keep my list short (no standard colours for negative rails, etc) because otherwise I would have to stop using those colours generally. There's never enough red and brown, and too much orange piling up, as it is.

Remember, this is the original Murphy's Law we're talking about. Most people know the generalized version, but Captain Murphy coined it after another test-run was ruined because every single sensor had been wired up backwards. "If there's a way to do it wrong, he will." said Murphy, and recommended buying better plugs.

At some point you will connect an orange wire, notice you just attached it to a blue wire, and will mutter "Hang on..." In that half-second of hesitation, you will save days or weeks of work.

Even in the future, we will still need assorted lengths of coloured wire and cable. This is one of those "habits of a lifetime" things.

The Professor knows what I mean.

"Here's where I keep assorted lengths of wire."
"Whoa! A real live spaceship!"
"I designed it myself. Let me show you some of the different lengths of wire that I used."



Wednesday, February 26, 2014

Review: Arduino Motor Drivers: L298N Module

Last year I did a pair of reviews of various cheap motor driver modules, but I wasn't entirely happy with any of them for the purposes of spinning a couple of small robot wheels around. There was one module which had ended up delayed, probably lost in the Christmas parcel backlog, and only finally turned up a few weeks ago:

  • L298N DC Stepper Motor Dual H Bridge Drive Controller Board : $3.25 

Frankly, it's the best so far for the job. Well Recommended.



There are several variants floating around. You're looking for one with the L298N chip (not D or P or any other suffix including none) and you're also looking for those rows of huge diodes next to it. There's a variant that has the diodes internal to the chip, but you know what that means? All the heat gets to stay in. External diodes means the '298 can push more watts through the H-bridge. It's not a modern chip, so that matters.

I have mine working at both 5 volts for the logic AND the motor power (in fact, the same +5.2V supply connected to both the +12V and +5V power inputs - this is barely allowed by the spec, but does work fine) and I've tried PWM at various frequencies as well as full drive in both forward, reverse, and fast changes in direction. I managed to get the heatsink warm.

I expect that larger motors running at the full 12V could push this to "Hot", and you'd want to worry about airflow. But for 6V robots or cars, enclosing it is not a problem.

It's very easy to drive, with only four wires needed, one for each half of the H-bridges. You could also break out the 'enable' lines, but there's really no point - on my module, they are the two small jumpers you can see on the sides of the pin header which bridges them to +5V. (in other words, permanently enabled.) I can't see a reason why you would want control over these, unless you were doing weird things with separate PWM sources, extreme power saving, or had an "Emergency Stop" hardware control path. (In which case, good for you!)

The particular module I got also had a 5V regular on-board, which could be handy in some situations, but I basically disabled it for my installation. The Low-Dropout regulator on the Arduino is far superior, if you need one.

Let's get my main gripe out of the way, which is that I hate terminal blocks. Sure, I used them a bit during early testing, but now that I'm giving the module a permanent home I've pulled them from the board like bad teeth.



"What's wrong with terminal blocks?" you ask? Nothing, if you like your wires randomly coming loose and flopping around the neighboring terminals. Personally, I don't. Especially high-current motor windings.

You'd think they'd work fine, and if you have "single core" wire then perhaps they do. But most of us use multistrand wire, which is like trying to hold a rope in a vice: it works at first, but eventually the bundle of fibres shifts and settles into a different shape - usually compressing enough to slip out of the vice. Assuming the screws don't rattle loose first.

Tinning the wires doesn't help much either, because solder is soft and malleable, deforms, and slips out of the vice. Grrr. 

For ten minutes, it's fine. For permanent installation it's a failure waiting to happen. 

And they're huge and heavy and take longer than soldering, and their in-contact surface area (therefore current capacity/resistance) is essentially random. Into the parts bin they go.




Here's the module all wired up and installed into the base of a "Rover 5". There's a pair of fairly standard DC motors (and gearboxes) driving the treads, though you can't really see them. (The long black cylinders are "choke" inductors to suppress motor noise.) The module has been running this rig for weeks now.

And because it won the shoot-out for best motor module in this class, that's where it's going to stay.


Monday, February 17, 2014

StarChess - The Rules

I just had a really, really silly idea. But it's growing on me. I was thinking about economies, and games, and wondered:

What would Chess be like if it was a resource-building game like StarCraft?

Managing economic flows, improving tech-trees, these raise StarCraft above mere "strategy" games like Chess (where you start with fixed resources and cannot increase the size of your army) because they more closely correspond with how real economies actually work. They are better simulators for reality, better teaching tools. Chess is really a "tactics" game, come to think of it.

So how would Chess be turned into a strategic resource builder? We want to keep as many of the usual rules of chess, and make the smallest number of changes.

Well, you'd start with a mostly empty board instead of a full one. The logical minimum would be to start with kings. (Although a couple of pawns might be handy as well)


Here's the first rule: Each "move", you can either move a chess piece as normal, or have your king (command center) generate a pawn (SCV/drone/zergling) into any empty square next to the king. A bit like transfer chess.


The king is the only piece with this ability, logically making it the most important piece on the board. We will now add one more rule: Your pawns can also "take" your own pieces (in the normal diagonal way) and in doing so "upgrade" them to the next most powerful piece. (Similar to 'queening')

Let's set the "tech-tree" order as:

  1. Pawn
  2. Knight
  3. Bishop
  4. Castle
  5. Queen

If you're playing this on a real board, you'll be "capped" by the usual number of pieces you have. Alas, no multiple queens or kings.

So, this is black moving normally, (making a rush?) but white doing an "upgrade" of one pawn with another. Like most resource builders, the start of the game is pretty slow.


And that's all. The game then proceeds, with each side spawning new pawns from their king, upgrading units, and deploying them against the opposing side.

 


As for the victory conditions, I think keeping "checkmate" is fine. Although in StarCraft it's possible to fight on without a command center, we can probably assume that wouldn't be the situation in ChessCraft unless you were on the ropes anyway.

I haven't actually played this against a person yet. But now I want to.

Rebooting the Economy

The last two major car manufacturers are shutting down in my country. Cars produced by the local divisions of Ford and Mitsubishi were well regarded, but financial winds have blown elsewhere, and they are wrapping up operations.

If that was the only thing, I wouldn't be concerned. But the loss of so much top-tier capacity is going to have a ripple effect right down to the manufacturing base. Specialist bolt-making shops, alloy suppliers, robot repairmen, many will loose their largest and most reliable customer, and business will become untenable.

Then the ripples go up again, as the remaining assemblers find they now have to wait weeks for bolts to arrive from overseas, and the quality is different.

Meanwhile, no local car manufacturers will spring up to replace them, primarily due to the enormous cost of proving a vehicle crash-safe and compliant with all regulations, creating enormous entry barriers to anyone not already a multinational.

Don't worry, I'm going to propose a solution. First, lets lay out the problem:

The essential issue is that taking out the middle piece of the consumer cycle means that Australia is now a nation that produces incredible amounts of mineral ore (and base alloys) and is filled with insatiable consumers, but the middle step is to send billions of tonnes of metal overseas to have it refined, worked, forged, stamped, bent, folded, milled, drilled, ground, assembled, packed, and then sent back. Then we unpack it, put it into our mining machines, and the cycle repeats.

If only we had some kind of magic box where you could pour metal powder into the top and fully formed parts come out of a slot at the bottom. Then we wouldn't have to round-trip every kilo of material and lose out on the best part of the journey.

Oh, wait, we do.

From Dust to 3D Printed Gold Jewelry

Hey, if that worked... how about "if only we had a magic box that could make entire cars?"

Well, it's bigger than a matchbox.

OK, that's not bad, although I probably should have been more specific about the size.

I'm not going to waffle on about the benefits of 3D printing... that's been done. What I will point out is that if we've just decimated our traditional manufacturing industries, we have lots of experts in the art of metal who could be at home, building internet cottage businesses around endless bespoke customization (and teaming up with their local artists to do so) and fuelled by abundant local raw materials.

You know, "Middle Class" stuff. I hear it was popular during Victorian times.

The obvious way to accomplish that is to start handing out on 'semi-permanent loan' 3D printers to anyone with the skills to operate one, at least in the initial phases. We need a convenience store model running here, not a shopping mall. Let them operate out of their house, with a little counter-front, so you can send your design for print, and walk down ten minutes later to pick up personalized cutlery and a carton of milk.

Of course, the organization required to hand out tens of thousands of 3D printers puts this squarely in government territory. Since the benefits accrue nationally rather than concentrate anywhere specific, no sane commercial entity would consider it.

If you quickly establish a wide pool of expertise in a common 3D platform, then I'm fairly confident you just have to stand back from that point and make sure the new practitioners have a strong legal framework that protects their interests so long as they act in good faith. (Only licenced/verified machines to print safety/emergency gear, kind of thing.)

This is Star-Trek level thinking. Once you have enough identical replicators up and running, you can depend on them to make their own replacement parts, and improvements. Any design investment gets amortized over the whole network.

Distributed technologies have many advantages, especially social, but the big disadvantage is they take a long time to get real traction compared to a centrally-pushed agenda. (especially if they're in competition with one) Why not combine the best of both worlds?

That's the key here. The potential is great. The biggest risk of these new technologies was their chaotic - possibly decimating - impact on manufacturing, but that just happened anyway, and with no replacement.

The lessons of technology show that it doesn't really matter which platform you pick, so long as there is broad compatibility. Skills and software need to transfer easily. If you start with a fractured and incompatible base, you spend the first five years arguing whether VHS or Beta is superior.

We could skip over all that. Straight into a 21st century manufacturing base - distributed, locally advantaged, independant. Then the flood of little boxes on eBay will start going in the other direction.

The Chinese word for "crisis" is actually not the same as for "opportunity". But in English, it increasingly is.

Tuesday, February 4, 2014

Building a Droid Nervous System


I have been so old-school recently I'm practically covered in chalk. Here's a screenshot of what I've been working on. (Yup, photo stolen from my screens review.)



This is the 'main menu' of my new miniature programming environment. It's Turing-complete, real-time, multitasking, has an interactive editor/debugger, and is field-programmable. It's intended to drive small robot-like toys and devices, and is "non-linguistic" in that it only uses numbers and math-like symbols, not words, for all programming concepts.

It is also the simplest possible language I could create that fulfils those requirements. It's less complicated than most calculators. In fact, it tries very hard to act like one.

And it fits in 26K. It would probably work great as an industrial controller, too.

Primary Features:
  • 128 pre-allocated global variables, called 'signals'
  • (up to) 64 code fragments which can perform math operations and conditional tests on the signals.
  • A 'trigger list' per signal, which defines the code fragments to run when a signal is changed.
  • Some signals correspond to sensor inputs, so sensor updates will trigger code.
  • Some signals map to robot 'outputs' such as motor speeds, lights, and noises.
Here are several things that seem, at first glance, to be missing from the "language".
  • Names.
  • Loops.
  • Function calls.
  • Trinary operators.
  • Recursion.
  • Comments
The lack of names is intentional, (and there's no memory for comments) but the other concepts can actually be built out of the few axioms we start with.

This programming language is based entirely around "accumulator logic". The "accumulator" is technically the name of the big number displayed on a calculator screen. The number to which all operations are done when you press the buttons. Some calculators have buttons to store or reload the accumulator from "memory" slots, and it's this basic concept I ruthlessly extend, so keep it in mind.

Here is the complete list of all possible math and skip operators the language supports:

:=Left Assign=:Right Assign=0Skip if Zero
+=Left Add=+Right Add!0Skip if Not Zero
-=Left Minus=-Right Minus>0Skip if greater than Zero
*=Left Multiply      =*Right Multiply     <0  Skip if less than Zero
/=Left Divide=/Right Divide
&=  Left AND=&  Right AND
|=Left OR=|Right OR
^=Left XOR=^Right XOR

What's up with the "left" and "right" versions? Basically, it's the choice of whether the "next thing" modifies the accumulator, or the accumulator modifies the thing. All operators are 'symmetric', (including a few that don't make complete sense) and have only one "operand" (parameter) per op.

Assignment is the easiest to understand. If the "right hand thing" is one of the memory slots, then "left assignment" will load the accumulator with the memory value. If we "right assign", that's storing the accumulator back to the memory slot.

Instead of just assigning (copying) the value, we can 'combine' the source and destination numbers in various mathematical ways, like adding, multiplying, or boolean logic. But we always apply one thing onto another. (No triplets!)

There are some cases in which the symmetry is a little broken. Assigning the accumulator with the constant number "3" is clearly fine, but trying to set the constant "3" to any other value makes no sense, so it becomes a "NOP" - a "no operation". The closest thing we have to 'commenting out'.

However, either the left hand or right hand can be "indirected", and this is where the language powers up... I use surrounding brackets to indicate whether the side is treated as a raw number, or as a signal reference. Here's what a fragment of that code looks like:

  := 3Load accumulator with the constant value "3"
  =:(3)Store that in signal index (3)
  +=(4)Add the value of signal (4) to the accumulator. 
  += 1  Increment the accumulator by one.
  =+(5)  Add the accumulator to the value in signal (5)

Once again, the order and type of operations is exactly that if you had to solve the problem yourself using a calculator, albeit one with 128 memories.

Indirection is also symmetric: you can put brackets around the left hand side (the accumulator) and operations will occur to the signal that the accumulator value references. So the first two lines of the above code (which put the value "3" into signal "3") could be rewritten:

  := 3Load accumulator with the constant value "3"
():= 3  Indirectly load that signal (3) with the constant value "3"

When you are using the editor/debugger the accumulator values are shown down the left, so you know what's going where.

The comparison operators are a little different in that they don't have any indirection. They always test the current accumulator value, and their operand number is used as a count of "lines to skip" if the test is true. They don't even specify another value to test with... if you want to check equality with a number, you need to subtract that number beforehand yourself and then test for zero.

  :=(9)Load accumulator with signal (9)
  -= 13  Subtract "13", which is our test number
  =0 >> 1  If it was equal, skip the next line.
  := 1  Load accumulator with "1"
  =:(8)  Store the accumulator (now "0" or "1") into signal (8)

That's it. And while there are many obvious ways the language could be improved with extra "syntactic sugar" to make certain operations more convenient, they come at a cost.

  

Building Up From There

Function Calls:
So if there are no explicit function calls, how do we chain code together?

Traditionally we would define functions, their parameters, and return values. We'd name variables and have a call stack. We would have a line of code that 'calls' the function, and passes in the named variables on one side, to come out the other side with new names.

Remember that modifying a signal causes all the code attached to that signal to trigger and run. We can specify a code list in the original trigger, or we could (in one code) write a value to another signal which triggers more code.

What's happened here is that we now have to manually do the job the compiler used to. Variable names compile down, eventually, to a simple memory reference number. We now have 128 globals that we can put values into, and then call code which also has total access to those variables. So we can use the signals as the equivalent of parameter slots!

So instead of having a function which accepts three parameters, we can use any three signals we want as our parameter holders, and we make sure that changing one of them (or all of them) triggers the relevant code.

So we don't call functions explicitly, but we can change 'variables' which implicitly runs more code later.

However, we have lost the ability to wait for a reply. "Triggering" other code does not run it immediately. The current code fragment has to finish, before anything else can happen. In other words, we actually can't do procedural calls, but a form of message-passing.

Loops:
The language contains a 'skip forward' comparison operator, but no 'skip backwards' test, or 'goto' equivalent which would seem to be necessary to implement loops.

However, there's no reason why code can't write back to the signal that triggered it, in which case it will run again. Simple FOR-loops can be constructed by setting a signal to a start value, and decrementing by one if the value is still above zero. When the self-triggering code reaches zero, it will stop updating and the loop will end.

Since every triggered signal gets a chance to run (in order), multiple signals which are looping will be interleaved - a primitive form of multi-tasking.


Why?

The choices made seem weird, and restrictive, but let's look at some of the consequences that a LOGO or BASIC-inspired language couldn't do:

Multitasking: We could potentially have all 128 signals triggering themselves, checking for conditions to be satisfied, and then looping again. No signal is ever 'blocked' because another is performing a long calculation - since code always runs linearly, can't loop and can't jump to other code, each fragment is guaranteed to finish quickly.

Fixed Overhead: Moreover there is an essential problem with the idea of recursive function calls - they require a stack of unknown size. Every embedded call burns up more stack space, and there's not much to start with. We 'flag' code to be run, and get to it once the current code is complete.

Responsiveness: This is where the "Nervous System" idea comes in. We are not creating one big master program with a mainline code path - we are creating "fragments" that hang around waiting for their trigger conditions. "Reflexes", essentially. And we expect that sometimes those reflexes will work at cross-purposes. Hopefully the robot will externalize this conflict (by twitching to and fro) rather than sullenly sitting in an infinite loop.

LOGO has been the exemplar of educational programming for decades, but the kind of programming it teaches is close to obsolete. Web pages use javascript to attach event handlers to buttons, most of which never run. Databases use table triggers to cascade updates. Graphics cards have vertex and fragment "shader" hardware which do not allow variable-length loops or recursive calls or dynamic memory allocation, in order to get massively parallel performance.

Learning LOGO today would be counterproductive. It barely even prepares you for driving a turtle around, let alone modern programming concepts. And what I've found is that if you strip those modern esoteric concepts (Like "flow-based programming" or VHDL) down to their simplest axioms, their power remains.