Barcode and QR Code with Beaglebone

From Texas Instruments Wiki
Jump to: navigation, search


TIBanner.png
Barcode and QR Code with Beaglebone
Sanjeev Premi


Introduction

It had been few weeks since BeagleBone had been with us, but it wasn't really used for anything beyond the Linux kernel development. With many folks our on vacation for the Christmas, there was an opportunity for us to do something with the board in spare time.

Though we didn't have any specific application in mind, the objective was to work one something that hasn't yet been tried on the board and can be used standalone.

We stumbled on zbar by chance. But the idea to use it was an immediate hit.

About zbar

ZBar is an open source software suite for reading bar codes from various sources, such as video streams, image files and raw intensity sensors. It supports many popular symbologies (types of bar codes) including EAN-13/UPC-A, UPC-E, EAN-8, Code 128, Code 39, Interleaved 2 of 5 and QR Code. It is licensed under the GNU LGPL 2.1.

Objective

The objective of the application was:

  • Read the barcode/QR Code using a USB camera attached to the Beaglebone.
  • For barcode:
    • Fetch the information corresponding to scanned barcode from well known database
    • Display information to the user
  • For QR Code:
    • Extract the decoded message
    • Display the message to the user

Screenshots

Watch the video

Quick introduction & Demo

Quick Demo at your desk

Here are the instructions to prepare an SD card to run pre-built demo:

Prerequisites

  • A Beaglebone (Rev A3) with a compatible 5V Power Supply
  • A USB Camera
  • A USB-to-Serial Cable
  • A Micro-SDHC card

Download pre-built binaries

Download these files to a folder on the host system

Prepare the SD card

  • Format an SD card to be used as boot medium for the Beaglebone using these instructions.
    • After format, 2 partitions will be created on the card:
      • boot
      • Angstrom
NOTE

The filesystem used for the demo is not Angstrom. You may want to edit the script to change the label of this partition to a generic name e.g. filesys; but this isn't necessary.
  • Copy these binaries to the boot partition - in order listed below.
    • MLO
    • u-boot.img
    • uEnv.txt
    • uImage
$ cp MLO /media/boot/.

$ cp u-boot.img /media/boot/. $ cp uEnv.txt /media/boot/.

$ cp uImage /media/boot/.
  • Copy the tarball containing the filesystem to the filesys partition and extract the contents with root (superuser) permissions.
$ cp saral-zbar.tgz /media/filesys/.

$ cd /media/filesys $ tar xvfz saral-zbar.tgz $ rm saral-zbar.tgz $ sync

$ cd -
NOTE

* These instructions assume that both partitions of the newly formatted SD card are mounted as /media/boot and /media/filesys respectively on the host system.
  • Steps to extract the tarball could be optimized. Longish instruction are used for illustration purposes.

Necessary changes to the filesystem

The network interfaces configured in this demo filesystem may require changes to match network where the Beaglebone is deployed.

  • Update the proxy settings in the file /media/filesys/etc/profile.d/proxy.sh
export http_proxy=192.168.1.1:80 export https_proxy=192.168.1.1:80
  • Update the domain and nameserver in the file /media/filesys/etc/resolv.conf
domain dummy.net

search dummy.net nameserver 192.168.1.1

nameserver 192.168.1.1

Launching the application

  • Connect the USB camera to the Beaglebone. Also ensure that Beaglebone is powered by an external 5V supply.
  • Boot the target with SD card prepared with instruction above.
  • At the Linux prompt, launch the application as:
$ TERM=xterm zbarcam #45;#45;alt /dev/video0

Building the Demo from scratch

Prerequisites

  • A Linux host
  • A cross-compile toolchain of choice
  • Linux kernel (uImage) built with uvcvideo.
    • If uvcvideo is compiled as a module, then ensure that the module is inserted before running the application.
  • A filesystem of choice - built for Beaglebone.
    • The ncurses compiled in; with compile-time components available.
NOTE

The tool used for building and/or modifying the filesystem may have additional dependencies. This article assumes that all these dependencies have already been sorted out.

Build the application

NOTE

At time of writing this article, the downloaded file was named zbar-ed4fa27763e9.tar.bz2, where ed4fa27763e9 corresponds to ID of the latest commit on the source repository.
  • Extract the sources in a directory.
$ tar xvfj zbar-ed4fa27763e9.tar.bz2
  • Download the tarball containing patches from here.
  • Extract the patches in the zbar directory
$ tar xvfz zbar-src-patches.tgz
  • Apply the patches in sequence
$ patch -p1 < 1

$ patch -p1 < 2 $ patch -p1 < 3

$ patch -p1 < 4
  • Build zbar in your cross-compile environment.
    • The application contained in the pre-built filesystem (shared above) was built with following commands:
$ autoreconf --install

$ ./configure --prefix=/usr --without-gtk --without-python --without-qt $ make $ make install DESTDIR=<target_install_path>

NOTE

The instructions to build would differ across various tools/ frameworks used e.g. OpenEmbedded, ScratchBox, etc. They are not covered in this article.
  • Download the script bdecode.sh from here and save it in the directory /usr/local/bin of the target filesystem.

Implementation Notes

Design

The default behavior of the zbarcam application is to print the barcode on the console(stdout).

Overall design of the modified application can be described in this sequence of operations:

  • Trap the string containing the barcode/QR-Code string before it is printed on stdout.
  • If the string corresponds to a barcode:
    • Show the raw barcode in a scrollable window.
    • Append the barcode to a predefined URL pattern and fetch the product information via http.
    • Parse the html page to extract product information - without HTML tags.
      • Though time to fetching information cannot be predicted, it is a 'blocking' operation (since it is being done in a shell script).
    • Show the product information in a separate window.
  • If the string corresponds to a QR-Code:
  • Show decoded string/ message in a separate window.

Issues worth mentioning

The project definition was quite simple and we didn't expect too many surprises. Still there were a few!

ncurses

  • In the original implementation, linked lists were used to implement the circular buffer. Each line of text in the window corresponds to a dynamically allocated buffer. However, we had many random errors during execution with glibc detecting memory corruption. These errors came either in first few seconds OR after many minutes.
*** glibc detected *** malloc(): memory corruption
  • We were sure that number of malloc() and free() calls would match if we closed the application. However, these errors would occur even while the listed lists were being populated.
  • None of these errors were encountered when executing the default application - without our additional patches. So, the problem had to be in the code added by us.
  • With no clues coming from code reviews and simple debugging, we decided to run the same application on the development host.
  • Complete application was compiled for the Linux host and executed through valgrind. Surprisingly, there were no crashes. It showed that alloc and free calls matched, but many allocated bytes were still reachable.
$ valgrind ./a.out

==19998== Memcheck, a memory error detector ==19998== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==19998== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. ==19998== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info ==19998== Command: ./a.out ==19998== ==19998== ==19998== HEAP SUMMARY: ==19998== in use at exit: 92,031 bytes in 106 blocks ==19998== total heap usage: 112 allocs, 6 frees, 96,083 bytes allocated ==19998== ==19998== LEAK SUMMARY: ==19998== definitely lost: 0 bytes in 0 blocks ==19998== indirectly lost: 0 bytes in 0 blocks ==19998== possibly lost: 0 bytes in 0 blocks ==19998== still reachable: 92,031 bytes in 106 blocks ==19998== suppressed: 0 bytes in 0 blocks ==19998== ==19998== Rerun with --leak-check=full to see details of leaked memory ==19998== ==19998== For counts of detected and suppressed errors, rerun with: -v ==19998== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

  • As we started to narrow down the possible cause(s), we found that valgrind reported same behavior with this application as well:
#include <ncurses.h>

main() { initscr(); endwin(); }

  • Applying additional patches available against the specific ncurses version didn't help either.
IMPORTANT

We did not debug the issue further - whether problem lies with ncurses OR another library it depends upon. Instead, we changed the implementation of text buffer to use fixed length arrays.
  • The revised implementation uses only a malloc per window - and repeated runs on the Beaglebone didn't show any crashes due to memory corruption.

The USB Camera

Working on a text console - as opposed to Graphical environment - was quite simple until the USB camera was attached for the very first time. We had no clue what camera is 'seeing'. We were almost groping in the dark.

  • Connected the camera to development host. Adjusted the focus (Yes. this camera had manual focus) and calculated approximate distance where the barcodes on sample chart were sharpest.
  • Back to Beaglebone - and we had the default zbarcam application working like charm!

Using libcurl

In the original design, we wanted to fetch the product information using libcurl into a buffer (instead of file). However, even in the simplest modes, we couldn't always guarantee that entire webpage is received in single chunk.

  • As we receive data in chunks, the buffer had to be "reallocated" to add more data. See the function WriteMemoryCallback() in this example for reference.
  • Having spent long time debugging memory corruption issues, we didn't want to get into same issues again.
  • A simple solution/ workaround was to create a script that fetches the html file, parses the necessary data and passes on to the main application.
    • This, however, meant serializing the process of fetching the information related to the barcodes.

Disclaimer

IMPORTANT

* The sources (patches to zbar) can only be described as DEMONSTRATION software. As-is, they CANNOT and SHOULDN'T be treated as production worthy.
  • The sources are available under the GNU LGPL 2.1 - (same as zbar).

The team

  • Sanjeev Premi
  • Vaibhav Bedia
  • Vaibhav Hiremath
  • Ajay Kumar Gupta
  • Anil Kumar Ch
  • Sekhar Nori