Linux Kernel Module for the TSIC 306

I’ve made my first foray into the kernel, by writing a kernel module for the TSIC 306 temperature sensor. After overcoming the difficulties in setting up the tools, the actual driver development was much easier than expected. The source code is up on Google Code and is basically working, but needs a little more development.

This maps the sensor to the file-system, so you can load the module and read the temperature like this:

$ sudo insmod tsic.ko
$ cat /sys/kernel/tsic/temp

In the example above, the temperature is 14.68°C and all the values are scaled by 1000 to avoid floating point maths in the module, and to match the behaviour of existing sensors such as:

$ cat /sys/class/thermal/thermal_zone0/temp 

Writing the module turned out to be easier than expected, and there are some great libraries such as gpiolib and kobject which simplify development. Documentation is a bit scarce, but there are some useful resources:

Eventually I plan to add support for multiple sensors on configurable GPIO pins,  make it more robust and clean up a few issues such as the lack of time-outs in the I/O.

Building Kernel Modules on the Raspberry Pi is Ridiculously Hard!

I don’t think I’m alone on this issue… it seems almost impossible to build a working kernel driver on the Pi. After much trial and error, and on the verge of giving up completely, I finally succeeded!

I started with cross compilation on Ubuntu but couldn’t get it to work initially, it kept giving “Invalid module format”. Compiling directly on the Pi, again I was only able to obtain “Invalid module format” errors and, finally, a module that loaded but crashed the OS. The .config and Module.symvers seem correct, but it just would not build a working module. It makes me suspect some compiler toolchain difference between the kernel and the tools used to build the module.

Finally, cross compilation worked. Here is the magical recipe which  worked for me under Ubuntu, cross compiling for 3.10.33+ (mostly in case I need it again myself). First, set up the environment variables and download tools as described here.

git clone --depth 1 git://
cd linux
cp your/raspi/config .config
ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig
ARCH=arm CROSS_COMPILE=${CCPREFIX} make menuconfig
# Save.. Exit..
ARCH=arm CROSS_COMPILE=${CCPREFIX} make modules_prepare
# Note: can specify -j9 for 8 core compile..

Well, now that it finally works, I’m not updating the Pi again until I’ve finished my driver 😉

Incidentally, here’s an easy way to find Module.symvers:

Temperature Sensor Upgrade: the TSIC 306

I’ve been using the DS18B20 for a while now, but wanted something with a higher temperature range and faster update rate, but with a similar digital interface. After a lot of searching, it became clear that there are very, very few parts that fit these requirements…

Finally, I found a neat sensor called the TSIC 306. This has a temperature range of -50 °C to +150 °C and the update rate is a very respectable 10Hz. Better still, it’s available in a 3-wire TO92 package, similar to the DS18B20. It has one small disadvantage: it looks as if you can only have one device on the bus, so each sensor will need a dedicated GPIO pin. That said, it still looks ideal to upgrade the sensors in my coffee machine, so here goes!

The hardware interface to the Pi is very straightforward: it can accept 3V3 power, and the data line is actively driven low/high, so it can be wired directly to a GPIO line with no pull up resistor. However, it’s worth noting that the data suggests that 5V supply yields better measurement accuracy, so it may be preferable to power from 5V and use two resistors as a potential divider to reduce the data output to 3V3 logic levels for the Pi.

To date I have managed to read the sensor from C++ on the Pi, but it’s a little unreliable as it’s difficult to get accurate timing from user mode. It looks like a Kernel Driver may be needed…

Replacing the Gaggia Classic Thermostat with a DS18B20

For my Espiresso Machine, I needed to replace the stock thermostat on the Gaggia Classic with a DS18B20 (Digital Thermometer). My first attempt was pretty basic, and consisted of smearing the DS18B20 with thermal paste and using a cable tie to tether it the side of the boiler (just beneath the steam thermostat). This actually worked well in practice, but I wanted to come up with a better mounting technique.

Someone on the Gaggia Users Group forum suggested modifying this Circuit Board Standoff, which would have been perfect but unfortunately all the UK stock seem to be 7mm AF instead of 10mm AF, which wouldn’t be large enough to drill out.

Instead, I decided to make a mounting block for the sensor. I used some 10x10mm square section Aluminium bar stock, cut it down to 25mm length, drilled and countersunk a 4.5mm hole through the bar at 5mm from one end. This is designed to mount on the side of the boiler in place of the existing coffee thermostat, using an M4x0.7mm brass screw. There’s another perpendicular 6mm hole along the length of the bar, to accomodate the DS18B20 sensor (this is the waterproof version, which is encapsulated in a stainless steel tube).

The picture below shows the original thermostat (left), and the new mounting block, M4 brass screw and encapsulated DS18B20:

ds18b20_mount_vs_tstatThe 6mm hole intersects the 4.5mm hole, so that it can be filled with thermally conductive paste to ensure a good contact with the temperature sensor. The picture below shows the sensor and brass screw inserted into the block. The screw has been cut down to leave about 6mm of thread exposed, to match the existing thermostat.


The final picture shows the sensor block mounted on the side of the boiler in place of the existing coffee thermostat (taking care not to over-tighten).


It was a challenge to tighten the screw in situ! Ideally I would have preferred an aluminium socket cap screw, but decided to use the materials to hand, rather than wait on another delivery 😉

Renault Modus Side Light Replacement

Now the Renault Modus isn’t a bad little car really, but it has at least one appalling design flaw: changing any of the front bulbs generally involves removing the whole front of the car!

Anyway, I recently had to change one of the sidelights, and read online that it’s possible to do this by removing  part of the front grille. I couldn’t find any pictures, so I decided to take some photos as I did the job in the hope it might help someone else in the same position!

To start with, here’s a picture of the side light from the front. The bulb (circled below) is a 501 (W5W) which is 12V and 5W.

Modus Sidelight Photo

When you lift the bonnet, there’s a rubber seal along the front edge. This is clipped into place at both ends with a plastic clip, and can be gently popped out as shown below, to reveal a plastic tab (centre of photo below):

Modus Sidelight Step 1

If you lift (and jiggle) this tab, you can pull out a long plastic shaft as shown below. Once removed, this releases the front grille.

Modus Sidelight Step 2

Having completely removed this, the grille can be popped out of the front panel as shown below with the plastic locking shaft. This needs care, to avoid breaking the tabs. Before removal I also popped out the four round plastic clips to free the top edge of the front panel so that I could see the rear of the grill, and this gives a bit more flexibility, but probably isn’t essential. To remove the grille, I pulled the lower edge of the grill forward and up (pivoting around the upper clips).

Modus Sidelight Step 3a

After you have removed the panel (hopefully without breaking any of the retaining tabs…) you will be left with a hole like this:

Modus Sidelight Step 3b

If you look inside here, you can see a rotary cover for the side light. Unscrew this and it will reveal a black plastic cylinder. This simply pulls out and you will find the bulb pushed in the end.

Modus Sidelight Step 4

Pull the bulb out of the holder and replace. Remember to refit the cover and test all the bulbs before reassembly.

This is quite a quick job and is much, much simpler than replacing the headlights, but that’s a story for another day!