Few days ago, I noticed odd problem with koha-common package. It depends on mysql-client which on squeeze tries to install version 5.1 which conflicts with my installation which uses Percona MySQL build. How can we fix this?

As it turns out, it rather easy. I will just create fake package which will provide mysql-client and in turn depend on percona-server-client using something like:

koha-dev:/srv# cat mysql-client-fake/DEBIAN/control 
Package: mysql-client-fake
Version: 0.0.1
Section: database
Priority: optional
Architecture: all
Depends: percona-server-client
Provides: mysql-client
Suggests:
Conflicts:
Maintainer: Dobrica Pavlinusic <dpavlin@rot13.org>
Description: Provides mysql-client for percona build
koha-dev:/srv# dpkg-deb -b mysql-client-fake .
dpkg-deb: building package `mysql-client-fake' in `./mysql-client-fake_0.0.1_all.deb'.
koha-dev:/srv# dpkg -i mysql-client-fake_0.0.1_all.deb 
(Reading database ... 59348 files and directories currently installed.)
Preparing to replace mysql-client-fake 0.0.1 (using mysql-client-fake_0.0.1_all.deb) ...
Unpacking replacement mysql-client-fake ...
Setting up mysql-client-fake (0.0.1) ...
Quick and easy. Before you start bashing Debian for this, have in mind that both Koha and Percona MySQL builds are not official Debian packages, so it's not really Debian developers problem.

Update: This problem occurs because Debian developers decided to use virtual-mysql-server and virtual-mysql-client Provides so Percona changed it's provides to virtual-mysql-server but Koha package requires older mysql-client.

Finally I decided to upgrade my wireless network to 802.11n, and to do so I picked up cheap TP-Link TL-WR740N and decided to install OpenVPN, n2n and munin node on it. This is where the problems started because simple opkg install openvpn filled up whole file-system. Instead of declaring fail on this front, I decided to ask a friend how to make this work...

Reason for this upgrade was change in my router provided by ADSL provider. I didn't have any administration privileges on it, and it was only 802.11g device, so my previous configuration with igel which provided pppoe wasn't possible any more (since I can't turn ADSL router into bridge mode). So I decided to scrap igel and move openvpn and n2n to TP-Link instead (which will also help with head dissipation on my closet which hosts all those devices).

Since router has just 4MiB of flash storage, installing large packages is not solution for this platform. However, all is not lost, and there is alternative way to make this work. Trick is in way how OpenWRT uses flash storage. Image which you download from internet contains squashfs (which is compressed) that enable really efficient usage of storage on router itself. All additional packages are installed into overlay file-system, which doesn't support compression so you will fill root file-system really quick. However, there is solution. OpenWrt project provides Image Builder which enables you to select packages which are included in base installation, and thus ends up in squash file-system nicely reducing need for flash storage. Even better, you can also exclude packages which you are not going to use. However, to make this really useful you also have to provide files directory which contains modifications needed to make your specific router configuration work (like IP addresses, OpenVPN keys, n2n keys and similar modification).

First, I downloaded OpenWrt Barrier Breaker (Bleeding Edge Snapshots) and created files directory in which I will create files which are specific for my setup. For a first build (to make sure that it works I just copied /etc/config/network into it and rebuild image with

make image PROFILE=TLWR740 PACKAGES="-dnsmasq -ip6tables -ppp \
 -ppp-mod-pppoe -kmod-ipt-nathelper -odhcp6c \
 openvpn-openssl n2n muninlite" FILES=../files/
I didn't need dnsmasq (because ADSL modem will provide DHCP service for my network) and along the same lines, I also excluded ppp and nat but added openssl, n2n and muninlite (which is munin node written in C).
After rebuild, I copied created image to router and started upgrade with
scp bin/ar71xx/openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-sysupgrade.bin root@192.168.1.2:/tmp/
ssh root@192.168.1.2 sysupgrade -v /tmp/openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-sysupgrade.bin
Than I hold my breath and after re-flashing router it rebooted and connected to my network. So far, so good. Now I had all required packages installed, so I started configuring packages to my specific need. In the end, I had following configuration files which I copied back to my files folder
dpavlin@t61p:~/openwrt$ find files/
files/
files/etc
files/etc/config
files/etc/config/system
files/etc/config/network
files/etc/config/wireless
files/etc/config/openvpn
files/etc/config/n2n
files/etc/openvpn
files/etc/openvpn/tap_home.conf
files/etc/openvpn/tap_home.sh
files/etc/openvpn/prod.key
files/etc/init.d
files/etc/init.d/openvpn
files/etc/dropbear
files/etc/dropbear/authorized_keys

After another rebuild of image to make sure that everything works, I was all set with new router for my home network.

As you know by now, few months ago I built 433 MHz control of power sockets using rc-switch. Since then, I somehow lost remote control for it so I decided to have more permanent solution than bunch of wires. This time around I also used USBee AX Pro clone to check voltage levels which meant that I first had to make it work on Linux.

IMG_20131215_184439.jpg

You can see final result on picture included in this post. It was mixed experience which included few surprises which might be useful to other people doing hacking with Raspberry Pi, so I decided to write this post. As I'm somewhat cheap, I didn't want to buy Adafruit Pi Cobbler but instead went with Raspberry Pi GPIO adapter board module which has additional benefit of routing 5V and 3.3V to power rails on breadboard. I already had 26 pin cable, but if you don't have one, make sure you get that also. Breakout board also have markings for wiringPi (as opposed to one of other variants of GPIO pins on pi). When breakout board arrived I noticed something interesting: it requires power pins which are aligned with holes on main board. Examine picture below to see difference.

breadboard-power-pins-aligment.jpg

As you can see on top 400 point breadboard, power pins are in the middle pins of main area which means that you won't be able to plug in breakout board into power rails. I was fortunate enough that another 800 point breadboard had power pins aligned with main area, but none of smaller 400 point breadboards I have are correctly aligned. Picture on seller's site does show 400 point breadboard, but adapter board shows V2.0 while mine is V2.2, but judging from picture 400 point breadboards with aligned pins do exist.

This time around, I also received USB Oscilloscope and logic analyzer which includes two analog ports which is clone of USBee AX Pro so I decided to see signals which receiver generated using it and picture is included below.

RF443-scope.PNG

As you can see, I was forced to use Windows XP in virtual machine to make it work. Although there is free software support for logic analyzer part of it in sigrok developers aren't really excited with USBee AX Pro clones so support for analog channels is missing. There is code in ax branch, but I haven't had a chance to try it yet. For few months I thought that it doesn't work at all, mostly because I was trying to make it work in kvm and VirtualBox. Finally, a friend suggested to try vmware, and it worked without a problem. Since there is open source implementation of USBee SX protocol, I think it's quite possible to extend it to support analog ports on AX Pro, but I haven't had time to do this yet. Have in mind that buying USBee Test Pod clones is not something CWAV condones, and newer versions of software from their's web site will re-flash the device (original is read only) which will make it unusable. DX has a long thread with dead links to Cypress site how to fix this, but easiest solution I found so far was to go to site of another clone called ESLA201A and download fix_esla201.rar which includes everything you need to re-flash USB ID back to USBee AX Pro in single rar archive.

When you are trying to configure touch screen on Linux machine, internet offers examples Xorg.conf configuration but without explanation were numbers in it came from. If you have different touch screen you might be out of luck or guess what to do. In this post, I will try to explain how to examine your device using evtest and try out settings using xinput without restarting X server or installing any drivers other than built-in evdev.

microtouch.jpg

We have a couple of 3M MicroTouch M150 touch screens which are VGA monitors (1024*768 resolution) with USB touchscreen interface which is reported as:

dpavlin@t42:~$ lsusb -d 0596:0001
Bus 002 Device 002: ID 0596:0001 MicroTouch Systems, Inc. Touchscreen
A bit of googling later, I found out that there are two different drivers for microtouch devices, but both of them support serial devices only. Not giving up that easily I decided to see what xinput reports about it (without any additional drivers installed!):
dpavlin@t42:~$ xinput list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ 3M 3M USB Touchscreen - EX II             id=9    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=11   [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                     id=12   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Sleep Button                              id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=10   [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                    id=13   [slave  keyboard (3)]
This seems like a good news, but when I tried to use it, it seemed that cursor would move only in middle of screen (with X axis swapped) so I wasn't very happy about it. Examining properties of device in more detail revealed that it has property to swap axes and calibrate them, but what to write into those values?
dpavlin@t42:~$ xinput list-props 9
Device '3M 3M USB Touchscreen - EX II':
        Device Enabled (139):   1
        Coordinate Transformation Matrix (141): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
        Device Accel Profile (263):     0
        Device Accel Constant Deceleration (264):       1.000000
        Device Accel Adaptive Deceleration (265):       1.000000
        Device Accel Velocity Scaling (266):    10.000000
        Device Product ID (257):        1430, 1
        Device Node (258):      "/dev/input/event7"
        Evdev Axis Inversion (267):     0, 0
        Evdev Axis Calibration (268):   <no items>
        Evdev Axes Swap (269):  0
        Axis Labels (270):      "Abs X" (261), "Abs Y" (262)
        Button Labels (271):    "Button Unknown" (260), "Button Unknown" (260), "Button Unknown" (260), "Button Wheel Up" (145), "Button Wheel Down" (146)
        Evdev Middle Button Emulation (272):    0
        Evdev Middle Button Timeout (273):      50
        Evdev Third Button Emulation (274):     0
        Evdev Third Button Emulation Timeout (275):     1000
        Evdev Third Button Emulation Button (276):      3
        Evdev Third Button Emulation Threshold (277):   20
        Evdev Wheel Emulation (278):    0
        Evdev Wheel Emulation Axes (279):       0, 0, 4, 5
        Evdev Wheel Emulation Inertia (280):    10
        Evdev Wheel Emulation Timeout (281):    200
        Evdev Wheel Emulation Button (282):     4
        Evdev Drag Lock Buttons (283):  0
First task was was to flip x axes to make it move left-right instead of right-left. This can be acomplised using following command:
dpavlin@t42:~$ xinput set-prop 9 267 1 0
Parameters are device id, property id, X axis swap and Y axis swap. If you don't know how many parameters property takes, just put one, try it out and if it returns errors, keep adding parameters until it suceeds.

Next, I needed to calibrate screen to track my finger moving over surface. This is where evtest comes into play. It's low level utility which enables you to see input events before they are passwd to Xorg server. You will have to run it as root as follows:

dpavlin@t42:~$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:      AT Translated Set 2 keyboard
/dev/input/event1:      Lid Switch
/dev/input/event2:      Sleep Button
/dev/input/event3:      Power Button
/dev/input/event4:      ThinkPad Extra Buttons
/dev/input/event5:      Video Bus
/dev/input/event6:      PC Speaker
/dev/input/event7:      3M 3M USB Touchscreen - EX II
/dev/input/event8:      SynPS/2 Synaptics TouchPad
/dev/input/event9:      TPPS/2 IBM TrackPoint
Select the device event number [0-9]: 7
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x596 product 0x1 version 0x410
Input device name: "3M 3M USB Touchscreen - EX II"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 330 (BTN_TOUCH)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value   7353
      Min        0
      Max    16384
    Event code 1 (ABS_Y)
      Value   4717
      Min        0
      Max    16384
Properties:
Testing ... (interrupt to exit)
Immidiatly we can see minimum and maximum values for both axes and putting figer on top-left corner of screen produced (a lot of) output like this:
Event: time 1386078786.506710, -------------- SYN_REPORT ------------
Event: time 1386078786.510712, type 3 (EV_ABS), code 0 (ABS_X), value 13919
Event: time 1386078786.510712, type 3 (EV_ABS), code 1 (ABS_Y), value 2782
After a few touches I had coordinates which where something like this:
14046,27222380,2986
7994,7819
13743,136162624,13545
Strangly it seems that origin is top-right corner, but we shouldn't care much about it beacuse we can specify them using following command (after rounding them a bit):
dpavlin@t42:~$ xinput set-prop 9 268 2380 14000 2800 13500
Trying it out on screen proved that it now works as expected. Let's call this success and remember that current Xorg knows a lot of tricks itself (recognising USB touch devices is one of them).

As a side note you don't really need to use evtest to get device position. Using xinput list id syntax displays you more-or-less same information, including last point which you touched on device as seen below:

dpavlin@t42:~$ xinput list 9
3M 3M USB Touchscreen - EX II                   id=9    [slave  pointer  (2)]
        Reporting 3 classes:
                Class originated from: 9. Type: XIButtonClass
                Buttons supported: 5
                Button labels: "Button Unknown" "Button Unknown" "Button Unknown" "Button Wheel Up" "Button Wheel Down"
                Button state:
                Class originated from: 9. Type: XIValuatorClass
                Detail for Valuator 0:
                  Label: Abs X
                  Range: 0.000000 - 16384.000000
                  Resolution: 0 units/m
                  Mode: absolute
                  Current value: 13889.000000
                Class originated from: 9. Type: XIValuatorClass
                Detail for Valuator 1:
                  Label: Abs Y
                  Range: 0.000000 - 16384.000000
                  Resolution: 0 units/m
                  Mode: absolute
                  Current value: 2832.000000
However evtest will run in loop until you stop it with Ctrl+C so I find it a little bit easier to use than re-running xinput list id.

Last week I had workshop on CARNet User Conference on topic of ZFS on Linux. In it, I tried to describe my experience with it, from zfs-fuse days up until today. There are quite a few useful bits in this presentation, covering everything from history and basic ZFS concepts up to smart hints and some downsides. I hope it was useful to people who attended it and that you, dear reader, will find something useful in presentation which is embedded below.

One of simplest home automation projects is to control power sockets. Back in the old days, this involved relays and parallel port, but nowadays you can buy ready made power sockets with remote control which work on 433 MHz IMS band. So next logical step is to replace remote control with computer controlled 433 MHz module. In this post, I will explain how to do it using Arduino or Raspberry Pi.

Power sockets with 433 MHz remote control

For this project I decided to try out two different types of power sockets available at our local hardware shop.

IMG_20130929_131622.jpg IMG_20130929_151434.jpg

As you can see they are quite different, but any of then will work fine. On the other hand, big bulky square ones have much more useful indicator on then which lights up then they are enabled, while smaller round ones have light which just denotes that they are plugged into electricity but doesn't show status of relay inside of them.

433 MHz modules

IMG_20130930_001121.jpg

If you want to communicate with these devices you will need some kind of radio modems. For this project, I decided to use cheap 433 MHz radio modules which come in pair: one of them is sender while another is receiver. On picture you can see modules with attached antenna.

I can't stress enough need for antenna. Although modules will work without it, they will have a really poor range of just few centimeters. Antenna should be 172 mm (1/4 of wavelength), and according to my friend who knows something about this things, it's equally bad to have longer or shorter antenna than that. I added 3 mm more for solder joint and it did improve reception and sending range dramatically. You can use any wire for antenna, in my case, I used wire used for wrapping power cords which was long enough to make two antennas.

Arduino

IMG_20131012_193005.jpg

As a first step, I decided to hook them to Arduino Uno to see some waveforms and test rc-switch library. Sure enough it worked on first try. I added project to my ~/Arduino/libraries/RCSwitch directory and used ReceiveDemo_Advanced example to capture signals. Another example, SendDemo enabled me to send signals back to power sockets and turn them on or off. Success on the first try.

With a little bit of tweaking I created RF433_Sockets.ino which allows receiving signals, turning sockets on or off or sending raw binary data to test protocols.

As you can see on picture, I also connected cheap logic analyzer clone to see signals and Bus pirate to monitor signal levels using Bus Pirate oscilloscope python script to make sure that I can connect it to 3.3V level device in next step and I got signals like this on receive pin: scope_2013-09-29T17:57:00.873653.png

Raspberry Pi

IMG_20131016_135743.jpg

Having verified that signal receiver is generating 3.3V signals (up to 3.6V is OK and mine is 3.46V - electronics isn't exact it seems :-), I decided to hook it up to Raspberry Pi so I will have Internet connected control over my power sockets.

Following link on rc-switch site to port for Raspberry Pi didn't end up all that well. This version of code doesn't support receiving of data, and sending code generates segfaults. However, after a little bit of searching I found blog post about Adding 433 to your Raspberry Pi from NinjaBlocks which inclues link to github repository with code which works fine.

Both versions of code use WiringPi library which is nice way to port Arduino code to Raspberry Pi. When sending signals to 5V devices 3.3V Raspberry Pi GPIO will be usually fine, but when receiving singals, make sure that they are 3.3V or you will fry your Raspberry Pi.

Less than $10 and few hours of work...

Having said all that, it's really easy to create your own home automation system. So I don't see a reason not to do so...

Parts list: (assuming you already have Arduino or Raspberry Pi)

nRF24L01 It's again this time of year when security researchers (and me) gather in Varaždin for fsec, vendor-neutral technical security symposium, hosted by Faculty of Organization and Informatics. This year, I deiced to re-visit my question about security wireless keyboards, so I ported Travis Goodspeed's GoodFET to Arduino UNO. Goal was to use cheap nRF24L01 modules from ebay to see if my Chicony KG-0609 keyboard is sniffable. And it is...

You can find the presentation in which I also tried to cover my experience with hardware hacking below.

I hope it was interesting to people who attended it, although I suspect that I crammed too much content into 30 minute slot which I had. If you are interested in my changes, they are available in Arduino_Uno branch in goodfet project at git.rot13.org.

This event has special place in my calender since I'm alumni and it's always nice to meet again friends and professors and visit again place where I started my Unix administration back in 1995. Thanks to everybody for nice three days in beautiful Varaždin.

IMG_20130908_140327.jpg

A few weeks ago my WRT54GL decided to die. This was quite fortunate because I wanted to upgrade my always on machine to something more powerful and install Debian on it. I had ADSL modem with wifi, so I didn't need wifi in my new box. Fortunately, I got a Igel 3/4 thin client with VIA Eden chipset, 256Mb of RAM and 128 Mb of CF storage so I decided to move by main gateway functions to it.

I had following requirements:

  • pppoe to connect to by ISP
  • dnsmasq to provide DHCP for my LAN
  • iptables will provide NAT
  • openvpn and n2n to provide VPN
  • motion so I can see what my dog is doing when I'm not home
As a first installation I started with Thinkpad T22 (since Igel was still on the way). All went quite well (after figuring out that I can't boot T22 from USB) but it took 2GB of disk space. That won't fit on 128MB CF card, so I acquired 2GB CF card. Still, even with it, the storage will be tight, so I decided to use btrfs with compression. And this is where the real story starts...

As a first step, I plugged 2GB CF card into USB adapter on my desktop (Igel can't boot from USB), created btrfs filesystem and mounted it using compress=zlib,ssd. After coping files over size of installation dropped from 1.9GB to just 840MB. This card will be adequate choice for my gateway. I was also toying with idea of moving my apt-cache-ng to this machine, so I wanted more space, and decided to also plug additional 8GB USB keychain for swap and cache storage. But, since I have two devices wouldn't it be better to create btrfs raid1 on it so I can survive failure of CF or USB (ignoring cache and swap)?

Next I plugged CF and USB into Igel and booted it. First boot was slow, but what can you expect from 600 MHz VIA Eden? Here is hdparm speed of CF (sda) and USB (sdb):

root@igel:~# hdparm -tT /dev/sd{a,b}

/dev/sda:
 Timing cached reads:   310 MB in  2.02 seconds = 153.76 MB/sec
 Timing buffered disk reads:  38 MB in  3.11 seconds =  12.22 MB/sec

/dev/sdb:
 Timing cached reads:   302 MB in  2.00 seconds = 150.92 MB/sec
 Timing buffered disk reads:  56 MB in  3.07 seconds =  18.26 MB/sec
It's interesting that USB is faster than CF. So, let's try to move my single drive btrfs filesystem to RAID1 configuration using:
btrfs device add /dev/sdb1 /
btrfs balance start -dconvert=raid1 -mconvert=raid1 /
This is where the problems started. I was running Debian wheezy with 3.2 kernel and rebalance filters are introduced in kernel 3.3. So I upgraded to sid with 3.10 kernel to see weather it will fix at least some btrfs issues. As we will see it really didn't. I got reports about corrupt blocks and after a while I decided to unplug CF and USB, move then over to desktop and create mirror filesystem there.

This worked (and didn't report any errors after scrubing) so I was somewhat confident that my data is safe. This time around, I decided to use noatime,compress=lzo,ssd_spread mount options to gain some speed. Filesystem did grow to 1.2GB (50% increase since I was using lzo instead of zlib for compression) but it was still acceptable. Next, I returned storage to Igel and tried to boot it. Another surprise: it couldn't mount root file system. When I got initrd shell, I could indeed see that I don't have /dev/disk/by-uuid/ nodes for root mostly because it wasn't mounted. However, manual mount from /dev/sda1 didn't work either. However, manual mount from /dev/sdb1 did work. After searching a web for reason it seems that Debian's initrd doesn't issue btrfs device scan on boot so multi-device btrfs filesystems don't get correctly recognized. Why does it work from second disk in mirror is still a mystery to me. I enabled GRUB_DISABLE_LINUX_UUID=true in /etc/default/grub and moved on...

However, my problems weren't over just yet. After running update-grub on booted filesystem Igel was again unbootable. It was reporting strange errors in part because grub-probe got both devices:

root@igel:~# grub-probe --target=device /
/dev/sda1
/dev/sdb1
This was easy to fix. I modified /usr/sbin/grub-mkconfig to report just /dev/sdb1 so it will be bootable:
GRUB_DEVICE="`${grub_probe} --target=device / | tail -1`"
The story would end here if I didn't try again to run btrfs balance start /. This time around, it didn't report any corrupt blocks, but it did oops kernel with out of memory backtrace. Lesson learned, 256MB RAM is too small for 2GB btrfs filesystem balance. Live and learn. Problem now was that balance restarted when I booted system. So as solution, I unplugged USB which dropped me into initrd shell where I could issue btrfs balance pause / followed by btrfs balance cancel / (cancel alone wouldn't do the trick).

So, what can I conclude about current state of btrfs? It does work (with some hand-holding) but it also has rough edges. But, if you really have flash based storage and need compression it is a valid choice.

For a last few months, I have been playing around with Arduino and collecting useful parts for my first real project. Last week we purchased Mitsubishi air condition with super-invertor and I wasn't totally happy with the way it operated so I took several afternoons and tried to understand how temperature in my room was varying depending on it's settings. To do that, I built simple temperature monitor using Arduino Nano, two temperature sensors and Nokia 5110 screen. This post tries to document my journey...

Arduino based temperature monitor

Arduino Nano bootloader flashing

When I started buying Arduino parts, I decided I'm cheap bastard and bought Arduino Nano without boot loader flashed, so as first step, I had crash course into ISP programming. As you can see on picture, my board doesn't even have ISP header soldered on it (although it came with one) which might explain why it wasn't pre-flashed. Fortunately, I do have Bus Pirate v3b clone from Sand Box Electronics (essential tool for any micro-controller work in my option) which can also work as ISP programmer for Arduino. On first try, I flashed wrong boot loader (holding ISP header with my finger since it wasn't soldered and using Bus Pirate cables), but I soon learned that Arduino software has helpful boards.txt file from which you can lookup correct boot loader using something like:

dpavlin@blue:~$ grep nano328 /usr/share/arduino/hardware/arduino/boards.txt  | grep bootloader.file
nano328.bootloader.file=ATmegaBOOT_168_atmega328.hex
So, I learned that chap Chinese Arduino clones will give you opportunity to learn something new. I could have used another Arduino for that also, but at the time I didn't have any. Lesson learned, always buy two of each components in hope that one of them will work.

Temperature sensors, display and parts

Having Arduino alone isn't really useful, so I decided to try different on-line shops and collect various parts needed for this project:

You might be wondering why I have two sets of jumper wires. As you can see on picture, I used both of them, since it's much easier and neater to route power and ground around breadboard using pre-made wires which come in various different sizes and sit nicely on top of breadboard and connect everything else using longer jumper wires with plastic handles.

I also have two temperature sensors. I started with DHT11 (mounted on small board with useless red power led - I wouldn't recommend that for next project) which is nice and provides temperature and humidity reading, but I don't get any decimal places in it's output. It's left temperature reading on display. Than I remembered that I have couple of DS18B20 sitting in drawer so I added a 4.7K resistor and hooked it up. This is where things become much more interesting - it's much more accurate that DHT11 so I decided to use that value to draw graph (and display right temperature reading with two decimal places). I also noticed that temperature readings differ by 1 degree or so between sensors.

And a little bit of software

One of main reasons why I'm excited about Arduino is it's software support. While it's a shame that there isn't anything like central repository of software libraries (no, wiki pages at Arduino site doesn't count as one) it's really nice that you can find libraries for everything you might need. This does introduce another problem: now to track all those libraries and your project?

I decided to use git and track everything in my ~/Arduino directory. Initially I was hoping that every library will have upstream git repository so I could use git modules to track them, but some of them don't so I just add them to my repo. This works quite well (if I remember to save sketch before trying to commit it). I started with DHT11 library example and continue adding other parts of code to it. Then I added Arduino Library for Dallas Temperature ICs which in turn uses OneWire to support DS18B20 which doesn't really speak normal i2c protocol. With that working (and reporting temperature back through serial port) it seemed like some kind of local display is in order. So I took Nokia 5110 display I had handy (which I really prefer to other solutions - it's cheap and can display graphic) and took Adafruit driver for PC8544 which in turn again needed Adafruit GFX graphics core library. It seems like mess by now, but it's quite workable and easy to hook together. Only thing that I had to take care is that name of directory within ~/Arduino/libraries should be same as library name itself, which isn't same as name of upstream repository. Oh, well...

This is where (some) form of real development kicked in. I decided to make small circular buffer for DS18B20 readings and draw that as scrolling graph, RRD style. As last step I also added PWM driven back-light to display which is off if value didn't change, half-dimmed if current temperature is lower than previous one or full brightness if it's higher (warning, warning: melting in progress :-) If can take a look at source of DHT11 DS18B20 temperature monitor sketch in all it's 5k glory if you wish. I will probably add average of last three readings for back-light brightness and reduce serial output to format which is better usable for real RRD graphs, but so far this has been useful and fun project. I also understand my air condition operation a little better now :-)

DHT11_DS18B20_temperature_bb.png

Finally, I used Fritzing to capture schematic output of this project so I don't have to write down pin mappings somewhere. It's somewhat unstable, especially if you try to edit custom parts (I replaced red LCD breakout board with the one which I have) but overall it's a great way to produce structured info about your breadboard view. Having ability to copy/paste elements from other drawing (DHT11 in this case) saved me from defining another custom element.
For some reason, I'm not getting correct schematic view for DS18B20. I might have defined something wrong for it or I just don't know how to correctly use Fritzing yet.

For last few months i have been playing around with Arduino. I came to conclusion that this platform is probably only one which I can recommend and develop for. Let me try to explain how I arrived to that conclusion...

It's easy to use for novices

This is especially important for me, since I'm mostly software kind of person. I don't solder and probably never will. But using just a few wires and so many good tutorials on the web together with availability of sub-$10 sensors and peripherals on Chinese sites or ebay it seems that we are currently in situation where anyone can get into hardware. And everyone should, at least to know what is possible. Arduino was design with teaching in mind in the first place.

There are lot of good examples

This basically boils down to: It's googlable. I'm aware this is not real verb, but what I mean by it is: there are enough info about every single peace of hardware you might buy if you just enter it's designation and arduino in google. That's a huge benefit and only other embedded platform which comes close to it is probably Raspberry Pi.

There is support for different architectures

This is probably point which is not obvious at first, but makes me most excited about Arduino. Let me try to list just some of them (this is somewhat random selection, not exhaustive comparison of characteristics of all the Arduino boards):

  • Arduino Uno - ATmega328, probably best one to get started
  • Arduino Mega - ATmega2560, as the name implies, it's probably second board you will buy when Uno becomes too small for your project
  • Arduino Due - Atmel SAM3X8E ARM Cortex-M3 CPU, first official Arduino board which isn't AVR. This makes my point about different architectures clear, but read on...
  • Pinguino - PIC18 8-bit or PIC32 32-bit CPUs, so if you dislike AVR you don't have to use it :-)
  • The Maple - STM32F103RB 72MHz ARM Cortex M3, exists longer than Due and included here to show that Arduino wasn't driver for multi-platform CPU support
  • Energia - MSP430 16MHz board for under $10
  • pcDuino - A10 1GHz ARM Cortex A8, this is full-fledged Linux machine with Arduino IDE support (it can also run Android, but we are not interested in that).
  • Papilio FPGA - Spartan 3 or Spartan 6 FPGA boards with support for Arduino IDE. If your design does signal processing, this is right path forward with your code, but you will have to learn VHDL and/or Verilog also! It supports two different CPUs implemented in FPGA: AVR8 - Clone of the AtMega103 chip with standard AVR peripherals and ZPUino - Arduino on steroids: 100Mhz, 32-bit, 96Mhz, up to 8MB code space.
While some of this boards are also compatible with Arduino shields, there are also others which don't use Arduino IDE, but can use Arduino shields. I don't care much about shields because I like my wires to be all over the place :-)

Open hardware respects your freedoms

Having all this CPUs and boards available (and in open hardware fashion which means with full documentation) makes me confident that I'm not wasting my time implementing something today. You will have to read schematics and examine data-sheets anyway, so having all documentation (and files required to produce your own boards) is very beneficial.