In the Interest of Future Flying Objects: XBypass

Despite losing the Spruce Goose of Quadrotors to an unfortunate semi-controlled flight into terrain where I was the terrain (from which I’m still recovering… the square area of skin has recovered by more than 75%), I haven’t quite given up on the prospect of building a flying thing yet – but for now, they will be smaller and more easily batted from the sky. For instance, I’ve figured out why Ballcopter never worked properly. The very last update left it in a state of limbo, which I can sum up in one sentence: No, it didn’t work, but more on that later.

Eventually, Ballcopter was scrapped as its foam structure was slowly eroded away by virtue of existing in MITERS.

But there will be a day.

In the mean time, I wanted to satisfy one of my persistent self-stabilizing-flying-thing itches: how to pass control inputs from a handheld  radio to the flying thing in question without having it process several consecutive servo pulse lengths. For the most common & simplest Arduino-compatible balancing algorithms, this limits the maximum control update frequency to 50hz, since the microcontroller has to actually measure 10 milliseconds of pulse commands (for, say, up to 5 or 6 channels) out of every 20 milliseconds. The remaining time is often taken up by software floating point multiplication and division.

The reason it takes so much of the loop time is because the abomination that is Arduino’s pulseIn() command. It’s a “busy wait” loop that sits and increments a counter while the pulse is being detected. It’s neither interrupt based nor uses the hardware timers (the loop is timed empirically). So while taking in a servo pulsewidth, the microcontroller can literally do nothing else. A little inefficient, in my mind.

More sophisticated ATmega based flight controllers like the Ardupilot use the chip’s hardware timers and internally generated interrupts. For instance, as far as I can tell in the Ardupilot, Timer 1 is constantly running (counting) and overflowing (resetting to count more), and pin change interrupts on the input pins are used to capture snapshots of the counter status, and the resultant pulse width is just the difference between the values when the pin changed from low to high (pulse started) and from high to low again (pulse ended). And if the counter overflowed while the pulse was high, no problem: just add the max possible value of the counter to the pulse width variable and keep counting. Yes, I spent a few hours reading Ardupilot source code to figure that out.

And no, I’m not going to steal it and use it, because it’s written all in straight Atmel C, and so it might as well be gibberish to me. I can read and  understand it, but hell if I’m going to write it.

One method around the onboard servo processing problem is completely bypassing hobby radios as an interface medium, which people often do with joysticks (with or without tethering to a computer). For example, there is the Arbotix Commander, which is essentially an XBee and Arduino in a completely unergonomic, overpriced package which seems to have functionality problems based on a few reports from my peers – I had the displeasure of dealing with the first version personally. Shane tethers his USB Playstation controller to a laptop, but that means the laptop has to be deployed whenever something has to be operated (The upside is infinite debugging and telemetry ability, which a plain R/C radio doesn’t give you).

So really what I would like is the ability to replace the transmitter-air-receiver-servo_pulses interface with something much more direct – like serial over wireless; something that just takes the transmitter inputs and pipes them directly to my vehicle, where it can be buffered and read at will. XBees make the serial over wireless problem very easy to solve. The result would be an XBee using a cheap R/C radio as a brainless “trainer box”: most radios have a “trainer port” over which servo pulses can be sent (over a cable) to a master radio, for situations like when you’re actually training someone who is utterly clueless about flying things (me) and want to take command of the vehicle if anything bad should happen. If this pulsetrain is read and parsed at the transmitter, then I effectively offload the overhead of processing servo pulses from the vehicle – allowing it to process much faster (hundreds or thousands of Hz) and making closed loop control less granular. My inputs would still be updated at 50hz, of course, but I doubt I can react to an event as fast as 0.02 seconds anyway. The vehicle can keep itself stable much faster.

Anyways, that’s exactly what I built. An Arduino Nano, reading the pulsetrain from a transmitter trainer port, and piping the read values as bytes over to an XBee.

It’s not nearly as epic as I made it seem to be, seriously.

I have two cheap 2.4ghz transmitters, one of which I got ages ago for Cold Arbor, and another one I picked up over the summer for Ballcopter. Which really means I have 2 of the same radio. They are both made by FlySky, but the right one is a Hobbyking rebadge. These things cost $28 brand new, with receiver, and some of the consequences of that cheapness show through – for instance, they don’t come with external servo reversing switches like every other radio, but the holes and pads are present internally to use them and if you mount your own switches the functionality is even there in the microcontroller, but no we will absolutely not spent 20 more cents to install those damned switches.  They have a 4-pin mini-DIN (also known as S-Video) connector on the back which is a trainer port.  And as usual with small Chinese gadgets, there is a community devoted to hacking them. It took me all of 10 seconds of Googling to find the pinout of that trainer port.

A little scope probing of pin 1:


The PPM pulsetrain


And zoomed in further.

The biggest difference between this “PPM” signal and the servo-style “PWM” (which isn’t even “PWM” but pulse-duration modulation… which collection of idiots agreed on these terms?) is that

  • It is falling edge driven – the time between falling edges of the square wave is actually the duration of the “PWM” pulse. When the receiver detects one of these falling edges, it will stop outputting the pulse on one channel and immediately start it on the next.
  • As a result, the actual “High” time of the pulse only goes between approx. 600 to 1600 microseconds on my radio
  • The low time is fixed duration at 400us. Makes sense – the minimum pulse lengths on the servo side, then is roughly 1000 to 2000us as it should be.
  • It “idles high” – meaning the gap between signal is +5v.

So I’d have to come up with a way to distinguish a signal pulse from the long idle pulse. Arduino’s pulseIn() doesn’t even allow in-pulse timeouts. It allows pre-detection timeouts, so you don’t wait forever for a pulse if it never comes, but it does not have “hey, this pulse is over the length I care about… let’s move on with life”. I’d have to get around this by throwing away the first update and “syncing” to the rest of the pulses, since I know how many there are and about how long they should be.

The first step of the hardware hacking was disabling the internal radio. As I found out while building the Deathcopter, 2.4ghz radios will tend to step on eachother. I didn’t want to permanently take this radio module out, however. Leaving myself the chance to return this radio to ‘normal’ duty if I ever figured out something better, I just added a pin header connection to the power supply wire. It would be left disconnected when I’m using my hack.

Next was throwing the hardware together on a perfboard. This little arrangement costs way more than the transmitter ($17-34 for an Arduino Nano and $22-25 for an XBee regular 1mW), so I really hope this isn’t the terminal solution. It’s also way underutilizing the Arduino right now, since I only have Tx and Rx pins connected, and one other digital pin hooked up to the PPM output. The transmitter provides 5 volts from the trainer port, so this board has no other power supply.

The XBee is mounted on an Adafruit XBee Adapter.

And that’s it.

Yeah, I didn’t even bother trying to source a 4-miniDIN for this. At least, not until my Digikey order arrives – until then, it’s wires jammed into sockets.

I took a few minutes hours to write the single pin read, serial write software for the Nano. The hard part was, again, thinking my code does one thing but really having it do something different – just logic errors, all caused by having to differentiate the long idle pulse from the servo pulses. But at the end of it:

There we go. I’m only piping back 5 channels out of 6 here, but this was successfully done over the air between 2 XBees. This is all done using Serial.print(), which converts everything to ASCII and thus has unnecessary overhead. When commanding a vehicle, I’d just send the raw byte values because I’m fairly sure my vehicles are not literate.

So how do I test this contraption? With someone elses’s flying object, of course.

4pcb became the subject of a few transmission tests and a whole lot of floor whomping, as seen in the test video:

While not the most economical option, it does work, and it does solve the problem I wanted to solve. I’ll probably look to refine this board or permanently mounting it inside the transmitter, possibly with a plain ATmega chip by itself so I at least don’t have to buy even more Arduini. Otherwise, creating a dongle using Arduino USB host shields and an XBee would open the floor up to using just about any gamepad or joystick as a remote.

The “XBypass” sketche as used on 4pcb is here. The general idea was to wait for the first time the 9ms long timing pulse was received, then immediately start taking in n channels, storing them, and then processing them into single-byte values (for transmission convenience as well as because 4pcb takes such single byte commands).

I Swear I’m Still Working On This Thing

Seriously! I promise I will poop out a new 3D printer by the end of IAP. Now that the holidays break is in full swing and everyone else is gone, I can focus on actually finishing up the design, rather than, say, be constant distracted by things happening at MITERS. I pushed out several orders for materials (including something like 30 square feet of acrylic sheets) and more mechanical parts before the Christmas Everything Shutdown, so hopefully I’ll have all materials in hand come January.

In the mean time, here’s another week or so of on and off work, including testing of the space heater platform and design of the XY gantry head. First, some more waterjetting which was not covered in the last episode.

I think I have made my first impossible-to-cut part. The heater grille has so many little things that can possible stick up into the machine path that, even with careful manual routing, I was unable to avoid interference accidents. And no, it does not have a powered Z axis so I can do head-lift traverses. I’m not that spoiled yet.

After writing off this piece, I tried again, but this time routing the machine to cut out everything but the little grille bits, then doing those last. That way, I can still have consistent mounting dimensions – who cares if the grilly bits are misaligned slightly? To make sure the piece didn’t float away after the separating cut, I inserted small tabs periodically to hold it in place:

I used a chisel and hammer to shear off the small tabs to separate the part. As can be seen, there was one bangup regardless, and there are parts of the resistor mounting holes which come close to the material edge as a result.

Oh well.

The proper method would have been to individually tab each one of those vents, and to manually route the path to start and stop on those tab cuts to minimize nozzle cycling. I wasn’t that patient.

0.22 ohm resistors mounted with a bit of thermal paste. I found out that no bolt head in existence fits in the little mounting tab given, so I had to drill out all of those mounting holes and actually tap the resistor’s aluminum body with M3 threads. They seem to work fine.

I actually bought one of those huge case fans seen in the Z platform models from xoxide. Actually no – I got 2, one to mess with and one to actually use, as per standard operating procedure. They move reasonable amounts of air for their size and low speed, and are indeed very quiet. The actual fan diameter is about 220mm – I found out which dimension is actually 250mm on these things, and the answer is the corner to corner measurement on the outside of the mounting tabs. Failsauce noodles.

Check out the new platform on top of MaB. This thing is going to be enormous – the standoffs mark the bounds of the build plate, which will be 250 x 250mm.

The big question after putting together the platform with wired resistors is whether or not it would dissipate the watts needed to bring the internals of the machine up to a high temperature. Fanning the resistors at room temperature showed that the 1.76 ohm arrangement (8 0.22 ohm resistors in series) isn’t very powerful at all. It draws about 80 watts, but it’s difficult to feel warm air even an inch away. Probably because the resistors are very, very well heatsunk and I just installed the sexually dimorphic father of all computer fans (this is the larger female of the species)

But future-MaB wasn’t going to be heating things up at room temperature – it’s going inside a box. For true thermal testing, I needed a box.


In this picture: a box

Conveniently enough, a box of essentially the right size was standing by.

I commandeered this early prototype of an arduino vending machine project by a certain Nancy (who is currently stomping it out in Asia – make sure to keep up with her blorg). It’s made of cardboard and very much glued and taped together. But hey, that’s all I need.

I actually love this form factor, by the way, so don’t be surprised if I just end up gluing everything to the inside of this

I stuck the platform on some big aluminum standoffs, hooked it up to 12 volts (uncompensated – I wanted a realistic simulation of losses in the wires), and closed the box up.

On the as-designed 80-watt setting, it was horrible. I think the temperature barely crested 40 celsius after 10 minutes, which is my benchmark for acceptable bootup time due to current MaB’s giant resistor board. Probably because the cardboard box leaks air everywhere and isn’t a good thermal insulator alone.  Sadly, I could not locate an IR thermometer (or even one of those stupid things you mount on your window… sadness), so the estimate is very much biased by my hand waving around in air, which given that I regularly act as my own soldering fixture, might be miscalibrated.

I went on Digikey and Mouser to see what the next value smaller resistor was available. I only have 8 mounting points, so I’d have to come up with a reasonable solution which was not just paralleling four resistors on each side of the board – that drew like 30 amps and was kind of insane. By going to 0.1 ohm resistors, I could get a power dissipation of roughly 180 watts.

The next step was to just pump up the power supply to 180 watts. When you’re just dumping into resistors, watts is watts, so the final setting turned out to be approximately 17.5 volts at the heater (the alligator clips eating like 2 volts on top) and 10 amps. This time, the results were much more promising. It certainly reminded me of the inside of a commercial printer, but again, without an IR or traditional thermometer, it’s hard to judge. I would estimate that it was over 60 celsius, but not with certainty.  I thought about hijacking MaB’s platform heater thermistor for a moment in order to get a good air temperature reading, but it was a little more work than I wanted to deal with at the moment.

The good news is that the shady case fan worked fine in the higher temperature environment.

My resistors are delayed due to the holiday break, but once MIT opens again briefly next week I should be able to get more testing done (as well as pick up a reasonable thermometer from somewhere)

a bit more design

I’ve been really lagging on the actual machine design this time, something which I took the past 3 days or so to address. The reason it took so long was because I’m a grad student that I… you know what, fine. I admit it. I’m a grad student. I spent more time thinking about different ways to design it rather than just merrily beasting along. Starting the first part file is always the hardest part of designing something entirely new, because you have to select yourself a ground point for the whole thing. At this point in the design, I was just aiming to have some kind of parallel gantry to stick Tinystruder to – dimensional adjustments and remodeling can come after I get a good look at everything.

Here’s some of the “mechanical penthouse” solid geometry. I picked an arbitrary square size – in this case, 400mm, selected for me by the fact that McMaster sells 400mm long shafting. The pulleys were selected from B&B Manufacturing and SDP-SI (who seem to gun for eachother and have “competitor” part cross references that are exactly eachothers’ part numbers) based on both price and diameter – the pulley diameter determines how far offset the X and Y rods have to be. This part was relatively simple.

What wasn’t as simple was designing the axis anchor blocks. Above is the most elaborately t-nutted thing I’ve ever designed…but it sucks. It requires 4 unique parts to be cut, and a cube only has 6 sides. When you have a waterjet, everything looks t-nuttable.

But what was important was that designing this thing gave me the critical dimensioned I needed for the part. After that, I could quickly whip up a better designed replacement:

Some times, thinking outside the box isn’t the right approach – the box must be thought about from a different axis. This axis anchor design is much better executed, requires fewer unique parts, and is fully constrained by 4 corner bolts. It even has provisions for a real belt-clippy-thing on the bottom (one axis runs the blocks inverted for clearance, so the thing on the left is still “Bottom”). It’s also smaller.

I legitimately thought about just machining a block of aluminum for this – the whole assembly can be replaced with a small cube that has two holes in it. One to hold the linear bearing, the other to hold the cross rod. But that wouldn’t be in the spirit of things, now would it?

The general idea explored in the anchor blocks was applied to the head mount. Because my cross rods don’t start in the same plane as my axis guide rods (unlike, say the Ultimaker), the end effector is a little tall. The rod separation is 40mm. There was no particular reason why I made the rods offset instead of in plane – it was just the first thing which came to mind.

And possibly because skew-offset rods are easier to install, and that further-spaced supports for the massive steel and aluminum testicle that is Tinystruder means more torsional stiffness along the axes.

Because Tinystruder sticks out more one way than the other, the gantry can’t be perfectly centered upon the build plate. This is a composite image of the maximum positions that Tinystruder can travel to at the moment, centered upon the build plate i.e. able to hit all corners. However, this puts the Z-axis in a slightly inconvenient position (halfway hanging out of the square base), so I might have to extend the platform arms even more to compensate for it. Or adjust some other dimension, or make the build volume rectangular, etc.

Now that the hard part of the machine design (in my opinion) is done, I hope there’s nothing to distract me in the near future so I can finish it off.