Effective QR-scanning with the Raspberry Pi and Camera Module

For a recent project I had a need for a reliable and fast QR-code scanner. I had an Raspberry Pi 2 single-board computer on hand and coupled with the Pi Camera Module and some elbow grease I managed to come up with a rather sweet setup.

Hardware

The official Raspberry Pi version 2 Camera Module consists of a 8-megapixel Sony IMX219 sensor mounted behind a fixed focus lens on a small circuit board. The board connects to the computer CSI connector via a flexible ribbon cable.

Cable

The stock ribbon cable supplied with the Camera module is too short (150 mm) to allow for a comfortable positioning of the module for QR-scanning. The are available replacement flex cables of various length that can be easily swapped in — I went with a 500 mm cable.

Focus point

The camera system has a huge depth of field but the fixed lens is still focused too far away to get sharp shots at the distances one would want in a QR-scanner. The lens is fixed with some glue but when this is broken or scratched off is it actually possible to rotate it in its assembly thus adjusting the focus point of the system.

tools

Tools of the trade.

There are many instruction videos on the net showcasing various techniques to achieve this, what worked for me was a small pliers to keep the non-rotating part of the assembly secure while applying force on the lens knobs with a tiny pointed screwdriver to force the lens to rotate counter-clockwise.

rotateReal force is actually required to break off the glue, but after this can the lens be adjusted rather easily. To determine the amount of rotation required I’d recommend to take frequent snapshots with the raspistill CLI tool shipped with Raspbian during the operation, stopping when sharp shots at 10 cm are achieved.

According to reports should it be possible to unscrew the lens from the assembly if it’s rotated too much. I’d like to think it would be quite finicky to re-attach so be careful! It’s only a matter of ~ 360° of rotation to achieve the desired focus point.

Software

The first step after attaching the camera is to enable it in  /boot/config.txt  (can be done with simple raspi-config utility), rebooting and verifying basic camera functionality with raspistill.

For the next steps are there a plethora of  write-ups. Many solutions appear to be quite fragile. I wanted something more robust, something not depending on python libraries that’s not installable with pip or downloads of binaries from unmaintained SourceForge-projects.

I finally ended up with agilerule’s QRScanner.java which utilizes the proven zxing java QR-code library (appears to be very popular in the Android eco-system) to detect QR-codes in snapshots taken by the standard raspistill command line tool. I threw in some optimizations:

  • The time consumed by zxing to detect a QR-code is proportional to the resolution of the image. The full 8 megapixel sensor resolution is very much overkill, I finally settled for 400×300 pixel snapshots (0,12 megapixel) as a compromise between detection speed and accuracy. This low resolution means that the image-acquisition, QR-detection cycle is dominated by the acquisition phase and that it’s possible to  detect ~1 QR-code/second.
  • Rather than dumping the acquired images to the root file system one can utilize tmpfs, thus saving some wear-and-tear on the SD-card and also perhaps achieving a minuscule performance improvement.

To try it:

  1. Clone the repo: git clone https://github.com/nordstrand/qr-scanner-for-raspberry-pi
  2. Install maven
  3. Run: mvn clean install exec:java

Conclusion

This QR-scanning setup is quite usable and responsive but cannot be compared with what you’d find at the super market checkout line when it comes to speed and accuracy.

The item to be scanned should ideally be positioned as parallel to the camera film plane as possible. Sharp shadow lines falling on the scanned item can cause problems. So can light sources shining directly into the lens. What worked best for me was an inverted mount, with the camera pointed down towards a dark surface. I’d also recommend to add a buzzer that can make some beeps after succesful scans.

position

~10 cm from the camera film plane to the scan target will work fine for a wide variety of QR-code sizes.

My main focus of improvement would be to increase the scanning speed. That would entail using something other than raspistill still image acquisitions, perhaps time lapses or trying to access the camera through a lower-level C interface.

 

 

Configuration management on the Raspberry Pi

Raspberry Pi computers running the Raspbian flavour of the venerable Debian Linux distribution make excellent headless home servers. Inexpensive, small, quiet, reliable, power-efficient and powerful enought to be employed as NAS-appliances, BitTorrent boxes, AirPlay receivers, blog hosts, beer fermentation controllers etc etc.. Setting up a Raspberry Pi for these application are seldom as trivial as a:

$ apt-get something

More typical are laborious sessions at the console cloning git repos, running DDL scripts, tweaking cron tables as directed by long step-by-step tutorials in blog posts.

If  one had to endure this once and then be set for the foreseeable future things might not be too bad.

However, as stable the Pi hardware is it does have one Achilles’ heel – persistent storage. The SDHC-cards used for holding the root file system are  infamous for not holding up very well in the long-term (perhaps not too unexpected considering the much less demanding camera applications SD cards typically are designed for). Eventual file system corruption appears  to be almost unavoidable, as the plethora of online problem reports bears wittnes to [1], [2].

This problem leads to frequent (re)imaging of cards. If one wasn’t for foresighted enough to keep a full backup image hanging around you’ll have to start from scratch with an install image, toiling away at the step-by-step guides again.

Enter modern configuration automation tools. The prefered silver bullet of the fledging devops movement promises big saving in the data center automating all kinds of system administration task on hordes of virtual machines in private or public clouds.

Recently I’ve experimented with applying these tools on a different kind of platform: the humble Raspberry Pi.

The tools provides ways to specify the desired configuration of the nodes under control in various domain specific languages. These languages typically allows for powerful encapsulation and modularization abstractions thus managing complexity and promoting reusability. The tools offers several importants benefits compared to manual or semi-manual configuration :

  • Large libraries of ready-to-use modules for tasks such as controlling databases, installing packages, etc
  • Convenient mass application of specification on multiple nodes
  • Idempotency. Specifications can be re-run repeatablity ensuring that controlled nodes are up-to-date with the latest addition.
  • More friendly syntax than bash.

I’ve taken a closer look att Puppet, Pallet and Ansible.

Puppet is a well-known Ruby based tool that has been around for a while. The Puppet ecosystem is huge and there is a great assortment of third-party modules ready to use for almost any task. I’ve used Puppet for implementing a manifest that installs the Tiny Tiny RSS reader on PostgreSQL with data backups, feed updates, etc.

Pallet is a newer Clojure based option. In the trio it is the option which currently clearly enjoys the least amount of community traction, the available documentation is also sparse and disorganized. Even though I’m attracted to Clojure as a language these factors caused me to abandon Pallet for now.

Both Puppet and Pallet are heavily geared toward operation in large data centers, offerings features to control and organize hundreds of nodes. Puppet also in general relies on central master nodes that agents on controlled nodes periodically pull new configuration specs from. This is a huge impedance mismatch when one only wants to control  a couple of a Raspberry Pi servers in a living room.

Ansible is a relatively new Python based tool hitting 1.0 as recently as February 2013. Compared to Puppet there is less documentation available and the selection of third party modules is still a little behind. However is Ansible under heavy development with features and new modules added at a furious pace, the latest release being 1.3 as of August 2013.

Ansible is by design push based and agent less, requiring no running daemon on controlled hosts. Since Ansible uses standard ssh as transport to control hosts it is perfectly possible to control hosts without installing any additional software at all on them. The apt modules however requires python-apt and aptitute to be installed (easily achieved remotely with the Ansible shell module).

This means that it’s possible to assume control of a freshly imaged Pi without ever manually logging in!

Ansible is remarkably quick and executes a typical playbook much faster than a corresponding Puppet manifest on the modest Pi hardware. Ansible comes with a great deal of instant gratification, the learning curve beeing  smoother than that of Puppet, much of which probably can be attributed to a simpler specification language. Ansible playbooks are YAML, Puppets manifest is a Ruby DSL. Yaml is definitely less ceremony, and more cool. Puppets manifest are declarative in nature, one defines the desired actions to be taken and relationships between them (like before/after) leaving Puppet to figure out the correct execution sequence, while Ansible’s style is more imperative. Puppets style of specification may offer better optimization possibilities on the tool level and perhaps specs that are easier to maintain in the long run, but so far I’m very happy with Ansible’s simpler approach.

The conclusion is simple: to control a couple of Pi:s go for Ansible!