[[!img rpi_dc_motor_control-scn.png size="300x" align=right alt="Simulink connected to RPi running motor control model"]] Raspberry Pi is low cost hardware which does not implement any usual motor control peripherals in hardware. Yet fully preemptive variant of Linux kernel latencies are so low that fast signals processing in software allows to implement precise DC motor feedback control for incremental encoder inputs changing up to 15 kHz.

Background

The goal was to prove that working control can be achieved with Embedded Realtime Linux Target for Simulink (ert_linux) on this low cost hardware which provides option for broader community to play with this control task taught during the real-time operating systems programming course at our university. The final task assignment targets industrial like PowerPC MPC5200-based board running VxWorks system. But Raspberry Pi (RPi) is much cheaper and common in broad community. The initial idea has been implemented in a frame of Radek Mečiar's bachelor thesis with controller and monitor web server implemented directly in C-language. The experiment has been improved and combined with ert_linux project to allow teach controller design with Simulink.

[[!img rpi-mc-wwrap-schema.png size="300x" align=right alt="Diagram of Interconnection of RPi and DC Motor"]]

Hardware

Since the RPi (and its BCM2835 SoC) is not intended for motion control applications, there is no hardware support for incremental encoder inputs (IRC) and the RPi connector has only one pulse width modulation (PWM) output. That is why most of signal and control processing is done in software with minimal HW support. In order to be able to rotate the motor in both directions, the only available PWM signal is demultiplex to two sides of power H-bridge by using four NOR gates (SN74HCT02) where direction is controlled by an additional GPIO output (DIR). The incremental encoder signals are connected directly to the RPi and processed only in software. The diagram of wire-wrapped interconnection is available in PDF and SVG formats as well.

IRC processing

The IRC signal processing is the most demanding part of our solution since the frequency of the IRC signal can go up to 21 kHz, when maximal voltage is applied to the motor. To achieve reasonable performance, a kernel driver has been implemented for this purpose. It uses four GPIO pins — two for each IRC channel. One of these two pins is configured to generate interrupts for rising edges and the other for falling edges. Motor position is derived from the order of interrupts and applications can read it via /dev/irc0.

This solution has an interesting property that it works even when the processing of one (or few more) interrupt(s) is delayed due to other activities in the system. In preempt_rt, the interrupt handlers run in dedicated threads, which can be preempted by threads with higher priority. Thanks to the fact that the scheduler run queue is a FIFO queue, the IRQ threads are activated in the same order as the original interrupts and our position calculation works even in the case of a delay. The alternative approach, where the position is calculated from the actual IRC signal levels read in the interrupt handler would fail, because the level read in a delayed handler might be different from the level at the time when the corresponding IRQ was generated.

Even better performance could be probably achieved by processing the IRC signals in ARM's fast interrupt requests (FIQ), but this solutions would not be portable to other architectures. Other option is to design more sophisticated hardware but minimal HW solution is excellent for teaching.

Simulink model

Simulink model of the motor controller is depicted in Figure. The IRC0 and PWMwDir blocks are so called C MEX S-functions. The former reads the motor position from /dev/irc0, the latter controls the PWM and DIR signals by directly accessing the GPIO registers via mmap()ed /dev/mem. The actual motor control is performed by a proportional-sum-derivative (PSD) controller enhanced with an anti-windup technique. Setpoint w is generated either manually or by a simple trajectory generator. Sampling period of the whole model was set to 1 ms. The source code of the S-functions as well as the model are available from Github repository.

The ert_linux target was configured to use an ARM C cross-compiler. The generated binary was copied to the target RPi board by the scp command and ran there. Simulink external mode was used to tune certain model parameters on-line as well as to see the actual signal values in the scope windows.

Performance evaluation

The Linux kernel used for our experiments was the official Raspberry Pi rpi-3.12.y Linux kernel version 3.12.28 patched with Steven Rostedt's stable preempt_rt patch (patch-3.12.26-rt40) and with Junjiro R. Okajima's aufs3.12.x 20140512. The latencies measured by the cyclictest tool when the system was loaded by TCP communication and SD card accesses are as follows. The maximal latency was 170 μs, average about 40 μs. When graphical desktop was run the maximal latencies increased to 280 μs (probably caused by contention on the system bus generated by the VideoCore GPU). This observation is in same range as more serious examination and long term performance monitoring on better tuned RT-kernel kernel executed by Open Source Automation Development Lab and documented in their Quality assurance Farm.

System load caused by running an unoptimized (soft-float only) model was about 2%. The USB connected Ethernet controller (a part of RPi) generated load of about 10%. The highest load was generated by the software IRC signal processing — up to 95%, i.e. the limit for RT tasks. This happened during fast motor rotation (e.g. when maximal input voltage was applied) and the interrupt frequency was 8 kHz per each channel (32 kHz in total). As can be seen, processing of the IRC signal at full speed (21 kHz) is above capabilities of the Linux kernel on this hardware. As mentioned above, the use of FIQ (or raw interrupts) could help here. For lower speeds, our simple solution works flawlessly and can be used as a great tool for control education and experiments.

Bachelor thesis of Radek Mečiar: Motor control with Raspberry Pi board and Linux (Czech language only), 2014
Available online in PDF format
Corresponding source code on GitHub https://github.com/Ramese/servoPi
Michal Sojka, Pavel Píša: Usable Simulink Embedded Coder Target for Linux at 16th Real Time Linux Workshop, 2014
Paper abstract at 16th Real Time Linux Workshop site.
RPi RT Control Support
https://github.com/ppisa/rpi-rt-control
GitHub Repository with RPi IRC kernel module and Simulink model and RPi blocks sources.
Fully preemptive kernel sources for RPi (kernel-3.12.28-rt40+)
https://github.com/ppisa/linux-rpi
GitHub repository with branch rpi-3.12.y-aufs-rt-ppisa containing Linux kernel sources with Steven Rostedt's stable preempt_rt (patch-3.12.26-rt40) and with Junjiro R. Okajima's aufs3.12.x 20140512 patches applied.
Simulink Embedded Coder target for Linux
http://rtime.felk.cvut.cz/gitweb/ert_linux.git
Repository with core templates for Linux hosted, Linux cross architecture targetted Simulink code generation templates and configuration.
Auxiliary utilities for Raspberry Pi
https://github.com/ppisa/rpi-utils
The repository includes RAM based root overlay support to protect SDcard against wearing and tearing and keep root filesystem intact when experiments are download and run on system or even crash it.