Beat's .NET Quadrocopter

Off and on there have been discussions on this and other forums about how real-time capable the .NET Micro Framework is. As a prime example: could and should a quadrocopter be programmed purely in C#? I have seen mostly two positions:

  • NETMF is not designed to be real-time. If you want real-time guarantees, create a special firmware version with C code for the control loop, or load the C code at runtime using non-standard extensions to NETMF, or don’t use NETMF at all. One glaring problem regarding real-time is the garbage collector. It blocks for an indeterminate time, and this destroys all real-time quarantees.

  • With a fast enough processor, NETMF should be able to handle such real-time tasks.

We asked ourselves the same question. It was clear to us that in general we would not [em]recommend [/em]doing real-time programming in NETMF, but would it really be that much beyond its capabilities? After all, it is a small and highly controlled environment, and real-time tasks are often few and simple in a real-world system. In NETMF, there are no operating system services that are scheduled at unknown times. We have written all the device drivers of [em]NETMF for STM32 [/em]ourselves, so we know where interrupts may occur and might introduce non-deterministic timings. (Speed is irrelevant in the definition of real-time, it only matters whether the timing is fully predictable.)

But how about the garbage collector? We knew for certain that a GC is not necessarily a problem. Fifteen years ago we have designed and implemented a bootable hard real-time Java runtime - with a garbage collector - that did not interfere with real-time tasks (not even with periodic tasks executing at well above 1 kHz, on rather slow microcontrollers). The key insight was that no one in his right mind dynamically allocates objects in a real-time task (at least not after its initialization phase). However, the often more numerous [em]non [/em]real-time threads (e.g., for communication purposes) should be allowed to allocate memory, and memory should be garbage-collected when necessary. The challenge was to implement the GC in such a way that it is interruptible anytime, i.e., it must never hold a global lock or something like that for more than a few processor cycles. While this was difficult to implement, it was still feasible. As a result, the real-time tasks (our own API, separate from the normal Java threads) always had absolute priority over all other code - including the GC. Their execution thus was fully deterministic.

NETMF doesn’t have such an intricate GC, nor does it have an API for real-time tasks and a suitable scheduler. But if a simple program avoids all allocations, there is no reason for it to become non-deterministic, as the GC will simply never run.

Beat thought that the proof of the pudding is in the eating, so rather than throwing around opinions, he built a proof. He designed a custom board for a quadrocopter, with an STM32F1 at 72 MHz plus a Bluetooth module. No separate microcontroller for the real-time stuff! The firmware was our standard F1 edition of [em]NETMF for STM32[/em]. No special C code linked in, no runtime loadable modules, no cheats. The control loop runs at 200 Hz, which is sufficient for stabilizing the flight of the quadrocopter.

The hardware has been ready for quite a while, see e.g.

Imgur

Tuning the control loop parameters had to wait until recently, but by now the quadrocopter is flying quite well:

So what’s the moral of the story? NETMF is rather deterministic if you are careful with your code. In some cases, it can thus be feasible, and possibly even reasonable, to implement simple real-time chores in C#. It should not, however, be mistaken for a full-fledged real-time operating system. But it is good to know that it can be stretched quite a bit beyond its original design goals.

Cuno (but the work was all done by Beat!)

PS
In another thread, Justin challenged me to show and tell about this project - thanks for the trigger :slight_smile:

15 Likes

Wicked :slight_smile:

No cut fingers :wink: Good!

i hope your’e not careful with your code…and shares it

fantastic work

1 Like

Thanks Cuno
Could you share the real time part code for exact timing?
I need exact timing for sampling the sensor (without using RLP or native C)

Great job! I’m with the others, I’d love to see your code. Any chance you’ll be selling that little quad as a kit?

What controller are you using? Is that custom also or an off the shelf BT controller?

Very cool. I always fancied these quadrocopter things. I hope we will see a kit for something like this at some stage. It is the type of cool thing that will attract many newcomers to Gadgeteer,

Nice!
Is the frame 3D printed?

@ dominik38 - The PCB is the frame.

Edit - i tell lies…

What would you call the blue arms that the motors are connected to?

Very nice … I too would be interested in the code.

Where are the ESCs hiding? Are they apart of the board? Underneath it?

Very cool,

is the quad airframe custom built or off the shelf?
(yes, I’m keen to get one going too :slight_smile: )

@ dominik38 - No, the frame was hand cut. But 3D printing would be cool.

@ Cuno - Is Beat using a MPU-6000 or MPU-6050 - ie SPI or I2C?

@ ianlee74 - The Bluetooth module is an off-the-shelf module from Texas Instruments (LMX9838):
Imgur
http://www.mouser.com/ds/2/282/snosaz9c-122649.pdf

The microcontroller is an STMicroelectronics STM32F103RET (Cortex-M3 at 72 MHz, 512 KB Flash, 64 KB RAM). This seems to be about the smallest practical RAM size for NETMF plus application, btw.
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00191185.pdf

The accelerometer is an ADLX345:
https://www.sparkfun.com/tutorials/240

The gyro is an ITG3200:
https://www.google.ch/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=1&cad=rja&ved=0CCwQFjAA&url=https%3A%2F%2Fwww.sparkfun.com%2Fdatasheets%2FSensors%2FGyro%2FPS-ITG-3200-00-01.4.pdf&ei=p3DeUdTmGMPsPLS-gJgG&usg=AFQjCNG6DaPyXZ_ptxva-HzDMOFeDF7SFg&sig2=gH_HDqr77E8je4yT4nU2qg&bvm=bv.48705608,d.ZWU

@ Cuno - Thanks for the info.

@ VB-Daniel - Beat will share the code, but this will be after the summer break.

2 Likes

@ Tzu Hsuan - The program consists of two threads. One for receiving commands via Bluetooth, the main thread for the rest. The main thread has a loop that polls the ready signal from one of the sensors, which is configured to produce new measurements every 50 millisecond. The ready signal is a digital input. Not an interrupt input, as this would be too slow (it would create a new thread every time). Instead, simple busy waiting is used.

More details from Beat, after the summer break :slight_smile:

@ ianlee74 - Ah, we’re really a software company, with hardware design as an occasional diversion. But we are not comfortable (nor efficient) with the logistics of producing, selling and shipping stuff in volume.

That’s where GHI could fill a gap quite nicely… (hint, hint) :wink: