1

as a student project, we're building a robot which should run through a defined course and pick up a wooden cube. The core of it is a single-board computer running debian with an ARM9 at 250MHz. So there is more than enough processing power for the controller. Additionally, it does some image processing (not when driving, only when it stops), that's why we don't use a simple microcontroller without an OS.

The whole thing works quite well at the moment, but there is one problem: The main controlling loop executes without any delays and achieves cycle frequencies of over 1kHz. This is more than enough, 100Hz would suffice as well. But every when and then, there is a single cycle which takes 100ms and more, which may greatly disturb the controller.

I suspect that there are some other tasks which cause this delay, since the scheduler may detect that they haven't got any CPU time for an extended period of time.

So what I'd like most is the following: A short sleep of maybe 5ms in the controller's mainloop which does really only take 5ms but gives some processor time to the rest of the system. I can include a delay of e.g. 500us using nanosleep, but this always takes more than 10ms to execute, so it is not really an alternative. I'd prefer something like a voluntary sleep to give waiting tasks the opportunity to do something, but returns as quickly as possible.

The system is unloaded otherwise, so there is nothing which could really need a lot of processing for a long time.

Is there any way to do this in userspace, i.e. without having to stick to things like RTAI?

Thanks, Philipp

Filburt
  • 17,626
  • 12
  • 64
  • 115
Philipp Burch
  • 869
  • 1
  • 7
  • 16

4 Answers4

0

I suggest that you stick to real time interfaces when doing motor control; I've seen a 1000 kg truck slam into a wall during a demo due to that the OS decided to think about something else for once... :-)

If you want to stay away from RTAI (but you shouldn't); a (perhaps) quick fix is to slap an Arduino board for the actual driving, and keep the linux board for high level processing.

To fix the "wall problem" implement a watchdog in the driver board, that stops the thing if no command have arrived for a while...

KarlP
  • 5,149
  • 2
  • 28
  • 41
  • Well, it's not that critical, our robot only weights approx. 2kg and can't do much damage. Anyway, I know that a realtime OS would be the correct solution, but I try to stay away from that because this would most likely require to change the whole software architecture. It's not that it would not work at all, but it's not exactly ideal. Oh, and for the watchdog, this is implemented already. – Philipp Burch Jun 03 '12 at 16:13
0

A real-time problem needs a real-time OS.

Because a real-time OS is predictable. You can set task priorities such that the ones that need to produce results at specified times don't get preempted by tasks that need processing power but are not time constrained.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
0

Ok, I've found a solution which makes it better, altough not perfect. There is another thread which explains the sched_setscheduler() function. My init code now looks like this:

// Lock memory to reduce probability of high latency due to swapping
int rtres = mlockall(MCL_CURRENT | MCL_FUTURE);
if (rtres) {
  cerr << "WARNING: mlockall() failed: " << rtres << endl;
}

// Set real-time scheduler policy to get more time deterministic behaviour
struct sched_param rtparams;
rtparams.sched_priority = sched_get_priority_max(SCHED_FIFO);
rtres = sched_setscheduler(0, SCHED_FIFO, &rtparams);
if (rtres) {
  cerr << "WARNING: sched_setscheduler() failed: " << rtres << endl;
}

Additionally, I've removed the short sleeps from the mainloop. The process now eats all available processing power and is (obviously) unresponsive to any actions from the outside world (such as console keystrokes and such), but this is OK for the task at hand. The mainloop stats show that most iterations take less than a millisecond to complete, but there are still a few (every 1000th or so) which need approx. 100ms. This is still not good, but at least there are no more delays which are even longer.

Since it is "only" a student project, we can live with that and note it as a candidate for futher improvement.

Anyway, thanks for the suggestions. For next time, I'd know better how to cope with realtime requirements and take an RT OS from the beginning.

Regards, Philipp

Community
  • 1
  • 1
Philipp Burch
  • 869
  • 1
  • 7
  • 16
0

We are running 100 Hz loops on an ARM7 board at work, using a standard Linux with the RT patch, which allows (almost) all locks in the kernel to be preempted. Combining this with a high-priority thread gives us the necessary performance in both kernel and user space.

As the only thing you need to do is to apply the patch and configure the kernel to use full preemption, it's pretty easy to use also - no need to change anything in the software architecture, although I'm not familiar enough with Debian to say whether the patch will apply cleanly.

sonicwave
  • 5,952
  • 2
  • 33
  • 49
  • Ok, this sounds interesting. Suppose I finally really have to recompile the kernel (tried to avoid this before). How did you realize the 100Hz interval? Using some sort of sleeping or a timer or something else? Thanks, Philipp – Philipp Burch Jun 03 '12 at 18:31
  • We are using kernel device drivers to talk to our custom hardware - and using the built-in hardware timer of the ARM processor to generate the interval. This is implemented in a separate driver module where any other driver that needs to can register. I take it that in your case, you can just as well squash everything together in a single module though. Using `hrtimers` is also a possibility, although I only have experience with these on an x86 platform. – sonicwave Jun 03 '12 at 20:03
  • Ok, I've run some tests with the RT patch. Compilation works more or less seamlessly, but after booting I no longer have my USB devices. I suppose that the kernel config is not the same as in the originally supplied image. Anyway, I'll need to run more tests on this to see if it really helps. Would be nice, altough the controller performs quite good now even with the latencies. Oh and for the kernel driver: This would be a clean solution of course, but it has the same problem of needing a lot of changes to the code for which we don't really have the time. Thanks, Philipp – Philipp Burch Jun 09 '12 at 16:20