Temperature PID control - Part Deux

Update: this version of the component may compile on 10.04LTS without errors/warnings: frequency2temperature.comp (thanks to jepler!)

There's been some interest in my 2-wire temperature PID control from 2010. It uses one parallel port pin for a PWM-heater, and another connected to a 555-timer for temperature measurement. I didn't document the circuits very well, but they should be simple to reproduce for someone with an electronics background.

Here's the HAL setup once again:

The idea is to count the 555 output-frequency with an encoder, compare this to a set-point value from the user, and use a pid component to drive a pwm-generator that drives the heater.

Now it might be nicer to set the temperature in degrees C instead of a frequency. I've hacked together a new component called frequency2temperature that can be inserted after the encoder. This obviously required the thermistor B-parameters as well as the 555-astable circuit component values as input (these are hard-coded constants in frequency2temperature.comp) . Like this:

I didn't have the actual circuits and extruder at hand when coding this. So instead I made a simulated extruder (sim_extruder) component and generated simulated 555-output. Like this:

This also requires a conversion in the reverse direction called temperature2frequency. A stepgen is then used to generate a pulse-train (simulating the 555-output).

  • The INI and HAL files for the simulated extruder, based on the default axis_mm config: simextruder
  • frequency2temperature component:  frequency2temperature.comp (install with: "comp --install frequency2temperature.comp")
  • temperature2frequency component: temperature2frequency.comp (only for simulated setup, not required if you have actual hardware)
  • sim_extruder component: sim_extruder.comp (only for simulated setup, not required if you have actual hardware)

"heartyGFX" has made some progress on this. He has a proper circuit diagram for the PWM-heater and 555-astable. His circuits look much nicer than mine!

The diagrams above were drawn with Inkscape in SVG format: temp_pid_control_svg_diagrams

Why Real-Time?

Why bother with these real-time kernels and APIs at all? Isn't timing on a modern PC good enough? Look at this:

This histogram shows latency-numbers from the same 1ms thread test run compiled without (red) and with (green) real-time enabled. All the green real-time data clusters around zero +/- 20us. Without real-time enabled the event we are expecting to happen every 1 ms might happen almost 1 ms too early, or up to 3 ms late. With real-time the timing is mostly consistent to better than 1% (10 us) with a worst-case jitter of 2% (20 us).

Latency Histogram

This shows a latency-histogram for a 1 ms thread running on Xenomai on my recently acquired ITX-board. Note how badly the histogram is approximated by a normal distribution (Gaussians look like parabolas with logarithmic y-scale!). See also Michael's recent RPi data and  Kent's Athlon/P4 data.

The usual latency-test numbers people report is the maximum latency, a measure of how far out to the left or right the most distant single data point lies. The histrogram can probably be used to extract many more numbers, but for real-time critical applications like cnc-machine control the maximum latency is probably an OK figure of merit.

The latency numbers are recorded with a simple HAL component:lhisto.comp

The instantaneous latency-number is then put in a FIFO by the real-time component sampler and written to a text-file using halsampler. I'm setting this up with the following HAL commands (put this in a file myfile.halrun and run with "halrun -f myfile.halrun")

loadrt threads name1=servo period1=1000000
loadrt sampler depth=1000 cfg=S
loadrt lhisto names=shisto
addf shisto servo
addf sampler.0 servo
net latency shisto.latency sampler.0.pin.0
start
loadusr halsampler -c 0  latencysamples.txt

The numbers can now be plotted with matplotlib. I'm using the following script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
# load data from file
x = np.loadtxt('latencysamples.txt' )
x=x/1e3 # convert to microseconds
 
fig = plt.figure()
ax = fig.add_subplot(111)
nbins = len(x)/1000
n, bins, patches = ax.hist(x, nbins,  facecolor='green', alpha=0.5, log=True)
bincenters = 0.5*(bins[1:]+bins[:-1]) # from matlplotlib example code
mu = np.mean(x)
sigma = np.std(x)
area = np.trapz(n,bincenters) # scale normpdf to have the same area as the dataset
y = area * mlab.normpdf( bincenters, mu, sigma)
l =  ax.plot(bincenters, y, 'r--', linewidth=1)# add a 'best fit' line for the normal PDF
 
ax.set_xlabel('Latency ( $ \mathrm{ \mu s } $ ) ')
ax.set_ylabel('Counts')
ax.set_title('Latency Histogram\n 12.04LTS + 3.2.21-xenomai+')
ax.set_ylim(1e-1, 10*max(n))
ax.grid(True)
plt.show()

LinuxCNC on Ubuntu 12.04LTS

Recent developments has made it possible to run LinuxCNC on the latest LTS release of Ubuntu. This is experimental work, so not recommended for controlling a real machine just yet. The main obstacle for moving LinuxCNC from 10.04LTS to a more recent distribution has been the RTAI real-time kernel, which has not been kept up-to-date with development of the normal Linux kernel. Fortunately there are alternatives such as Xenomai or RT_PREEMPT.

Here is a step-by-step description of the install/build process, if you want to experiment with this.

  1. Download and install a normal 32-bit 12.04LTS Ubuntu (ubuntu-12.04.1-desktop-i386.iso). Note that the 64-bit version is not supported for the steps that follow further down. I could not get Ubuntu's startup-disk-creator to work, so I used unetbootin to write the ISO-file to a USB-stick.
  2. It's possible to compile the xenomai-kernel from scratch, along with the runtime etc., but I used pre-compiled deb-packages by Michael Haberler from here: http://static.mah.priv.at/public/xenomai-debs/
  3. Install the xenomai kernel:
    sudo dpkg -i linux-headers-3.2.21-xenomai+_0.1_i386.deb
    sudo dpkg -i linux-image-3.2.21-xenomai+_0.1_i386.deb
  4. make sure it will show up as a GRUB-entry when booting:
    sudo update-initramfs -c -k 3.2.21-xenomai+
    sudo update-grub
  5. reboot. uname -r should now show: 3.2.21-xenomai+
  6. now install the xenomai runtime:
    sudo dpkg -i libxenomai1_2.6.1_i386.deb
    sudo dpkg -i libxenomai-dev_2.6.1_i386.deb
    sudo dpkg -i xenomai-runtime_2.6.1_i386.deb

This installs the xenomai system on top of which a recently available version of LinuxCNC can be built. There are probably many ways to now obtain the tools/dependencies that are required. I used the following:

  1. sudo apt-get install synaptic
    sudo apt-get install git
  2. Now using synaptic, install the following packages (I found these are required for a minimal linuxcnc build):
    build-essential
    autoconf
    libpth-dev
    libglib2.0-dev
    libgtk2.0-dev
    tcl-dev
    tk-dev
    bwidget
    libreadline-dev
    python-tk
    python-dev
    libgl1-mesa-dev
    libglu1-mesa-dev
    libxmu-dev
  3. Get Michael's version of LinuxCNC that can be compiled for Xenomai:
    git clone git://git.mah.priv.at/emc2-dev emc2-dev
    cd emc2-dev
    git branch --track rtos origin/rtos-integration-preview1
    git checkout rtos
  4. Configure and build for Xenomai:
    cd src
    ./configure --with-threads=xenomai-user --enable-run-in-place
    make
    sudo make setuid
  5. Test:
    . ./scripts/rip-environment
    latency-test

This new version of LinuxCNC can be built without a real-time kernel (previously called "simulator" or "sim") or with any of the real-time kernel alternatives: RTAI, Xenomai, RT_PREEMPT. It should be possible to compare real-time performance in the form of latency-numbers with different hardware and kernels.

40-pin breakout board

Making break-out boards is not exactly rocket science... Oh well, this one is required for a 10-channel temperature measurement which we do with pt100 sensors and a 4-wire multimeter. It's great however to have a working toolchain where you come up with an idea in the morning, spend a few hours designing the schematic and PCB, then go over to the PCB-mill and run the CAM-programs to produce the PCB, and assemble and test your circuit by the end of the day.

Raspberry Pi

Out of curiosity and with a couple of different projects in mind I have been playing with a Raspberry Pi (a cheap, small, but slow linux computer) lately. Some observations:

  • It's small, but it does require quite a few bulky connectors that connect to three different sides of the board. If you wanted to enclose the board and cables in a case the connectors add a significant amount to the footprint.
  • Who came up with the idea of offsetting the two USB-connectors so they extend out of the board? This makes all the cases for the Pi have a funny shape to get the Ethernet and USB connectors flush with the side of the case.
  • It seems to run the raspbian distribution OK. But for a standard debian-desktop it's very slow. There are optimized lightweight X-environments that are supposedly faster and more responsive.
  • Since it's an ARM processor, not every package I am used to using on Ubuntu/Debian is available from the repositories.
  • The modern way to interact with a gadget nowadays is a touchscreen. But there doesn't seem to be any good consensus on what touchscreen to use with the Pi. Could we have something budget-priced with good existing drivers for both screen and touch please. Perhaps use the DSI-connector so the gadget screen won't tie up other resources (USB, HDMI, SPI, or GPIO).

Overall this means my ideas for various real-time instruments & gadgets may be better served by an Atom ITX-sized motherboard. The atom is a standard x86 architecture that runs everything a desktop or laptop will run. It's fast enough to run modern desktop environments. And it has a PCI or PCIE slot for e.g. a Mesa FPGA card. Given the cost of enclosures, (touch)screens, FPGAs, and the analog electronics I have in mind, it really will not matter much if the cost of the motherboard+cpu combo is 40 euros (Pi) or 140 euros (Atom). Someone suggested I'd have a look at BeagleBoard or BeagleBone, but right now I'm leaning towards the Atom.

Espoorastit

This is the last orienteering event for this year.

On #5 I somehow started looking for the control too early on the wrong hill. Probably lost 10 min here. Then from #7 I went back to a road and tried to find #8 from there when in hindsight it would have been much better to head for the fence around the radio-mast and use that to find #8. Probably another 4 min or so lost. Between #9-#10 my route is too safe and a more direct route through the wet or frozen field would have been faster.

Dobson-mount progress

About 2 hours more work on the triangular base for the telescope dobson-mount.


Here I have added one more profile in the middle of the triangle which holds an 11mm diameter steel pin, around which the upper platform will rotate. Roughly 30mm high acetal plastic cylinders at the midpoints of the triangle-sides support the upper platform and will hopefully provide the right amount of friction. Too much and it will be hard to move the telescope, too little and it won't stay aimed at a particular target.


This is the upper platform, a piece of oak-board. The steel pin fits in a brass-fitting which is bolted to the center of the board.


This is how the two pieces fit together (upside down). The oak-board will rotate around the steel pin while resting on the three acetal posts.

To be continued...

Espoorastit, Uusmäki

Not a good start as I ran too much east when looking for #1.
Then mostly OK until#7 where I climbed to the top of the hill and had to return half-way down to find the control.
From #10 to #11 the idea was to go directly in the direction of #11, but the execution of that didn't go too well and I ended up walking a while here until I found the control.
5.7km course in 64 minutes.