CatsEyes Aerial Photography

Introduction

This page contains some preliminary thinking of mine on the subject of trying to build an autonomous flight vehicle. I am at the very early initial stages of the design right now, having only done some preliminary testing.

This has been one of my dreams for a while now: to be able to direct an aircraft to fly to a specific location, at a specific altitude, to take a photograph. I have in mind dozens of spots out in the middle of the wilderness where it would be difficult to get close enough to direct the plane by line-of-sight. There are (at least) two approaches to this end. First, one could mount a video camera on the plane that transmits "what the plane sees" back to the pilot, allowing him/her to pilot the plane. This is referred to as FPV (First Person View) and is being done by many R/C pilots. The other approach is autonomous flight, in which the airplane pilots itself without any input from the pilot. As I envision it, the pilot will still do the takeoffs and landings the "normal" way, i.e. by radio control, but plane then will fly itself inbetween.

The following noodlings and meanderings are just a "brain dump" of my current thinking on the subject. I'm presenting it blog-style, with dated entries, for now so you can see how things are developing and evolving. Obviously much still has to be worked out and many of these ideas will probably not survive the first design revision. (No plan survives first contact with the enemy and all that.) However, you gotta start somewhere...


August 22, 2009

Modular approach

Obviously, for an autonomous flight vehicle, there will need to be a good bit of software written. Software is, of necessity, written in a modular fashion. But I thought it might be useful to extend this concept to the hardware level as well.

For instance, a particular controller could be dedicated to altitude. It's job would be to place the model at a specific altitude and keep it there. There would be one input that would sense the model's altitude (probably from a GPS receiver), and one output (probably the motor throttle control).

It is interesting to note that in the natural world, animals have evoloved this approach as well. The central nervous system coordinates the organism's actions, but much of the mundane processes of balance and "putting one foot in front of the other" are handled by peripheral nerves.

The "brain" would, clearly, have to be a fairly powerful (in relative terms) controller which would be responsible for navigation and overall control. It would determine if the model was on course and issue instructions to the other modules if it was off course. But the instructions could be fairly simple, i.e. "go to 1500 ft" or "turn to a heading of 30 degrees", rather than micro-managing the throttle and rudder at every step of the way.

The advantage I see to this is that each of the module could be developed and tested separately and any bugs worked out. Once any particular module was working properly, it could then be included in the overall system without any further worry about how it would perform. (Theoretically)

How to LAN a plane

There is also the problem of how to tie all these modules together. What I envisage is a sort of "local area network" (LAN) on the plane, similar to a home network but at a much lower bandwidth and much simpler protocol. It would probably consiste of three wires, ground, power and signal.

The LAN would allow each of the modules to communicate with each other. At its most basic (and for the first test of the system), it might consist of nothing more than what is usually on an R/C plane, a receiver, ESC (motor speed controller) and several servos for the control surfaces. But these would be tied together using the LAN, rather than all those wires running from the receiver to wherever. Obviously, each of these modules would have to be a bit more complex as it would need to write data to, and read data from, the LAN as well as performing its own functions.

Other modules would then be added, one at a time, and tested thoroughly before moving on to the next. One of the first would probably be a "telemetry module." Like the "black box" on full-size aircraft, its job would be to record flight parameters throughout the flight, which could then be used analyzed what went on during the flight, and, if something went wrong, could (hopefully) be used to figure out what. The recorded data would simply be all the information going over the LAN. This would included, at a minimum, the data that would be necessary to fly the plane, but the modules could be designed to output other data over the LAN (i.e. data not necessary for flight) that might be deemed to be useful to figure out what was happening internally within the module.

Currently, I see the following modules in a basic autonomous flight system:

  1. R/C receiver module,
  2. ESC module,
  3. rudder servo module,
  4. elevator servo module,
  5. GPS receiver module,
  6. navigation module,
  7. altitude module,
  8. heading module,
  9. flight data ("black box") module

August 27, 2009

To describe this concept as a LAN or "network" is perhaps to give it the wrong impression. It would probably more properly be called a "serial bus." I have been researching some of the existing bus specifications out there to see if anything would be appropriate. The most obvious one is the I²C bus.

The I²C bus

The I²C bus sounds on the surface like it might be ideal for my purposes. It consists of just two wires (not including ground and power). I was hoping to get away with just one, but two is not onerous. There is a lot of flexibility in terms of timing and, for instance, a node that is receiving data too fast for it to process can tell the transmitter to wait until it catches up. Since I am not planning on dedicated hardware, this might be useful.

However, upon further investigation I think it may not be exactly what I want. It is really designed for point-to-point communication, where there is a specific transmitter sending data over the bus to a specific receiver. I was envisaging more of a "broadcast" type of scenario, where a node would identify itself and the data it was sending, but not specify a receiver. Any other node on the network (which might be multiple nodes) could use the data.

The I²C bus seems to be geared to a more standard computer system architecture, where there is a central, relatively powerful CPU communicating with several peripherals. The communication is initiated and mediated by the CPU, whereas the peripherals just respond slavishly. This is really not in keeping with the modular approach I am envisaging.

Finally, it looks like the programming required might be somewhat complex to implement the I²C bus specification, or even a subset of it (for instance I would not need the "multi-master" mode). I am not afraid of a little programming, but code space is limited in some of the controllers I have in mind.

Therefore I have concluded that the I²C bus is not going to meet my needs. Researching it has been useful, however, in that it has given me more focus on the bus I actually will be designing. I may also want to implement a short I²C bus segment to interface between my bus and an EEPROM device to store flight parameters (the "black box").

Links: I²C-bus.org, I²C Wikipedia article, Serial EEPROMS, I²C tiny usb, userial, I²C-bus specification (pdf)

Current bus concept

The concept as I now have in mind would work as follows.

There would be a single "master" module that would take care of timing on the bus. It would "poll" the other nodes to see if they had any data to transmit. The other nodes would not transmit their data until polled and this would thus avoid collisions. Polling would be done one-by-one for each of the nodes on the bus. If a node's address was polled and the node didn't respond within a certain time, it would be assumed to be busy or have no data to transmit and the master module would move on to the next.

A complete polling cycle (all nodes polled) will probably end up being 20mS, the same as the receiver's frame rate. This would make sense as the receiver module will be "busy" timing the receiver pulses for much of the time, but after all the pulses have been measured it would be available to transmit its data to the bus. The other modules can I believe be designed to wait for their turn to transmit, or can easily skip several frames if busy doing other things. For the servo and ESC modules, which are going to output a standard servo signal, the 20 mS cycle makes it very easy to program these modules (probably at least two and possibly three "modules" could probably be combined on one controller).

I imagine the receiver and master modules would be separate controllers, and separate nodes on the bus, but might be linked by an extra wire to syncrhonize timing. That is, the receiver module would send a signal to the master module (not over the bus) saying, in effect, I have data now, please start the next frame." I might also futz with the roles a bit, so that the receiver module would act like the master module for a short period of time and start the polling sequence, in effect polling itself, then transmit its data as per any other module. The master module would then take over the polling for the rest of the nodes. I don't think it would be possible to combine them in one controller, since the master module has to do the polling at the same time as the receiver module is timing the receiver pulses for the next frame.

The basic R/C aircraft configuration (before the introduction of any autonomous flight capability) would consist of the R/C receiver, the servo and ESC modules. Once this is complete and functional, I can start working on the other modules. The next one to be introduced would probably be the altitude module. I envisage the altitude module will work like this. In the full autonomous flight mode, it will receive instructions on what altitude to fly the plane to from the navigation module. However, at first we can just test the module's ability to fly the plane to a certain pre-defined altitude.

The altitude hold module would listen to the receiver module's output on the bus. One of those channels will be a toggle tied to a switch on the pilot's transmitter. When the pilot triggers this switch, it puts the plane in autonomous flight mode (or during the testing I am describing, in "altitude hold" mode). When the altitude module sees that the pilot has switch to altitude hold mode, it begins sending commands to the ESC module to tell the motor to speed up or slow down to put the plane at the correct altitude. The ESC module initially listens to the receiver module's channel 3 signal (the standard throttle channel) to decide what to do, but it also listens for the altitude hold module. If it finds commands from the altitude hold module, these commands override those from the receiver module and it responds to those commands instead. (It might also listen to the trigger channel from the receiver as well, to make sure the pilot indeed triggered altitude hold, as a precausionary measure.)

This of course puts a specific requirement on many modules to monitor a specific channel from the receiver and compare it with a specific value to determine if the plane has been toggled into autonomous mode. This is probably not a good idea as it would require re-programming many of the modules if this mapping ever changes. A better solution is probably to put this logic in the receiver module, which would then transmit a mode byte that would have a specific unchangable meaning. If the toggle mechanism ever changes, then it is only the receiver module that needs to be re-programmed.

At the moment I am thinking of just two modes, "R/C mode" and "autonomous mode," but this would allow other modes to be introduced. For instance, there might be a "return to home" mode that could be triggered under certain conditions that would cause the plane to immediately try to return to the location it took off from.

Way forward

The first step will be to develop a tentative bus protocol and try to implement a simple data transfer between a couple of controllers. Actually trying to program and test the protocol will I think give me a good idea of what will work and what won't, whether it will be too code-space intensive, whether it will be too slow, etc.

I also will have to take a look at the actual R/C receiver I am going to use, an XPS 2.4 GHz spread spectrum receiver. There is no necessity, for instance, that the channels be serialized (i.e. the pulse on channel 2 occuring right after the pulse on channel 1) the way they are for a 72 MHz receiver. I am hoping they are (it's probably easier to design it that way), but there is no guarantee. In worst-case, if all the pulses occur at once and overlap, I'll probably need one controller per channel! If they are serialized, I should only need one controller for all the channels.


September 7, 2009

I have now got a rudimentary protocol set up and have run a few tests to make sure that the microcontrollers can actually send and receive data over the bus. I decided to use the term "packet" for the discrete collection of data that each module will put on the bus. I realize again it sounds a bit more ambitious that it is, but I couldn't think of another term. I was calling it a "frame" but there are two reasons why that is not appropriate. First, a frame usually refers to a fixed-length time-slice, and my packets are variable in length. Second, it would cause confusion with the 20mS R/C "frame."

Inter-module communication tests

This test was an attempt to get two microcontrollers to talk to each other (or rather, one to talk to the other) over the bus. One was set up as both the master and transmitting module (i.e. it transmitted the break, module select byte and the packet data. The second acted as a receiver only, detecting the break and decoding the module select byte and data stream. The data was stored in EEPROM for later analysis.

Results

It was necessary to re-do the receiver slightly. The time taken to write a byte to EEPROM (several milliseconds) meant that it couldn't be done in real time, i.e. as the data is received. Instead, I stored it in a buffer in RAM and wrote it out to EEPROM at the end of the test. The test was determined to have completed when a long (500 µS) idle was detected.

There were several problems with timing that were corrected by adjusting the timing of some of the elements. In particular, a 100 µS idle was introduced after each byte to allow the receiver to store or otherwise process the received byte. There were some other adjustments which I'll document with the protocol once it is more stable.

The first packet was decoded correctly. The second was garbled. The exact modality of the garbling was not immediately clear as the bit sequences did not appear to match with some offset. Probably there was not enough time between the break and the module select byte, throwing off the timing of that byte and all subsequent bytes. The "terminator" bit and idle bits were probably being interpreted as data bits and vice versa, masking the relationship between the intended data bits and the actual decoded bits.

Further analysis is probably not a good use of time, as in some ways this test is not a fair characterization of what would occur in the end product. The fact that the first packet was received correctly indicates that the thing should work in principle. I therefore propose to frame a test that will more closely match the real-world situation as it should occur in the end product.

XPS Receiver

I also looked at the output of the XPS receiver on the oscilloscope. At the first look my heart sank. All the pulses occur at once! So I was resigning myself to having one controller (or at least one timing circuit) per channel.

But then I started to look more closely. The channels don't in fact all start at once. The times each of them start are offset by a small amount. In fact, the amount is large enough to be resolved by a sufficiently short interrupt routine. However, what I was really interested in was when the pulses end. Since each pulse can vary in width by a large factor (larger than the start offset), then even with the staggered start time, it would be possible for two pulses to end at the same time, or near enough that even a very short interrupt routie would not be able to resolve the difference.

So I hooked up two channels through a couple of resistors and adjusted the sticks until the two channels ended at the same time. Yes, it turns out they can end at the same time. But adjusting them a small amount yields a surprise. The start times change, so that the pulses end at the same time, within a small range. Then, after moving a bit further, the end times suddenly jump so they end at some discreet interval apart (approximately 60 µS). After moving still further (with, again, the start times moving slowly relative to each other and the end times a fixed interval apart), it suddenly jumps again so then end times are twice that interval(approx. 120 µS). So it appears that the end times are quantized in approximately 60 µS steps. Any two pulses either end at exactly the same time, or they end a discrete multiple of 60 µS apart.

Very clever! And also good news for me. It means that, as long as I can make the interrupt routine less than 60 µS long, I should be able to resolve each pulse width with just one controller. The (slightly) bad news is that I don't think I can just combine all the channels with diodes and feed them in on one controller pin as I could have done with a 72 MHz receiver. I will need one pin per channel. However, I believe I will only need four channels, and even my little 8-pin controllers have six I/O pins, so I should be fine. (I will of course need one I/O pin for the bus!)

As an aside, the algorithm that the receiver appears work like this. For each channel, choose a tentative start time to be 60 µS after the previous channel (for the first channel, start at time "zero"). Calculate the end time (by the channel's value). Now move the end time ahead until it is exactly on a 60 µS boundary, adjusting the start time accordingly.

Of course this may not be exactly how it works. The scope is triggered by one of the channels and thus may be delayed/advanced from frame to frame in ways I am not aware of and may just make it appear that the end times are quantized, when in fact something else may be going on. Anyway, it's a really clever way of getting around the resolution problem, which would of course be the same kind of problem when producing the pulses with a single controller as when reading them.

At any rate, it appears that I can time the pulses with one controller, if I use one pin per channel. I will have to keep the interrupt routine very short to make sure it is over within the 60 µS. I can set it so that an interrupt is generated when any of the channel pins change state. I will have a two-byte timer running at the clock speed (1 MHz). The interrupt routine would just read the state of all the input pins (channels) and read the timer and store these two pieces of data in memory for later analysis. Figuring out which channel changed and calculating the channel times would then be done later, once all the pulses were done. Resolution will be 1 µS (much better than your standard analog servo which has an approx. 8 µS deadband).

Anyway, it will be interesting to try and write the code to do this. The question marks I see will be 1) if I can keep the interrupt routine short enough, and 2) if there will be enough memory. For four channels, there will be eight (maximum) events that the interrupt routine will have to store (the start and end of each pulse). Each event will have associated with it the state of all the channels (one byte) and the timer state (two bytes), for 8 x 3 = 24 bytes. There are only 32 bytes of RAM available, so I hope the rest of it can be done with only 8 more bytes!


September 27, 2009

Just a quick note to say, I have successfully completed test #2.

Second inter-module communication test

As with the first test, this was simply a demonstration that the transmitting module could send data reliably to the receiver module. The transmitter was programmed to send hundreds of "bogus" packets, intersperced with two test packets that the receiver was to receive and store. The module select byte is what distinguished the good packets from the bogus ones.

Results

Anazingly, there was only one glitch, which was just a firmware bug not caught during simulation testing. Once corrected, the test worked flawlessly. The two packets were received and stored in EEPROM correctly (as noted above, they had to be stored in a RAM buffer temporarily, since the EEPROM writing is far too slow to keep up with the transmission rate).

This demonstrated that a one-wire bus is quite feasible, and I believe will have sufficient bandwidth for the purpose. It is quite probable that I can reduce the timing of some of the pulses and still maintain reliability. For instance, I currently have a "0" bit at 20 µS, which seems to be the practical mininum, but a "1" bit at 50 µS. I could probably reduce this to 40 or even 30 µS. Other timings could probably be reduced accordingly.

I realize this is hardly earth-shattering, but for me it is the first time I have attempted to get these controllers to talk to each other, and it is gratifying that it seems to be fairly straightforward, and reliable. It also shows that the "break" serves as a good way to synchronize and to indicate the start of a new packet. This means that the receiver, which may well be doing other processing, can pretty much come in anywhere in the sequence and pick up the required packet.


January 31, 2010

Yikes, it's been a long time!

I have been concentrating lately on getting the receiver decoder designed. In the entry on September 7th, I described what I thought was the algorithm used to time the pulses coming from the XPS receiver, or at least describe them. Further testing has shown that I was close, but not exactly right.

In an attempt to actually characterize the pulses and design the PIC firmware to decode them, I discovered something a bit unsettling. That is, the start time for the pulses can start very close together, as little as 17 µS apart. This means that I would not be able to resolve this with the shortest interrupt routine I could write, which requires about 50 or so µS to complete. This was bad news, and, I thought, meant that I would need a separate PIC for each channel once again.

However, during further investigation I found I could not get two subsequent intervals between channels to both be 17 µS. Reducing the interval between one set of channels seemed to push the prior and subsequent intervals out to considerably more than that. I eventually figured out what I now believe to be the correct interpretation of the timings.

XPS timing diagram

XPS timing diagram

The above diagram will hopefully describe what I now believe to be the timing mechanism used in the XPS receiver. Note all timings are approximate. The four thick blue lines represent four channels being output from the receiver. We'll call them 1 through 4, from top to bottom. These lines are just examples of what might happen with particular locations of the sticks on the transmitter controlling these channels and are just for illustration.

Let's start to the right, when the pulses end. As I described before, the end times are quantized. All pulses ends on particular 60 µS boundary, represented by the dashed vertical lines. You can also see from this example that it's possible for the channels to end out of order, for instance, channel 3 ends before any of the other channels. You can also see that it is possible that more than one channel can end at exactly the same time (channels 2 and 4 in the example).

Now let's go back to the beginning of the pulses. (Note that the diagram is not to scale here!) This is where I was a little bit off in my analysis before. It seems like each channel has a 60 µS "window" in which it can start. The end time is quantized on a 60 µS boundary and the start time is adjusted so it starts some time within this 60 µS window, so that the entire pulse width is of the required length.

What is interesting is that each subsequent channels seems to have its own 60 µS window and these do not overlap. There is a 17 µS gap between the end of the window on one channel and the start of the window on the next channel. In the worst-case scenario (from the point of view of decoding it), if one channel starts at the very end of its window and the next channel starts at the very start of its window, there is only a 17 µS gap between the starts of the two pulses. Channels 2 and 3 in the above example illustrate this.

That's the bad news. It means that I can't use one controller to resolve two adjascent channels. However, as it should be clear, if two channels do start within 17 µS of each other, then obviously the second pulse started at the very beginning of its window, and the pulse in the next channel cannot start for at least another 60 µS. That bit of news tells me that I do not need one controller per channel; I can get away with two controllers, one to handle odd-numbered channels and one to handle even channels. That way, there must be at least 60+17+17=94 µS between the starts of any two pulses on a given controller. That is plenty of time!

I originally thought I would be decoding 4 channels with one controller. Since it is apparant now that I need two controllers, it becomes possible to decode 8 channels. Coincidentally, the XPS receiver is 8 channels. I don't believe I will need all those channels, but I don't see any point in limiting myself if it is easy to process all eight. You never know when you might want more in the future.

Receiver decoder design

With that, I think I have enough information to proceed with the receiver decoder module's design. I think the module will actually, conceptually, be two modules, the receiver decoder and the bus controller. The receiver module will be two PICs (processing odd and even channels) and the bus controller will be one PIC for a total of three. They will all be on the same board, as the bus controller will have to wait for the receiver decoder to finish before starting the frame. There will be a wire between each of the receiver decoder controllers and the bus controller.

From there, perhaps the next step might be to implement a servo module, which will pick up one of the channels from the bus and convert the value back into a servo pulse of the appropriate length. I can program up several of these and hook up servos or even an ESC, and I should see the entire thing work as if the servos were plugged into the receiver directly. Look ma, only one wire!