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).

The Decommissioning of the Quadrotor Project

I bet everyone forgot about this thing!

I almost did, anyway. After the last test some time in July ended in one fan cracking its motor mount, fortunately not resulting in catastrophic failure, I lost my enthusiasm for flying objects and literally hid it under my cart of parts and stuff – as in, it fit perfectly between the wheels. I pledged that one day I will once again have a quadrotor boner and return to finish it off, since I did have a spare fan and all.

Well, I figured Thanksgiving weekend was as good as any. This year, MITERS seems to have accumulated a fair number of freshmen and newbies with quadrotors (and trirotors). The pressure was on to just finish it once and for all. It was a roughly 1 hour job to pull the damaged fan casing out and mount the spare, including printing a replacement tailcone.

noise isolation

During the testing of the Z-axis yaw rate control loop last time, I noticed a fair amount of mechanical noise coupling into the gyro readings. The gyros are mounted facing the same axis as the fans, almost in plane with them, and essentially on the end of a long carbon fiber stick. While the filtered readings were clean with stationary fans, they would become very erratic as soon as any power was applied. This was clearly visible in the test videos where the fans are jiggling quickly almost like they’re loose. The noise was of the same order of magnitude as the signal I was trying to get from the gyro – as a result, the filtering was not very effective. That was number one thing I was out to address before I moved onto the other axes of control.

I elected to remount the center Arduino Nano carrier board using memory foam – a tip I picked up from tricopter-nick, which is in fairly wide use.

With all 4 fans functional again, I was able to find out that the noise coupling was significantly lessened. It was still causing some trouble, but only when fan speeds were significantly higher than before – the “barely-touching-the-ground-hover” was mostly erratic jitter-free. Refactoring the yaw rate control code to not pre-scale the gyro readings also made the control less granular (and consequently even less shaky), and I also implemented a 2nd-order filter instead of a 1st-order. As a result, I was able to increase the loop PI gains by 2 times to yield a faster response to stick inputs. A little bit more driving on the ground like a doped-up robot on ice confirmed that the updates worked.

So now I was at the same external functionality I was 4 months ago. Yippee.

The only way I could get more data and test if the filtering and shock mount actually mattered was by continuing with the rest of the stability code.

how i killed the giant quadrotor

I hit the reset button on the Arduino. Actually, to be more specific, I left the controller calibration code in and then absentmindedly hit the reset button on the Arduino.

On occasion, I’d notice the fans peg off to one side and not respond to rudder stick inputs. They would some times recover again, but usually it required a power cycle to fix. I have a sneaking suspicion that my 2.4Ghz FHSS transmitter and the 2.4Ghz FHSS Xbee modules I had as a data link were Frequency Hopping over eachother’s Spread Spectrum at times.  Regardless, my usual rigorous procedure is to completely power down the electronics and then restart them.

The number one mistake was not commenting the calibration code out after the first time. After I temporarily decommissioned it the first time in july, I had “borrowed” one of the Turnigy 100A controllers for melonscooter. With melonscooter having moved onto greener melon vine patches,  I returned that controller to quadrotor duty, but it had to be recalibrated again.

The calibration procedure for these R/C controllers is full-stick within 1-2 seconds of powerup (2000uS pulse width), hold, then neutral stick (1000 or 1500uS, depending on your type of stick). This has to be done within 2 seconds of powerup, or else the ESC initializes and waits for command. The problem is when 2000uS is commanded after the ESC is already on and initialized, that means gun it.

For reasons I can only explain as “meh”, I elected after testing the yaw rate controller for the last time and seeing it lock up to just hit Reset on the Arduino to clear all the readings and start over, without powering down the ESCs. About 1 second after I did so, the stunning realization of idiocy hit me – along with the entire thing.

I only really remember leaping back as it flew upwards and sideways towards my head – keep in mind stabilization code wasn’t even written yet – and batting it out of the air with my left arm before ducking and turning around. It did a powered somersault over my head and crash-landed on top of a substantially more solid vehicle, and consequently shattered into many pieces.

It took me a second or two to realize what had happened, upon which I leapt for the big red key switches of main battery disconnection. The two remaining fans were still spinning – a consequence of me knocking over the radio – but luckily only slowly.

Pieces of fans were being collected from across the room afterwards – this destroyed rotor was found a few feet away with motor still attached.

I didn’t escape without damage. Batting the Deathcopter from the sky, I was grazed by what must have been a ducted fan leading edge:

In what is probably the luckiest near-miss I’ve ever been in, I’m only missing about 3 square inches of skin from my left forearm where the fan scraped it off. There’s 3 very evenly spaced cuts where I presume a rotor dinged me while disintegrating, but none were deep. Bleeding was slight, so the damage was cleaned, bandaged up, and ice-packed. It could have gone way more wrong in many possible alternate scenarios.  I’m still periodically testing my left hand fingers and wrist for full motion just in case.

What’s the lesson for other quadrotor builders who use RC controllers?

Well, besides don’t be a total dumbass and violate your own safety procedure,

calibrate the motor controllers once and cross it out of your code after.

This accident was totally avoidable if I wasn’t trying to rush to get to writing the stability controller.

Nevertheless, with 2 fans completely destroyed and the other two now in unknown condition possibly with structural damage, and the frame in many pieces, I think this project is done. Maybe I will instead concentrate on other flying things, or maybe I’ll build a more normal quadrotor or a tiny and cute one I can swat without worry.

The Once and Future Ballcopter

First off, some minor updates on the not-Land-Bear-Shark (a.k.a the quadrotor, deathcopter, and myriad other pet names I and my peers have assigned to it). I’ve tuned the Z-axis rate controller some more such that now the yaw rate is much more controlled and the servos less twitchy. Powering those fans on injects massive amounts of mechanical noise into the sensors, so much that I’ve begun to consider coding more robust discrete-time filters in the software to target the vibrational frequencies that the fans so readily emit. I was ready to move onto testing the pitch and roll control software, though, when the problem suddenly became a little less virtual:

Oh boy. When you hear the scratchy-fan sound and look up to see a fan rotor hanging halfway out of the duct, it’s time to stop hovering. I guess this is why cheap ducted fans are cheap.

The entire motor mounting face seemed to have broken off; luckily the motor was held in by its power leads, otherwise there would probably be a hole in the ceiling somewhere. I’m not sure what plastic the casing of the fan is made of, but it does seem quite brittle. With the motor mounting face being the focal point of all the stresses the fan rotor imparts on the system, any manufacturing defect (like voids or local shrinkage) or increased loads (like from an off-balance rotor) would make the area prone to failure.

This fan is the most unbalanced of the entire set that had their shafts replaced, so I’m not surprised it was the first to go. However, it’s still a bummer – luckily only $40 lost and not $400 (then again, perhaps a better made fan would have never failed or been off balance). Otherwise, it’s also a hassle to have to replace the whole thing – the rotor is also well-trashed by being ground against the housing at a few thousand RPM. Fortunately, I have a spare (the very first one tested, in fact).

Now, I naturally gravitate away from projects as they enter the software-only stage. During the coding of the yaw controller, I was also thinking of distractions to embark on so I have an excuse to not write code. With this thing temporarily out of mechanical service now, I’m going to take a little break to recharge my code-monkey-pacitor with a project that only requires more software.

I knew I couldn’t leave Ballcopter alone for long. Despite its parts now having taken two and a half weeks to get back to the East Coast (still having not managed it as of right now… seriously, USPS?), I do have enough parts back here at base to independently build version two. Not that I would want to do that, since I did order an entire new radio for the thing…

So what’s different about BallCopterTwo? Hopefully it will be 1000% less terrible. What ultimately failed on the first design was my complete failure at creating control surface linkages. Airplane parts and building methods are still weird to me, which is part of the reason why Chuckranoplan hasn’t moved much from where it was in May. For the new design, I had intended to move to 8 independent, direct-driven flaps, mixed in software, such that there were no linkages involved, but figured that would negatively impact the vehicle weight. However, it took a new video of the original Japanese ball drone design for me to seriously pursue the 8-servo route. Here’s a screencap from the video.

Those sneaky bastards. Well, you can only get spiral deflection of the flaps like that if each one is actually independently driven. Two can play at that game:

Other changes to the version 1 design are a sleeker center column thing which should reduce weight even more and control flaps that aren’t way oversized. Because processing 4 channels of radio control into 8 servo channels needs software, I’ll probably whip up a quick board that carries an Arduino Nano and an IMU module – basically a condensed version of what’s on the quadrotor, stripped to the bare necessities. As long as I have a microcontroller onboard, it will be gyro-stabilized using the gyros on the IMU – I have plenty of practice now from making the quadrotor yaw controller.

Remember kids, don’t cut foamcore on the laser cutter.


4Chan, the Four-Channel Isolated Charger

In a previous episode of the quadrotor show, I mentioned modifying a single four-channel Hobbyking battery charger (this one) into four isolated single-channel chargers. Well, that operation has been done… so at least now I can charge the quadrotor in one shot. The process involves cutting some traces, a small amount of surface-smount desoldering, and getting four isolated power supplies for the resultant charger channels.

So this is what the inside of the thing looks like. It’s mostly three copy and paste operations, with a few differences to accommodate mounting holes and the fan connection. The main power bus is on the left side – positive on top, negative on the bottom.

The power semiconductors are all on the underside, heatsunk to the aluminum case with silicone pads. The board standoffs keep the switches pressed against the chassis.

These common power traces are the ones to cut. I used a Dremel with a cutting wheel to separate the trace into four sections between the inductors. The fans receive power from the very end of the power trace, so it is now associated with one channel (it will still turn on according to temperature, but pulls from the power supply for that channel).

After this, it’s time to get some power supplies.

I bought these cheap switching power adapters (supposed to be used for LCD monitors) from Ebay for something like $10 each. They’re about as shady as you can possibly get a power supply, I suppose. In fact, they were so cheap that I cracked one open to see if it was really isolated or not. I see an optocoupler and isolation transformer, so I hope that means yes.

The rating is 12v and 5 amps, which is about 10 more watts than the HK Quattro should be charging at (50 watts) so it was a good fit.

Each channel needs to be connected to a power supply. I just used the long wire the PSUs came with to complete this operation. Positive on top, negative on the bottom.

This is where I decided to get Extra Fancy and made a supplementary case to hold the whole thing. It was designed in around 3 hours and then cut out of clear acrylic plastic on a laser cutter. This step is of course not necessary, but it organizes the wiring alot. I dug an IEC power jack out of a pile of old power supplies and made a 4-way split cable with the line cords that the PSUs came with. No, it’s not grounded.

It’s also really hard to take pictures of clear acrylic.

The charger mounts on top of the power supply case using its existing four rubber leg things. After making sure it powered on, I reassembled the case and put the whole thing together.

Unfortunately, the first test proved to be inconclusive. While the channels were DC isolated, clearly there was still some kind of coupling going on – whenever one channel started charging, the rest of the channels would freak out and some times reset. If I started another channel charging while one was already running, all of them would freak out and terminate.  The LCDs would also some times all blank if one battery was plugged in.

Clearly I missed something, so I took the charger apart again for a close flashlight inspection.

Here’s the culprit. I noticed a capacitor connected between each channel and the frame at each mounting hole. This is most likely a noise decoupling capacitor, but together they connect all the channels to chassis ground.

This is no problem if all the channels operate at pure DC offsets since capacitors are DC blocking. However, my guess is that the AC component of the switching power supply outputs is being transmitted across the capacitors on each channel, which is wreaking noisy havoc everywhere.

These caps had to go. There is one per mounting hole – just follow the lead emanating from the copper ring and remove the first capacitor you run into. And only that one, as far as I can tell. This can be done with a big soldering iron and a solder blob, or small iron and rapid back-and-forth heating of the two pads of the capacitor. Or you can dremel it off or something.

The behavior after this was much better. For some reason, the bottom channel LCD still has a contrast issue when any others are plugged in and running. However, it does not seem to affect the way it operates. I tried testing the isolation by trying random combinations of chargers and battery halves, and am proud to say that they all do work together.

The maximum charge rate for the Quattro on 5S lithium polymer batteries seems to be about 2.8 amps maximum. This works out to 60 watts or so, not accounting for inefficiencies (it does get quite hot for a 60 watt max charger – much much hotter than my 1010B+ ever gets, period). The shitty monitor power supplies also have thermal issues when charging at full capacity, so I think they’re either overrated or just that horrible. They only let the charger go full rate if there’s a fan pointed at them.

With these thermal issues in mind, I might append or redesign the base to house a small PC case fan. But in the mean time, it works!

It Drives Like A Robot

The result of a day of software head-bashing: getting your alleged air vehicle to behave like an awkward robot on barbiturates.

Only the Z-axis yaw controller is complete at the moment, and it still needs some tuning. The job of this controller is to keep the yaw rate of the vehicle under pilot control – such that it doesn’t spin in place and can track (relatively) straight. It adds an equal constant offset to the tilt angle of all the fans as to induce a spin about the vehicle’s vertical axis. This has a few issues – namely the gyro is a 300 degree per second full scale type, and this vehicle should never, ever be going 300 degrees per second in any direction. Hence, I really get to use only a few least-significant-bits (LSBs) of the analog reading from the sensor, making the control a little granular. I still need to play with filter speeds and gains as a result, but it’s kind of working.

The fans are otherwise controlled open-loop by the aileron and elevator sticks of a standard airplane radio. The Z command is mixed into the directional command. Otherwise, I haven’t coded up the pitch and roll controllers yet – hence my desire to stick to the ground and apply just barely enough throttle for the vehicle to break friction. The vehicle’s controls were therefore a rotation rate on the Rudder stick, and two planar translations using the right stick.

As seen in the video, it’s distinctly right-side heavy, so I’ll shuffle batteries around until it’s mostly balanced without a controller.

Tomorrow comes diddling with the Two Orthogonal Segways part of a quadrotor: Two Orthogonal Segways and a Robot.