Tag Archives: raspberrypi

Running FreeBASIC on Raspberry Pi

FreeBASIC is a pretty nifty cross-platform BASIC compiler. It uses a Microsoft-like syntax, has an active user and developer base, and is quite fast. Building the latest version on a Raspberry Pi is a bit of a challenge, though.

FreeBASIC 1.01 demo running on a Raspberry Pi
FreeBASIC 1.01 demo running on a Raspberry Pi from Geany

Part of the problem is that FreeBASIC is mostly written in FreeBASIC, so you need a working compiler to bootstrap the latest version. The following steps worked for me:

  1. Install some necessary packages:
    sudo apt-get install build-essential libncurses5-dev libffi-dev libgl1-mesa-dev libx11-dev libxext-dev libxrender-dev libxrandr-dev libxpm-dev ncurses-doc libxcb-doc libxext-doc libgpm-dev git libcunit1 libcunit1-dev libcunit1-doc

    (You don’t really have to include the cunit packages; they’re only needed if you run tests before installation.)

  2. Download a nightly binary from Sebastian’s server: http://users.freebasic-portal.de/stw/builds/linux-armv6-rpi/  and install it:
    unzip fbc_linux_armv6_rpi_version.zip
    cd fbc_linux_armv6_rpi/
    chmod +x install.sh
    sudo ./install.sh -i

    Don’t delete the installation folder just yet.

  3. Grab the latest version of the source from github:
    git clone https://github.com/freebasic/fbc.git

    Change directory to the new FreeBASIC source folder (cd fbc), and type make. (or, on a Raspberry Pi 2, make -j4 to use all the cores …). After a while (in my tests, about 52 minutes on a 512 MB Raspberry Pi, or around 6½ minutes [!] on a Raspberry Pi 2), it should finish. If there’s a bin/fbc file, the compilation worked!

  4. Before you install the new compiler, uninstall the old one: change directory to the fbc_linux_armv6_rpi folder, and type:
    sudo ./install.sh -u
  5. Once that’s done, go back to the new fbc folder, and type:
    sudo make install

And you’re done! You can delete the fbc_linux_armv6_rpi folder now. If you don’t mind it taking up space, keep the fbc folder to allow you a quick rebuild of the latest version of the compiler with:

cd fbc
git pull
sudo make install

Note that this will build a native armv7l compiler on a Raspberry Pi 2, and an armv6l one on a Raspberry Pi. This means you can’t run binaries you built on a Raspberry Pi 2 on a Raspberry Pi (you’ll get an Illegal Instruction error), but you should be able to run ones built on a Raspberry Pi on a Raspberry Pi 2. Binary compatibility is overrated, anyway …

all I wanted to do was rip a CD on my Raspberry Pi …

So, the DVD drive on my laptop’s on the fritz. It reads data fine, but ripping CDs with CDDA checks makes it go over the transport error rainbow bridge. So, partly through necessity and partly for lulz, I wondered how well a Raspberry Pi B+ would do on ripping CDs. I’ve got an old IDE DVD-R drive in an external 5¼” USB enclosure (huge!). I set about installing abcde, which is about the leanest way of ripping CDs in a terminal that I know. The standard sudo apt-get install abcde didn’t quite come up with all of the options I’d want to use, so I made the mistake of trying this:

sudo apt-get install --install-suggests abcde

Nooooooooooooooooooooooooooo! This horror suggested I install the following:

  abcde acl akonadi-backend-mysql akonadi-backend-postgresql
  akonadi-backend-sqlite akonadi-server alien antiword apache2 apache2-doc
  apache2-mpm-worker apache2-suexec apache2-utils apache2.2-bin
  apache2.2-common apmd aptdaemon aptdaemon-data at atomicparsley auctex
  autoconf autoconf-archive autoconf-doc autoconf2.13 automake automake1.4
  autopoint autotools-dev autotrace avahi-autoipd avahi-daemon bc bind9-host
  binfmt-support binutils-multiarch bsd-mailx bsh bsh-doc bsh-gcj
  ca-certificates-java catdvi cd-discid cdparanoia cdtool chktex chromium
  chromium-browser chromium-inspector chromium-l10n cjet cl-asdf cl-swank
  clisp clisp-dev clisp-doc cm-super cm-super-minimal colord comerr-dev
  common-lisp-controller cpufrequtils cup cups cups-filters cups-pdf
  cups-pk-helper cups-ppdc darcs db5.1-util dbtoepub dc debhelper
  debiandoc-sgml debiandoc-sgml-doc default-jdk default-jdk-doc default-jre
  default-jre-headless devhelp devhelp-common dh-make dhelp diffstat distmp3
  djtools djview-plugin djview4 djvulibre-bin djvulibre-desktop doc-base
  docbook docbook-defguide docbook-dsssl docbook-dsssl-doc docbook-mathml
  docbook-xml docbook-xsl docbook-xsl-doc-html docbook-xsl-saxon dot2tex
  dvidvi dvipng eject elfutils enscript ethtool exim4 exim4-base exim4-config
  exim4-daemon-light exim4-doc-html eximon4 exiv2 eyed3 fam fancontrol feynmf
  ffmpeg finger firebird-dev firebird2.5-common firebird2.5-common-doc
  firebird2.5-examples firebird2.5-server-common flac fontforge fontforge-doc
  fontforge-extras fonts-arphic-bkai00mp fonts-arphic-bsmi00lp
  fonts-arphic-gbsn00lp fonts-arphic-gkai00mp fonts-beng fonts-beng-extra
  fonts-comfortaa fonts-deva fonts-deva-extra fonts-dustin fonts-freefont-otf
  fonts-gfs-artemisia fonts-gfs-baskerville fonts-gfs-complutum
  fonts-gfs-didot fonts-gfs-neohellenic fonts-gfs-olga fonts-gfs-porson
  fonts-gfs-solomos fonts-gubbi fonts-gujr fonts-gujr-extra fonts-guru
  fonts-guru-extra fonts-hosny-amiri fonts-inconsolata fonts-indic
  fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic
  fonts-ipafont-mincho fonts-junicode fonts-knda fonts-knda-extra
  fonts-liberation fonts-linuxlibertine fonts-lohit-beng-assamese
  fonts-lohit-beng-bengali fonts-lohit-deva fonts-lohit-gujr fonts-lohit-guru
  fonts-lohit-knda fonts-lohit-mlym fonts-lohit-orya fonts-lohit-taml
  fonts-lohit-telu fonts-mlym fonts-nakula fonts-navilu fonts-oflb-asana-math
  fonts-orya fonts-orya-extra fonts-pagul fonts-sahadeva fonts-samyak-gujr
  fonts-samyak-taml fonts-sil-gentium fonts-sil-gentium-basic fonts-smc
  fonts-stix fonts-taml fonts-telu fonts-telu-extra
  foomatic-db-compressed-ppds foomatic-db-engine foomatic-db-gutenprint
  foomatic-filters fop fop-doc fragmaster freeglut3 freetds-common
  frei0r-plugins gawk gawk-doc gcc-4.6-doc gcc-doc-base gcj-4.7-base
  gcj-4.7-jre-lib gcr gdal-bin geoip-bin geoip-database geotiff-bin gettext
  gettext-doc gfortran gfortran-4.6 gfortran-4.6-doc ghostscript-cups
  ghostscript-x gimp gimp-data gimp-data-extras gimp-gutenprint
  gimp-help-common gimp-help-en gimp-ufraw gir1.2-atk-1.0 gir1.2-freedesktop
  gir1.2-gdkpixbuf-2.0 gir1.2-gst-plugins-base-0.10 gir1.2-gstreamer-0.10
  gir1.2-gtk-3.0 gir1.2-pango-1.0 gir1.2-vte-2.90 gnome-keyring
  gnome-mime-data gnu-standards gnuplot gnuplot-doc gnuplot-nox gnutls26-doc
  gocr grads graphicsmagick graphicsmagick-dbg graphviz graphviz-doc groff
  gstreamer0.10-alsa gstreamer0.10-doc gstreamer0.10-ffmpeg
  gstreamer0.10-gconf gstreamer0.10-plugins-bad gstreamer0.10-plugins-base
  gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly
  gstreamer0.10-pulseaudio gstreamer0.10-x gutenprint-doc gutenprint-locales
  gv hardening-includes hdf4-tools hdparm heirloom-mailx hp2xx hpijs
  hpijs-ppds hplip hplip-cups hplip-data hplip-doc hplip-gui hspell html2ps
  html2text hylafax-client i2c-tools iamerican icedtea-6-jre-cacao
  icedtea-6-jre-jamvm icedtea-6-plugin icedtea-netx icedtea-netx-common
  icedtea-plugin icoutils id3 id3v2 ienglish-common ijsgutenprint imagemagick
  imagemagick-common imagemagick-doc info2www intltool-debian ir-keytable
  ispell jadetex java-wrappers javascript-common jlex kate-data katepart
  kde-runtime kde-runtime-data kdelibs-bin kdelibs5-data kdelibs5-plugins
  kdepim-runtime kdepimlibs-kio-plugins kdoctools ko.tex-extra-hlfont
  krb5-config krb5-doc krb5-multidev krb5-user lacheck latex-beamer
  latex-cjk-all latex-cjk-chinese latex-cjk-chinese-arphic-bkai00mp
  latex-cjk-chinese-arphic-bsmi00lp latex-cjk-chinese-arphic-gbsn00lp
  latex-cjk-chinese-arphic-gkai00mp latex-cjk-common latex-cjk-japanese
  latex-cjk-japanese-wadalab latex-cjk-korean latex-cjk-thai
  latex-fonts-sipa-arundina latex-fonts-thai-tlwg latex-sanskrit latex-xcolor
  latexdiff latexmk liba52-0.7.4 libaio1 libakonadi-kabc4 libakonadi-kcal4
  libakonadi-kde4 libakonadi-kmime4 libakonadiprotocolinternals1 libamd2.2.0
  libao-common libao4 libapache-pom-java libapm1 libappconfig-perl libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libapt-pkg-perl
  libarchive-zip-perl libarmadillo3 libart-2.0-2 libasm1 libasound2-plugins
  libatk-wrapper-java libatk-wrapper-java-jni libatk1.0-doc libatkmm-1.6-1
  libattica0 libaudio-scrobbler-perl libauthen-ntlm-perl libauthen-sasl-perl
  libautotrace3 libav-tools libavahi-core7 libavalon-framework-java
  libavalon-framework-java-doc libavdevice53 libavfilter2 libavfilter3
  libavformat53 libavresample1 libbabl-0.1-0 libbackport-util-concurrent-java
  libbackport-util-concurrent-java-doc libbatik-java libbcel-java
  libbcel-java-doc libbind9-80 libbonobo2-0 libbonobo2-bin libbonobo2-common
  libbonoboui2-0 libbonoboui2-common libboost-program-options1.49.0
  libbsf-java libc6-dbg libcairomm-1.0-1 libcanberra-gtk-module
  libcanberra-gtk0 libcanberra-gtk3-0 libcanberra-gtk3-module
  libcanberra-pulse libcanberra0 libcap-dev libcap-ng0 libcap2-bin libcdaudio1
  libcddb2 libcdt4 libcf0 libcgraph5 libclass-accessor-chained-perl
  libclass-accessor-perl libclass-load-perl libclass-singleton-perl
  libclone-perl libclucene0ldbl libcommandline-ruby1.8 libcommons-codec-java
  libcommons-io-java libcommons-io-java-doc libcommons-logging-java
  libcommons-logging-java-doc libcommons-parent-java libconfig-inifiles-perl
  libconvert-binhex-perl libcpufreq0 libcrypt-openssl-bignum-perl
  libcrypt-openssl-rsa-perl libcrypt-ssleay-perl libcupscgi1 libcupsdriver1
  libcupsfilters1 libcupsmime1 libcupsppdc1 libcurl3-dbg libcurl4-gnutls-dev
  libcxxtools-dev libcxxtools8 libdap11 libdapclient3 libdapserver7
  libdata-dump-perl libdata-float-perl libdata-integer-perl
  libdata-optlist-perl libdata-page-perl libdatetime-format-mail-perl
  libdatetime-format-w3cdtf-perl libdatetime-locale-perl libdatetime-perl
  libdatetime-timezone-perl libdb-ruby1.8 libdbd-mysql-perl libdbi-perl
  libdbi1 libdbusmenu-qt2 libdevhelp-3-0 libdigest-hmac-perl libdirac-decoder0
  libdiscid0 libdjvulibre-text libdjvulibre21 libdlrestrictions1 libdns88
  libdom4j-java libdom4j-java-doc libdvbpsi7 libdw1 libebml3 libelf1 libelfg0
  libemail-valid-perl libencode-locale-perl libepsilon0 libescpr1
  libexcalibur-logkit-java libexiv2-12 libexpat1-dev libfam0 libfbclient2
  libfbembed2.5 libffcall1 libffi-dev libfile-listing-perl libfile-remove-perl
  libfile-which-perl libfont-afm-perl libfontforge1 libfop-java libfreexl1
  libftdi1 libgail18 libgavl1 libgcc1-dbg libgcj-bc libgcj-common libgcj13
  libgcj13-awt libgcj13-dbg libgck-1-0 libgconfmm-2.6-1c2 libgcr-3-1
  libgcr-3-common libgcrypt11-dev libgcrypt11-doc libgd-gd2-perl
  libgd-graph-perl libgd-graph3d-perl libgd-text-perl libgdal1 libgdraw4
  libgegl-0.2-0 libgeoip1 libgeos-3.3.3 libgeos-c1 libgeotiff-epsg libgeotiff2
  libgettext-ruby1.8 libgettextpo0 libgfortran3-dbg libgimp2.0 libgl1-mesa-dev
  libglademm-2.4-1c2a libglib2.0-bin libglib2.0-dev libglib2.0-doc
  libglibmm-2.4-1c2a libglu1-mesa-dev libgnome2-0 libgnome2-common
  libgnomecanvas2-0 libgnomecanvas2-common libgnomeui-0 libgnomeui-common
  libgnomevfs2-0 libgnomevfs2-bin libgnomevfs2-common libgnomevfs2-extra
  libgnuinet-java libgnujaf-java libgnujaf-java-doc libgnumail-java
  libgnumail-java-doc libgnutls-dev libgnutls-openssl27 libgnutlsxx27
  libgpg-error-dev libgraph4 libgraphics-magick-perl libgraphicsmagick++3
  libgraphicsmagick3 libgraphite3 libgrib2c0d libgssapi-perl libgssrpc4
  libgstreamer-plugins-bad0.10-0 libgstreamer-plugins-base0.10-dev
  libgstreamer0.10-dev libgtk-3-doc libgtk2.0-doc libgtkimageview0
  libgtkmm-2.4-1c2a libgtkmm-3.0-1 libgusb2 libgutenprint2 libgutenprintui2-1
  libgvc5 libgvpr1 libhdf4-0 libhdf4-0-alt libhdf4-alt-dev libhdf4-doc
  libhdf5-7 libhpmud0 libhtml-form-perl libhtml-format-perl libhtml-lint-perl
  libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl
  libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl
  libhttp-message-perl libhttp-negotiate-perl libi2c-dev libib-util libical0
  libice-dev libice-doc libid3-3.8.3c2a libid3-tools libidl0 libidn11-dev
  libieee1284-3 libio-pty-perl libio-socket-inet6-perl libio-socket-ip-perl
  libio-socket-ssl-perl libio-string-perl libio-stringy-perl libiodbc2
  libipc-run-perl libipc-sharedcache-perl libipc-sharelite-perl libisc84
  libisccc80 libisccfg82 libiso9660-8 libjavascriptcoregtk-1.0-0 libjaxen-java
  libjaxme-java libjaxme-java-doc libjaxp1.3-java libjaxp1.3-java-gcj
  libjboss-jmx-java libjdom1-java libjdom1-java-doc libjline-java
  libjline-java-doc libjpeg-progs libjpeg62 libjpeg8-dev libjs-jquery
  libjs-underscore libkabc4 libkadm5clnt-mit8 libkadm5srv-mit8
  libkatepartinterfaces4 libkcal4 libkcalcore4 libkcalutils4 libkcmutils4
  libkdb5-6 libkde3support4 libkdeclarative5 libkdecore5 libkdesu5 libkdeui5
  libkdewebkit5 libkdnssd4 libkemoticons4 libkfile4 libkhtml5 libkidletime4
  libkimap4 libkio5 libkjsapi4 libkjsembed4 libkldap4 libkmediaplayer4
  libkmime4 libkml0 libknewstuff2-4 libknewstuff3-4 libknotifyconfig4
  libkntlm4 libkparts4 libkpathsea6 libkpimutils4 libkprintutils4 libkpty4
  libkrb5-dev libkresources4 libkrosscore4 libktexteditor4 libldap2-dev
  liblensfun-data liblensfun0 liblircclient0 liblist-moreutils-perl
  liblog4j1.2-java liblog4j1.2-java-doc liblqr-1-0 libltdl-dev liblua5.1-0
  liblwp-mediatypes-perl liblwp-protocol-https-perl liblwres80 liblzo2-2
  libmagickcore5 libmagickcore5-extra libmagickwand5 libmail-box-perl
  libmail-dkim-perl libmail-imapclient-perl libmail-sendmail-perl
  libmail-spf-perl libmailtools-perl libmailtransport4 libmath-round-perl
  libmatroska5 libmhash2 libmicroblog4 libmime-tools-perl libmime-types-perl
  libmodule-implementation-perl libmodule-runtime-perl libmpcdec6 libmpeg2-4
  libmtp-common libmtp-runtime libmtp9 libmusicbrainz-discid-perl libmyodbc
  libmysqlclient-dev libmysqlclient16 libmysqlclient18 libneon27-gnutls
  libnepomuk4 libnepomukquery4a libnepomukutils4 libnet-dns-perl
  libnet-domain-tld-perl libnet-http-perl libnet-ident-perl libnet-ip-perl
  libnet-ssleay-perl libnetaddr-ip-perl libnetcdf-dev libnetcdfc++4
  libnetcdfc7 libnetcdff5 libnetpbm10 libnl-route-3-200 libnspr4-0d
  libnss-mdns libnss3-1d libntrack-qt4-1 libntrack0
  libobject-realize-later-perl libodbc1 libodbcinstq4-1 libogdi3.2
  libopencv-core2.3 libopencv-imgproc2.3 libopenraw1 liborbit2 libosp5
  libostyle1c2 libp11-kit-dev libpackage-deprecationmanager-perl
  libpackage-stash-perl libpackage-stash-xs-perl libpam-cap
  libpam-gnome-keyring libpango1.0-doc libpangomm-1.4-1
  libparams-classify-perl libparams-util-perl libparams-validate-perl
  libparse-debianchangelog-perl libparse-recdescent-perl libpathplan4
  libpcre3-dev libpcrecpp0 libperl5.14 libperlio-gzip-perl libphonon4
  libplasma3 libplot2c2 libpod-plainer-perl libpolkit-qt-1-1 libpoppler-glib8
  libpostproc52 libpotrace0 libpq-dev libpq5 libproj0 libpstoedit0c2a
  libptexenc1 libpthread-stubs0 libpthread-stubs0-dev libpulse-mainloop-glib0
  libpython2.6 libqca2 libqca2-plugin-cyrus-sasl libqca2-plugin-gnupg
  libqca2-plugin-ossl libqt3-mt libqt3-mt-mysql libqt3-mt-odbc libqt3-mt-psql
  libqt4-declarative libqt4-declarative-folderlistmodel
  libqt4-declarative-gestures libqt4-declarative-particles
  libqt4-declarative-shaders libqt4-designer libqt4-dev libqt4-dev-bin
  libqt4-help libqt4-opengl libqt4-opengl-dev libqt4-qt3support libqt4-script
  libqt4-scripttools libqt4-sql libqt4-sql-mysql libqt4-sql-psql
  libqt4-sql-sqlite libqt4-test libqt4-xmlpatterns libqtassistantclient4
  libqtwebkit-dev libraptor2-0 librarian0 librasqal3 librdf-storage-mysql
  librdf-storage-postgresql librdf-storage-sqlite librdf0 librecode0
  libregexp-java libresid-builder0c2a librhino-java librhino-java-doc
  libroman-perl librpm3 librpmbuild3 librpmio3 librpmsign1 librrd4
  librrds-perl librtmp-dev libruby1.8 libsane libsane-common libsane-extras
  libsane-extras-common libsane-hpaio libsaxon-java libsaxon-java-doc
  libsaxonb-java libsaxonb-java-doc libscalar-number-perl libsensors4 libserf1
  libservlet2.5-java libsgmls-perl libshp1 libsidplay1 libsidplay2 libsigsegv2
  libslp1 libslv2-9 libsm-dev libsm-doc libsnmp-base libsnmp15 libsocket-perl
  libsocket6-perl libsolid4 libsoprano4 libsp1c2 libspatialite3 libspeexdsp1
  libspiro0 libsqlite0 libsqlite0-dev libsqlite3-dev libssh-4 libssh2-1-dev
  libssl-dev libssl-doc libstreamanalyzer0 libstreams0 libsub-install-perl
  libsub-name-perl libsvn-perl libsvn-ruby1.8 libsvn1
  libsys-hostname-long-perl libsystemd-daemon0 libtar0 libtasn1-3-dev
  libtemplate-perl libtemplate-perl-doc libtemplate-plugin-gd-perl
  libtemplate-plugin-xml-perl libterm-readkey-perl libterm-readline-gnu-perl
  libtext-format-perl libtext-template-perl libthreadweaver4 libtiff-opengl
  libtiff-tools libtiff5 libtntnet-dev libtntnet10 libtool libtool-doc
  libtry-tiny-perl libtwolame0 libudunits2-0 libumfpack5.4.0 libuninameslist0
  libunistring0 libupnp6 libupower-glib1 liburi-perl liburiparser1
  libuser-identity-perl libutempter0 libuuid-perl libva-x11-1 libvcdinfo0
  libvirtodbc0 libvlc5 libvlccore5 libvte-2.90-9 libvte-2.90-common
  libwebkitgtk-1.0-0 libwebkitgtk-1.0-common libwebrtc-audio-processing-0
  libwebservice-musicbrainz-perl libwmf-bin libwmf0.2-7 libwww-perl
  libwww-robotrules-perl libx11-dev libx11-doc libxalan110 libxalan2-java
  libxalan2-java-doc libxau-dev libxcb-composite0 libxcb-doc libxcb-keysyms1
  libxcb-randr0 libxcb-xv0 libxcb1-dev libxdmcp-dev libxdot4 libxerces-c28
  libxerces2-java libxerces2-java-doc libxerces2-java-gcj libxext-dev
  libxext-doc libxml-commons-external-java libxml-commons-resolver1.1-java
  libxml-commons-resolver1.1-java-doc libxml-dom-perl libxml-libxml-perl
  libxml-namespacesupport-perl libxml-parser-perl libxml-perl
  libxml-regexp-perl libxml-rss-perl libxml-sax-base-perl
  libxml-sax-expat-perl libxml-sax-perl libxml-simple-perl libxml2-dev
  libxml2-doc libxml2-utils libxmlgraphics-commons-java libxom-java
  libxom-java-doc libxpp2-java libxpp3-java libxsltc-java libxslthl-java
  libxt-dev libxt-doc libxvmc1 libyajl2 libyaml-tiny-perl libzvbi-common
  libzvbi0 lintian linuxdoc-tools linuxdoc-tools-info linuxdoc-tools-latex
  linuxdoc-tools-text lirc lirc-x lm-sensors lmodern locales-all lsb lsb-core
  lsb-cxx lsb-desktop lsb-graphics lsb-languages lsb-multimedia lsb-printing
  lsb-release lsb-security luatex m4 magicfilter man2html man2html-base
  media-player-info mesa-common-dev mgetty-viewfax mkcue mp3gain mpg321
  mplayer mplayer-doc mscompress mysql-client mysql-client-5.5 mysql-common
  mysql-server-core-5.5 netcdf-bin netcdf-doc netpbm netselect netselect-apt
  normalize-audio ntrack-module-libnl-0 odbc-postgresql odbcinst
  odbcinst1debian2 ogdi-bin oidentd openjade openjdk-6-demo openjdk-6-doc
  openjdk-6-jdk openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib
  openjdk-6-source openprinting-ppds openslp-doc opensp openssl-blacklist
  otf-freefont oxygen-icon-theme paman paprefs patchutils pavucontrol
  pavumeter pax pdf2djvu perl-doc perl-tk perlmagick pfb2t1c2pfb pgf phonon
  phonon-backend-gstreamer phonon-backend-vlc plasma-scriptengine-javascript
  pm-utils po-debconf postgresql postgresql-9.1 postgresql-client
  postgresql-client-9.1 postgresql-client-common postgresql-common
  postgresql-doc-9.1 potrace powermgmt-base preview-latex-style
  printer-driver-all printer-driver-c2050 printer-driver-c2esp
  printer-driver-cjet printer-driver-escpr printer-driver-foo2zjs
  printer-driver-gutenprint printer-driver-hpcups printer-driver-hpijs
  printer-driver-m2300w printer-driver-min12xxw printer-driver-pnm2ppa
  printer-driver-postscript-hp printer-driver-ptouch printer-driver-pxljr
  printer-driver-sag-gdi printer-driver-splix proj-bin proj-data proj-ps-doc
  prosper ps2eps psgml pstoedit pstotext psutils pulseaudio
  pulseaudio-module-gconf pulseaudio-module-x11 pulseaudio-module-zeroconf
  pulseaudio-utils purifyeps python-apt python-apt-common python-apt-dbg
  python-apt-doc python-aptdaemon python-aptdaemon-gtk
  python-aptdaemon.gtk3widgets python-aptdaemon.gtkwidgets python-cairo
  python-chardet python-cups python-cupshelpers python-dbg python-debian
  python-defer python-dev python-distribute-doc python-doc
  python-egenix-mx-base-dbg python-egenix-mx-base-dev python-egenix-mxbeebase
  python-egenix-mxbeebase-doc python-egenix-mxdatetime
  python-egenix-mxdatetime-doc python-egenix-mxproxy python-egenix-mxproxy-doc
  python-egenix-mxqueue python-egenix-mxqueue-doc python-egenix-mxstack
  python-egenix-mxstack-doc python-egenix-mxtexttools
  python-egenix-mxtexttools-doc python-egenix-mxtools
  python-egenix-mxtools-doc python-egenix-mxuid python-egenix-mxuid-doc
  python-egenix-mxurl python-egenix-mxurl-doc python-examples python-eyed3
  python-fontforge python-gconf python-gdal python-gdbm python-gdbm-dbg
  python-gi-dbg python-gi-dev python-glade2 python-gnome2 python-gnome2-doc
  python-gnomekeyring python-gnupginterface python-gobject python-gobject-2
  python-gobject-2-dbg python-gobject-2-dev python-gobject-dbg
  python-gobject-dev python-gst0.10 python-gst0.10-dbg python-gst0.10-dev
  python-gtk2 python-gtk2-doc python-imaging python-imaging-dbg
  python-imaging-doc python-imaging-doc-html python-imaging-doc-pdf
  python-imaging-tk python-imaging-tk-dbg python-kde4 python-libxml2
  python-notify python-pexpect python-pkg-resources python-pycurl
  python-pycurl-dbg python-pyorbit python-pyparsing python-qt4 python-qt4-dbg
  python-qt4-dbus python-renderpm python-renderpm-dbg python-reportlab
  python-reportlab-accel python-reportlab-doc python-setuptools python-sip
  python-sip-dbg python-smbc python-smbus python-software-properties
  python-subversion python-vte python2.6 python2.6-doc python2.6-minimal
  python2.7-dbg python2.7-dev python2.7-doc python2.7-examples python3-gi
  pyzor qt-assistant-compat qt4-designer qt4-dev-tools qt4-doc qt4-doc-html
  qt4-linguist-tools qt4-qmake qt4-qmlviewer radeontool radiance radiance-doc
  radiance-materials raptor2-utils rarian-compat rasqal-utils razor re2c
  read-edid realpath recode redland-utils rhino ri ri1.8 ri1.9.1 rpm
  rpm-common rpm-i18n rpm2cpio rrdtool rtkit ruby ruby-bdb ruby-commandline
  ruby-dev ruby-gettext ruby-locale ruby-open4 ruby-svn ruby-switch
  ruby-text-format ruby1.8 ruby1.8-examples ruby1.9.1-dev sane-utils sensord
  sessioninstaller setcd setserial sgml-data sgmls-doc sgmlspl
  shared-desktop-ontologies sidplay-base slime slpd slv2-jack smistrip
  snmp-mibs-downloader soprano-daemon sp spamassassin spamc spell
  spf-tools-perl sqlite sqlite-doc sqlite3 sqlite3-doc ssl-cert subversion
  subversion-tools svn2cl swaks swath swish++ system-config-printer
  system-config-printer-kde system-config-printer-udev t1utils tcl-tclreadline
  tcl8.4 tcsh tdsodbc tex-common tex-gyre texinfo texinfo-doc-nonfree texlive
  texlive-base texlive-binaries texlive-common texlive-doc-base texlive-doc-en
  texlive-doc-zh texlive-extra-utils texlive-font-utils texlive-fonts-extra
  texlive-fonts-extra-doc texlive-fonts-recommended
  texlive-fonts-recommended-doc texlive-generic-recommended
  texlive-lang-african texlive-lang-all texlive-lang-arabic
  texlive-lang-armenian texlive-lang-cjk texlive-lang-croatian
  texlive-lang-cyrillic texlive-lang-czechslovak texlive-lang-danish
  texlive-lang-dutch texlive-lang-english texlive-lang-finnish
  texlive-lang-french texlive-lang-german texlive-lang-greek
  texlive-lang-hebrew texlive-lang-hungarian texlive-lang-indic
  texlive-lang-italian texlive-lang-latin texlive-lang-latvian
  texlive-lang-lithuanian texlive-lang-mongolian texlive-lang-norwegian
  texlive-lang-other texlive-lang-polish texlive-lang-portuguese
  texlive-lang-spanish texlive-lang-swedish texlive-lang-tibetan
  texlive-lang-vietnamese texlive-latex-base texlive-latex-base-doc
  texlive-latex-extra texlive-latex-extra-doc texlive-latex-recommended
  texlive-latex-recommended-doc texlive-luatex texlive-metapost
  texlive-metapost-doc texlive-pictures texlive-pictures-doc texlive-pstricks
  texlive-pstricks-doc texlive-xetex thailatex time tipa tix tk8.4 tntnet
  tntnet-demos tntnet-doc tntnet-runtime transfig ttf-dejavu ttf-dejavu-extra
  ttf-dustin ttf-indic-fonts ttf-liberation ttf-marvosym ttf-wqy-microhei
  tzdata-java ufraw ufraw-batch unattended-upgrades unixodbc unixodbc-bin
  unixodbc-dev unpaper upower videolan-doc virtuoso-minimal
  virtuoso-opensource-6.1-bin virtuoso-opensource-6.1-common vlc vlc-data
  vlc-nox vlc-plugin-notify vlc-plugin-pulse vorbis-tools vorbisgain
  w3-dtd-mathml w3-recs w3c-dtd-xhtml wamerican weblint-perl wwwconfig-common
  x11proto-core-dev x11proto-input-dev x11proto-kb-dev x11proto-xext-dev xalan
  xapm xaw3dg xfig xfig-doc xfig-libs xfonts-75dpi xhtml2ps xindy xindy-rules
  xorg-sgml-doctools xsane xsane-common xsidplay xsltproc xtrans-dev zip

Eep! That looks like the full TeXLive system, most of QT4, almost every TrueType font ever (plus a font editor), printer drivers, the full Apache webserver setup, MySQL, a couple of web browsers, scanner drivers and OCR programs, a mail server … 2.4 GB of downloads, or over 6 GB installed. And all this for a command line script for ripping CDs.

Eventually, I got by by installing just this:

sudo apt-get install abcde lame eject id3 id3v2 eyed3 normalize-audio vorbisgain mkcue mp3gain libdata-dump-perl flac

Much better. Installed in a couple of minutes. Worked quite well, if not fast — ripped and encoded a 45 minute CD in just under 26 minutes (using lame -V2, which is good enough for me). For setup hints for abcde, abcde: Command Line Music CD Ripping for Linux is a good resource. On a Raspberry Pi, with its single core processor, you probably want to set MAXPROCS=1 in the abcde.conf file, or the encoders will fight for resources and get really slow.

Screamingly fast HWRNG on Arduino Due

Well, look at this:

$ stty -F /dev/ttyACM0 speed 115200 raw cs8
$ rngtest -t 6 < /dev/ttyACM0
  … much snippage …
rngtest: bits received from input: 312368864
rngtest: FIPS 140-2 successes: 15602
rngtest: FIPS 140-2 failures: 16
rngtest: FIPS 140-2(2001-10-10) Monobit: 2
rngtest: FIPS 140-2(2001-10-10) Poker: 2
rngtest: FIPS 140-2(2001-10-10) Runs: 8
rngtest: FIPS 140-2(2001-10-10) Long run: 4
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=837.317; avg=1168.033; max=1948.060)Kibits/s
rngtest: FIPS tests speed: (min=16.834; avg=27.779; max=77.221)Mibits/s
rngtest: Program run time: 271917796 microseconds

Over a megabit/second of decent quality random data. This is from an Arduino Due, which has an Atmel SAM3X8E ARM Cortex-M3 microcontroller on board. I hadn’t found much use for this board previously, as it fell between a regular 8-bit Arduino and my (many!) Raspberry Pis.

This changed when I found out about Walter Anderson’s Entropy library, which uses µc timer jitter as a source of entropy. Originally designed as a slow but true source of random integers on the Atmel AVR chips, it’s been extended to use the SAM3X8E‘s built-in hardware RNG. Since the Due has a native USB port, you’re not limited to standard baud rates.

Here’s the code, trivially modified from one of Walter’s examples:

// Generate_Random_Bytes_Due - speedy demo of Arduino Due's HWRNG
// based on Generate_Random_Bytes, for Entropy, an Arduino library.
// Copyright 2012 by Walter Anderson
//  modified - scruss - 2014-08-13
// remember to reconnect to native USB port

#include <Entropy.h>

void setup() {
  while (!SerialUSB) {
    ; // wait for serial port to connect.

void loop() {
  uint16_t r = Entropy.random();

It’s a minor pain to have to reconnect the USB cable to the other port on the Arduino Due after programming, but it’s worth it just to see an 84 MHz µc belting out random bytes 37½% faster than an 800 MHz Raspberry Pi

Pleasantly futile: Dogecoin digging on the Raspberry Pi

I don’t recommend this in any way, but cpuminer will run on the Raspberry Pi. It’s pretty easy to build:

sudo apt-get install build-essential libcurl4-openssl-dev automake git
git clone https://github.com/pooler/cpuminer.git
cd cpuminer/
./configure CFLAGS="-march=armv6 -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -ffast-math -ffast-math -O3"
sudo make install

I’m not convinced that the l33t funroll-l00pz CFLAGS are strictly necessary. Yes, you still only get 0.34 khash/s on a stock Raspberry Pi — which means it would take several days to earn 1Đ (or roughly 0.1¢).

I’m trying to find the most futile computer on which to dig Đ. My BeagleBone Black is (somewhat surprisingly) more than 2× as fast, once you replace the very limited Ångström distribution with Debian. I’m really disappointed that I can’t build cpuminer on my Intel Galileo. Its Yocto distribution is extremely small yet confusing. As the board runs burny hot under no load, I wonder how quickly it would glow white-hot under 100% CPU load.

So that’s how the Raspberry Pi camera fits in the CamdenBoss housing …


The CamdenBoss Raspberry Pi Camera Enclosure (data sheet, suppliers: RPI CAMERA BOARD – RASPBERRY-PI – ADD-ON BRD, CAMERA MODULE, RASPBERRY PI | Newark element14 Canada, MCM Electronics Carbon Raspberry Pi Camera Case 83-15493 – Micro Center) comes with no instructions. Maybe the lighter coloured ones are easier to work out, but on the faux-carbon one I bought, the little guide slots the board has to slide into are very hard to see.

Given all the warnings about static, I was a little too careful trying to install the camera into the housing. Slip open the camera case, then put the board in at an angle with one side in one slot, then (with a bit more force than I’d like) spring or flex the housing so the other side of the board can click into place. You have to make sure that both sides are fully engaged in the slots before the cover will slide back on.

So here it is, all set up:


Oh, sorry;  should’ve warned you about the bright pink case and the awesome/appalling Lisa Frank sticker. The sticker is in no way to cover up where I cut the wrong place for the camera connector, nope nope nope …

Processing 2.1 + Oracle Java + Raspberry Pi + Serial + Arduino = ☺

Update for Raspberry Pi 2/Processing 2.2.1/Processing 3.0.5: Raspbian now ships with Java 8, and Processing only likes Java 7. oracle-java7-jdk is still in the repos, so install that, and follow the instructions below. It’s a bit flakey, but when it runs, runs quite fast on the Raspberry Pi 2. You might have more luck running Processing.js or p5.js in the browser.

With Sun Oracle hardfloat Java now available, Processing now runs at a decent clip on the Raspberry Pi. My old instructions are now very obsolete. Here are current, tested instructions for installing it under Raspbian.

[This is a particular solution to installing a Serial/Firmata-enabled Processing 2.1 distribution on a Raspberry Pi. Processing still has issues with other aspects of visual programming (particularly video) that I’m not addressing here.]

A lot of software is installed here, and much of it depends on previous steps. Don’t jump in mid-way and expect it to work.

Update the system

Always a good plan if you’re doing major upgrades:

sudo apt-get update
sudo apt-get dist-upgrade

Install Sun Oracle Java

sudo apt-get install oracle-java7-jdk

Check if the right version is installed as default: java -version should give

java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)

If you get anything else, you need to make Sun Oracle’s version the default:

sudo update-alternatives --config java

Download & Install Processing

Go to Download \ Processing.org and get the Linux 32-bit version.  It’s big; about 100 MB. I’m going to install it in my home directory, so the base path will be ~/processing-2.1. Extract it:

tar xvzf processing-2.1-linux32.tgz

Now you have to remove the included x86 Java runtime, and replace it with the Raspberry Pi’s armhf one:

rm -rf ~/processing-2.1/java 
ln -s /usr/lib/jvm/jdk-7-oracle-armhf ~/processing-2.1/java

You should now have a Processing installation that will run, but there’s some more we need to get serial and Arduino support.

Install the  java Simple Serial connector

Download jSSC-2.6.0-Release.zip and extract it:

unzip jSSC-2.6.0-Release.zip

Now overwrite the jssc.jar that ships with Processing with the one you just downloaded:

mv jSSC-2.6.0-Release/jssc.jar ~/processing-2.1/modes/java/libraries/serial/library/

(You can remove the jSSC folder now: rm -r jSSC-2.6.0-Release)

Test Processing’s serial support

You’re almost there! Fire up Processing:


and try Perhaps the World’s Most Boring Processing Sketch:

// Example by Tom Igoe

import processing.serial.*;

// The serial port
Serial myPort;

// List all the available serial ports

Screenshot from 2014-01-07 20:08:32When this runs (it’s a little slow), you should get a single line of output, which should start /dev/tty___:


(I have an Arduino Leonardo attached, which usually appears as an ACM device.)

Installing Arduino/Firmata support

(I’m not going to go into uploading Firmata onto your Arduino here. All I can recommend is that you use the newest version at firmata/arduino, rather than the old code bundled with your Arduino distribution.)

Exit Processing, and download processing-arduino.zip from firmata/processing. Extract it into your Processing sketchbook:

unzip processing-arduino.zip -d ~/sketchbook/libraries/

For tedious reasons, you also have to rename one of the files:

mv  ~/sketchbook/libraries/arduino/library/Arduino.jar  ~/sketchbook/libraries/arduino/library/arduino.jar

Start up Processing again, and  save Most Probably the World’s Second Least Interesting Processing Program™:

import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int ledPin = 13;

void setup()
  arduino = new Arduino(this, Arduino.list()[0], 57600);
  arduino.pinMode(ledPin, Arduino.OUTPUT);

void draw()
  arduino.digitalWrite(ledPin, Arduino.HIGH);
  arduino.digitalWrite(ledPin, Arduino.LOW);

Screenshot from 2014-01-07 21:13:54
What this sketch does is emulate the µC’s “Hello World” program, Blink. It flashes the board’s LED once per second. Boring? Yes. But if it worked, you have a working Processing 2.1 installation on your Raspberry Pi. Go forth and make more interesting things.
(Props to bitcraftlab/wolfing for the basic outline for installing Processing, and for samaygoenka for the prodding needed to update and test the Processing installation process. If you’re still stuck, the Processing 2.0 Forum and the Raspberry Pi Forum are good places to ask.)

My Raspberry Pi talks to my Oscilloscope

… it complains that the oscilloscope is always making waves.


Ahem. Anyway. I have a Rigol DS1102E 100 MHz Digital Oscilloscope. For such a cheap device, it’s remarkable that you can control it using USB Test & Measurement Class commands. I’d been wanting to use a Raspberry Pi as a headless data acquisition box with the oscilloscope for a while, but Raspbian doesn’t ship with the usbtmc kernel module. I thought I was stuck.

Alex Forencich turned up in the forum with an all-Python solution: Python USBTMC (source: alexforencich / python-usbtmc). I got this working quite nicely today on both the Raspberry Pi and my Ubuntu laptop. Here’s how I installed it:

  1. Check your device’s USB code with lsusb:
    $ lsusb
    Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
    Bus 001 Device 004: ID 1ab1:0588 Rigol Technologies DS1000 SERIES
  2. Ensure that libusb-1.0 is installed:
    sudo apt-get install libusb-1.0-0
  3. Create a new group, usbtmc:
    sudo groupadd usbtmc
  4. Add yourself to this group:
    sudo usermod -a -G usbtmc pi
  5. As root, create a file /etc/udev/rules.d/usbtmc.rules. You’ll need to put in your device’s ID values:
    # USBTMC instruments
    # Rigol DS1100 – ID 1ab1:0588 Rigol Technologies DS1000 SERIES
    SUBSYSTEMS==”usb”, ACTION==”add”, ATTRS{idVendor}==”1ab1″, ATTRS{idProduct}==”0588″, GROUP=”usbtmc”, MODE=”0660″
    (all of the SUBSYSTEMS to MODE= should be one one line)
  6. Download and install the latest pyusb (Raspbian version is rather old):
    git clone https://github.com/walac/pyusb.git
    cd pyusb
    python setup.py build
    sudo python setup.py install
  7. Now get python-usbtmc:
    git clone https://github.com/alexforencich/python-usbtmc.git
    cd python-usbtmc
    python setup.py build
    sudo python setup.py install
  8. For this simple demo, you’ll need to convert the USB vendor IDs to decimal:
    0x1ab1 = 6833
    0x0588 = 1416
  9. Now, start python as root (sudo python) then type:
    import usbtmc
    instr =  usbtmc.Instrument(6833, 1416)
  10. This should return something like:
    Rigol Technologies,DS1102E,DS1EB13490xxxx,

If you get the status line, congratulations! You now have a fully working usbtmc link. I haven’t had much time to play with this, but I know I can make really nice screenshots to an attached USB drive using the command: instr.write(“:HARDcopy”). Many more commands can be found in the DS1000D/E Programming Guide, available on Rigol‘s site.

I had a couple of problems, though:

  1. The library seems to need root privileges, despite the udev rule thing. After creating the udev rule, you will need to reboot. This is the simplest way of getting it to work without being root.
  2. Reading from the ‘scope’s memory  chokes on non-UTF8 characters. If I do:
    rawdata = instr.ask(“:WAV:DATA? CHAN1″)[10:]
    I get a lengthy Python error which ends:

    File “/usr/lib/python2.7/encodings/utf_8.py”, line 16, in decode
        return codecs.utf_8_decode(input, errors, True)
    UnicodeDecodeError: ‘utf8′ codec can’t decode byte 0x99 in position 10: invalid start byte
    I have no idea what that means, or how to fix it. Alex suggested using ask_raw instead of ask, and the data comes through with no complaints.

I’ve still got to work my way through the Rigol’s data format, but other people have done that before:

  1. Controlling a Rigol oscilloscope using Linux and Python | C i b o M a h t o . c o m
  2. Ken Shirriff’s blog: Four Rigol oscilloscope hacks with Python

I’ll post any updates here, along with the Raspberry Pi forum topic: USB Test & Measurement class (usbtmc) driver?

Incidentally, if you’re working with WFM data dumps from the Rigol ‘scopes (and you should, because they make storing data to USB drives quick), mabl/pyRigolWFM is basically magic. Not merely can it describe and decode those binary files, it can do pretty graphics with no thought required:

made by pyRigolWFMHat tip for the mention: MP3 Options & Oscilloscope Interfacing For Raspberry Pi @Raspberry_Pi #piday #raspberrypi « adafruit industries blog

Update, 2013-12-20: I’ve successfully managed to run most of Ken’s examples with Alex’s code. The major modification you have to do is use ask_raw instead of ask. Example code shown below:

# -*- coding: utf-8 -*-

Download data from a Rigol DS1102E oscilloscope and graph with matplotlib
         using  Alex Forencich's python-usbtmc pure python driver


scruss - 2013-12-20

based on
Download data from a Rigol DS1052E oscilloscope and graph with matplotlib.
By Ken Shirriff, http://righto.com/rigol

which in turn was
Based on http://www.cibomahto.com/2010/04/controlling-a-rigol-oscilloscope-using-linux-and-python/
by Cibo Mahto.

import usbtmc
import time
import numpy
import matplotlib.pyplot as plot

# initialise device
instr =  usbtmc.Instrument(0x1ab1, 0x0588) # Rigol DS1102E

# read data
instr.write(":WAV:POIN:MODE RAW")
# first ten bytes are header, so skip
rawdata = instr.ask_raw(":WAV:DATA? CHAN1")[10:]
data_size = len(rawdata)

# get metadata
sample_rate = float(instr.ask_raw(':ACQ:SAMP?'))
timescale = float(instr.ask_raw(":TIM:SCAL?"))
timeoffset = float(instr.ask_raw(":TIM:OFFS?"))
voltscale = float(instr.ask_raw(':CHAN1:SCAL?'))
voltoffset = float(instr.ask_raw(":CHAN1:OFFS?"))

# show metadata
print "Data size:      ", data_size
print "Sample rate:    ", sample_rate
print "Time scale:     ", timescale
print "Time offset:    ", timeoffset
print "Voltage offset: ", voltoffset
print "Voltage scale:  ", voltscale

# convert data from (inverted) bytes to an array of scaled floats
# this magic from Matthew Mets
data = numpy.frombuffer(rawdata, 'B')
data = data * -1 + 255
data = (data - 130.0 - voltoffset/voltscale*25) / 25 * voltscale

# creat array of matching timestamps
time = numpy.linspace(timeoffset - 6 * timescale, timeoffset + 6 * timescale,

# scale time series and label accordingly
if (time[-1] < 1e-3):
    time = time * 1e6
    tUnit = "µS"
elif (time[-1] < 1):
    time = time * 1e3
    tUnit = "mS"
    tUnit = "S"

# Plot the data
plot.plot(time, data)
plot.title("Oscilloscope Channel 1")
plot.ylabel("Voltage (V)")
plot.xlabel("Time (" + tUnit + ")")
plot.xlim(time[0], time[-1])

Faster MP3 options for Raspberry Pi

One thing the Raspberry Pi is not good at is encoding MP3s at any great speed. At best (using lame) you might get slightly better than 2× real time playback. If you’re using your Raspberry Pi to transcode to another format, that might be slow enough (with other system overhead) to make the output stutter.

While it would be nice to have the GPU as a general media encoder, we’re not there yet. If you must encode mp3s quickly on a Raspberry Pi, there are a couple of options:

Please note that both of these are based on the old ‘8hz’ mp3 encoder, which was a fairly literal interpretation of the original Fraunhofer code. They only start producing okay sounding files at high bitrates.

If you need to decode mp3s quickly, MAD is pretty good: http://www.underbit.com/products/mad. It’s in the repos as ‘madplay’.

Faster Java on Raspberry Pi

With the official announcement of Oracle Java on Raspberry Pi, Java just got usable on the Raspberry Pi. It’s still not super-fast, but I’m seeing ~10× speedup over OpenJDK.

To install it (on Raspbian):

sudo apt-get update && sudo apt-get install oracle-java7-jdk
sudo update-java-alternatives -s jdk-7-oracle-armhf

By way of a baseline, here are SciMark 2.0 results on OpenJDK:

$ java -classpath ./scimark2lib.jar jnt.scimark2.commandline -large

SciMark 2.0a

Composite Score: 2.4987047508570632
FFT (1048576): 1.5550941987343943
SOR (1000x1000):   5.32030759023185
Monte Carlo : 0.6005590152716936
Sparse matmult (N=100000, nz=1000000): 2.3584905938878946
LU (1000x1000): 2.6590723561594847

java.vendor: Sun Microsystems Inc.
java.version: 1.6.0_27
os.arch: arm
os.name: Linux
os.version: 3.6.11+

Here’s what the Oracle JDK cranks out (bigger numbers → better):

$ java -classpath ./scimark2lib.jar jnt.scimark2.commandline -large

SciMark 2.0a

Composite Score: 14.94896390647437
FFT (1048576): 6.953238474333376
SOR (1000x1000):   33.91437255527547
Monte Carlo : 8.869794361002157
Sparse matmult (N=100000, nz=1000000): 9.81896340073432
LU (1000x1000): 15.188450741026523

java.vendor: Oracle Corporation
java.version: 1.7.0_40
os.arch: arm
os.name: Linux
os.version: 3.6.11+

That’s a tidy increase, and might make Processing and Arduino much easier to work with.

(It’s still not tremendously fast, though. My i7 quad-core has a composite score of nearly 1450 …)

BeagleBone Black: slow as a dog

All benchmarks are artificial, but this one had me scratching my head. One hears  that the BeagleBone Black is screamingly fast compared to the Raspberry Pi; faster, newer processor, blahdeblah, mcbtyc, etc. I found the opposite is true.

So I buy one at the exceptionally soggy Toronto Mini Maker Faire. Props to the CircuitCo folks, they are easy to set up: just a mini-USB cable provides power and virtual network shell. And BoneScript — an Arduino-like JavaScript library — is very clever indeed. But I need to see if this thing has any grunt, and so I need a benchmark.

After hearing about the business-card raytracer, I thought it would be perfect. I compiled it on both machines with:

g++  -Ofast   card.cpp   -o card

and then ran it with:

time ./card > /dev/null

The results are … surprising:

  • Raspberry Pi: 4′ 15″
  • BeagleBone Black: 12′ 39″ → 3× slower

(In comparison, my i7 quad-core laptop runs it in 8½ seconds.)

I don’t have any explanation why the BBB is so much slower. It’s almost as if the compiler isn’t fully optimizing under Ångström Linux.

Raspberry Pi: system info

$ uname -a
Linux rpi 3.6.11+ #538 PREEMPT Fri Aug 30 20:42:08 BST 2013 armv6l GNU/Linux

$ cat /proc/cpuinfo 
Processor    : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS    : 697.95
Features    : swp half thumb fastmult vfp edsp java tls 
CPU implementer    : 0x41
CPU architecture: 7
CPU variant    : 0x0
CPU part    : 0xb76
CPU revision    : 7

Hardware    : BCM2708
Revision    : 000f

BeagleBone Black: system info

# uname -a
Linux beaglebone 3.8.13 #1 SMP Tue Jun 18 02:11:09 EDT 2013 armv7l GNU/Linux
# cat /proc/cpuinfo 
processor    : 0
model name    : ARMv7 Processor rev 2 (v7l)
BogoMIPS    : 297.40
Features    : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls 
CPU implementer    : 0x41
CPU architecture: 7
CPU variant    : 0x3
CPU part    : 0xc08
CPU revision    : 2

Hardware    : Generic AM33XX (Flattened Device Tree)
Revision    : 0000

Both boards are running at stock speed.

Update: I’ve tried with an external power supply, and checked that the processor was running at full speed. It made no difference. I suspect that Raspbian enables armhf floating point by default, while Ångström needs to be told to use it.

“Well, that was unexpected…”: The Raspberry Pi’s Hardware Random Number Generator

Most computers can’t create true random numbers. They use a formula which makes a very long stream of pseudo-random numbers, but real randomness comes from thermal noise in analogue components. The Raspberry Pi has such a circuit in its SoC, as it helps making the seed data for secure transactions. It was only recently that a driver for this circuit was supplied. To enable it (on Raspbian):

  1. Make sure your system is up to date with
    sudo apt-get update
    sudo apt-get -y dist-upgrade
    sudo rpi-update
    and, if necessary, reboot.
  2. Install the module:
    sudo modprobe bcm2708-rng
  3. To make sure it’s always loaded, add the following line to /etc/modules (editing as root):
  4. For some RNG-related stuff, install rng-tools:
    sudo apt-get install rng-tools

The /dev/hwrng device should now be available, but can only be read by the root user.

What random looks like


Random data look pretty dull. Here are random RGB values made with:

sudo cat /dev/hwrng  | rawtoppm -rgb 256 256 | pnmtopng > random$(date +%Y%m%d%H%M%S).png

(you’ll need to install the netpbm toolkit to do this.)

What random sounds like

Two short WAV samples of, well, noise:

Yup, sounds like static. It was made with the rndsound.sh script. You’ll need to install sox to run it.

This is not random

If it sounds like static, and even if it sometimes looks like static, it may not actually be true random noise. An infamous case of a pseudo random number generator being not very random at all was RANDU, which at first glance appeared to produce nearly random results, but close study showed it to be very predictable.

I wrote (what I think to be) a C implementation of RANDU: randu.c. While it produces appropriately random-sounding audio data (randu17.wav), if you output it as an image:

randu17_rgbThose stripes are a giveaway; there should be no order in the output. (Then again, I have no idea if I’ve implemented RANDU correctly.) Testing random data is hard, then — you really need a barrage of tests, and even some of them might fail even for truly random output. Thankfully, when you installed rngtools, it included rngtest, a simple checker for random data:

sudo cat /dev/hwrng | rngtest -c 1000
rngtest 2-unofficial-mt.14
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests…
rngtest: bits received from input: 20000032
rngtest: FIPS 140-2 successes: 1000
rngtest: FIPS 140-2 failures: 0
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 0
rngtest: FIPS 140-2(2001-10-10) Runs: 0
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=67.969; avg=921.967; max=1953125.000)Kibits/s
rngtest: FIPS tests speed: (min=842.881; avg=3208.336; max=6407.890)Kibits/s
rngtest: Program run time: 27658884 microseconds

We were lucky that none of the tests failed for that run; sometimes there are a few failures. RANDU, on the other hand fares very badly:

./randu 17  | rngtest -c 1000
rngtest 2-unofficial-mt.14
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests…
rngtest: bits received from input: 20000032
rngtest: FIPS 140-2 successes: 0
rngtest: FIPS 140-2 failures: 1000
rngtest: FIPS 140-2(2001-10-10) Monobit: 730
rngtest: FIPS 140-2(2001-10-10) Poker: 1000
rngtest: FIPS 140-2(2001-10-10) Runs: 289
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=45.630; avg=14255.221; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=23.694; avg=154.238; max=176.606)Mibits/s
rngtest: Program run time: 141071 microseconds

See? Lots of failures there. It’s hardly random at all. If you really want to get out testing randomness, there are the dieharder tests. They takes ages to run, though.

(Note: newish Intel machines also have a real hardware RNG in the shape of Rdrand.)

Compose yourself, Raspberry Pi!

Years ago, I worked in multilingual dictionary publishing. I was on the computing team, so we had to support the entry and storage of text in many different languages. Computers could display accented and special characters, but we were stuck with 8-bit character sets. This meant that we could only have a little over 200 distinct characters display in the same font at the same time. We’d be pretty much okay doing French & English together, but French & Norwegian started to get a little trying, and Italian & Greek couldn’t really be together at all.

We were very fortunate to be using Sun workstations in the editorial office. These were quite powerful Unix machines, which means that they were a fraction of the speed and capabilities of a Raspberry Pi. Suns had one particularly neat feature:

Compose_key_on_Sun_Type_5c_keyboard(source: Compose key, Wikipedia.)

That little key marked “Compose”  (to the right of the space bar) acted as a semi-smart typewriter backspace key: if you hit Compose, then the right key combination, an accented character or symbol would appear. Some of the straightforward compose key sequences are:

  Compose +    
Accent First key Second key Result Example
Acute e é café
Grave ` a à déjà
Cedilla , c ç soupçon
Circumflex ^ o ô hôtel
Umlaut u ü küche
Ring o a å Håkon
Slash / L Ł Łukasiewicz
Tilde ~ n ñ mañana

Like every (non-embedded) Linux system I’ve used, the Raspberry Pi running Raspbian can use the compose key method for entering extra characters. I’m annoyed, though, that almost every setup tutorial either says to disable it, or doesn’t explain what it’s for. Let me fix that for you …


Run raspi-config

sudo raspi-config

and go to the configure_keyboard “4 Internationalisation Options” → “I3 Change Keyboard Layout” section. Your keyboard’s probably mostly set up the way you want it, so hit the Tab key and select <Ok> until you get to the Compose key section:

raspi-config: Compose key selectionChoose whatever is convenient. The combined keyboard and trackpad I use (a SolidTek KB-3910) with my Raspberry Pi has a couple of “Windows® Logo” keys, and the one on the right works for me. Keep the rest of the keyboard options the same, and exit raspi-config. After the message

Reloading keymap. This may take a short while
[ ok ] Setting preliminary keymap...done.

appears, you now have a working Compose key.

Using the Compose key

raspi-config hints (‘On the text console the Compose key does not work in Unicode mode …’) that Compose might not work everywhere with every piece of software. I’ve tested it across quite a few pieces of software — both on the text console and under LXDE — and support seems to be almost universal. The only differences I can find are:

  • Text Console — (a. k. a. the texty bit you see after booting) Despite raspi-config’s warning, accented alphabetical characters do seem to work (é è ñ ö ø å, etc). Most symbols, however, don’t (like ± × ÷ …). The currency symbol for your country is a special case. In Canada, I need to use Compose for and £, but you’ve probably got a key for that.
  • LXDE — (a. k. a. the mousey bit you see after typing ‘startx’) All characters and symbols I’ve tried work everywhere, in LXTerminal, Leafpad, Midori, Dillo (browser), IDLE, and FocusWriter (a very minimal word processor).
Special characters in Python's IDLE
Special characters in Python’s IDLE
Some Compose key sequences — Leafpad
Some Compose key sequences — Leafpad

To find out which key sequences do what, the Compose key – Wikipedia page is a decent start. I prefer the slightly friendlier Ubuntu references GtkComposeTable and Compose Key, or the almost unreadable but frighteningly comprehensive UTF-8 (Unicode) compose sequence reference (which is essentially mirrored on your Raspberry Pi as the file /usr/share/X11/locale/en_US.UTF-8/Compose). Now go forth and work that Compose key like a boß.

(If you’re on a Mac and feeling a bit left out, you can do something similar with the Option key. Here’s how: Extended Keyboard Accent Codes for the Macintosh. On Windows®? Out of luck, I’m afraid WinCompose!)

Hint: I don’t do this for the money …

I don’t know why getting an e-mail like this one would disturb me so much:

Hi Stewart,

Just a quick reminder message – I’m currently working with [REDACTED], a top electronics and engineering tech company, and we’re still interested in collaborating with you!

We can provide bespoke content by [REDACTED]‘s own tech copywriters to give you something relevant for your readers, based on a topic that you’d like us to write about. We can also offer a $25 voucher to purchase any product of that value or less from the [REDACTED] website (http://www.[REDACTED].com/) which you could then use and review.

If you’re interested, I can send over some rough content ideas for you to have a look at, and you can let us know what grabs you.

Look forward to hearing from you!


It’s not spam; I’ve had this offer before via another channel. I can’t see why anyone would want someone else’s text under their own byline. Running this blog costs me a trivial amount of money, but I’m okay with that. Monetizing, SEO, sticky eyeballs (I’m showing my age …): feh. All I ever wanted to do with this blog is write my own drivel without someone else’s noise polluting the page.

X11-Basic: Compiler Insanity!

Screen Shot 2013-03-11 at 22.13.31Markus Hoffmann has been very helpful with getting X11-Basic running on the Raspberry Pi. Remember how I said that the simple Mandelbrot Set test took nearly 1¼ hours to run using the interpreter? How about 2′ 6″ when compiled? That’s a speedup of 35 times! What you need to do is:

xbc -virtualm -o mandel-simple mandel-simple.bas

The “-virtualm” bit is the secret key to speed. Without it, the compiled code is a bit faster than interpreted.

If you’re running from the source code posted to SourceForge yesterday, you might want to replace xb2csol.h with this new xb2csol.h. It’s supposed to help with the compiled code. Just make clean; make; sudo make install to replace the code.

Running X11-Basic (almost perfectly) on Raspberry Pi

Update: Markus Hoffmann uploaded a new version of X11Basic-1.20.tar.gz to SourceForge that addresses most of these problems. I’ve edited the article to remove the obsolete bits.

More than 20 years ago, I really liked GFA-Basic. It ran blindingly fast on the Atari ST, and when it didn’t crash on the Amiga, it ran blindingly fast there too. I even wrote a review of it for comp.sys.amiga.programmer, which you can read to this day in all its textual glory. One of the e-mail addresses in that article still works, too.

I still sometimes think in BASIC, and there is much wringing of hands (not by me, really) that there isn’t a good interpreter for Raspbian on the Raspberry Pi. So when I found X11-Basic — a cross-platform GFA-Basic-like system — I had to take a look.

While I have managed to get X11-Basic demos to run, I have to say it’s not running super well. I’ll show you how to install X11-Basic 1.20 and get it (mostly) running, but it’s a bit rough on the ARM. Incidentally, these instructions also work on Ubuntu 12.mumble LTS on x86.

First, you need to install some (okay, a lot of) packages:

sudo apt-get install libreadline-dev tcsh libncurses5-dev xutils-dev libc6-dev libsdl1.2-dev libtool

Now download and extract the package:

tar xvzf X11Basic-1.20.tar.gz
cd X11Basic-1.20

For X11Basic-1.20, you have to issue an extra command before the standard ‘./configure ; make ; make install‘ sequence:

sudo mkdir -p /usr/local/share/man/man1
sudo make install

This is enough to make a working xbasic interpreter. I made some screenshots of some of the graphics demos —

Screen Shot 2013-03-08 at 16.34.51 Screen Shot 2013-03-08 at 14.59.37 Screen Shot 2013-03-08 at 14.57.21 Screen Shot 2013-03-08 at 14.54.08 Screen Shot 2013-03-08 at 14.49.48As you can see, there’s some screen corruption, but most demos just worked. Incidentally, the Mandelbrot one took almost 1¼ hours to run. Took me right back, that did (or it would have, if I hadn’t been outside bombing about in the slush on my bicycle while it churned away).

In order to see just how fast the interpreter is, I ran the formerly fearsome Personal Computer World Benchmark #8 under X11-Basic. PCW#8 used to bring 8-bit home computers to their knees, typically taking more than a minute to run. Here’s the code, indented a bit and with a timing wrapper added:

	LET start=TIMER
	LET K=0
	LET K=K+1
	LET A=K^2
	IF K<1000
		GOTO L30

(yeah, GFA-style BASIC isn’t too pretty …)

It takes about ¼s to run. The old BBC B was supposed to take about 50s. By comparison, X11-Basic on a manky old dual-core Atom took 0.04s.

The native compiler xbc seems to work. To make a standalone binary of the above code, you do:

xbc -o PCWBenchmark PCWBenchmark.xbas

The compiled binary runs roughly twice as fast as the interpreted code. Not blazing fast, but a useful increase.

Unfortunately, the bytecode compiler xbbc doesn’t actually do anything on the Raspberry Pi yet. So here I leave it up to you to play with X11-Basic, and see what it can and can’t do.

A Murder of Crows on your Raspberry Pi with Boodler

Boodler is rather fun. It generates ambient music based on user-defined or downloaded ‘soundscapes’. If you’ve got a modern (HTML5/Opus-capable) browser, you can hear a streaming demo here: http://repeater.xiph.org:8000/clock.opus. It’s using the FM3 Buddha Machine samples in this demo, but it can run lots more: a tree full of crows, a thunderstorm, dripping water, …

It’s pretty easy to run on a Raspberry Pi running a recent version of Raspbian. The only technical glitch I had was that there’s something deeply confused about ALSA sound handling on the Raspberry Pi. I’m sure it’ll get fixed soon, but for now, you have to use PulseAudio. (If you want to read about my ALSA woes, go here.)

The installation prerequisites are simple:

sudo apt-get install pulseaudio pulseaudio-utils libpulse-dev python-dev

Now download and configure Boodler:

wget http://boodler.org/dl/Boodler-2.0.4.tar.gz
tar xvzf Boodler-2.0.4.tar.gz
cd Boodler-2.0.4
python setup.py build

It takes a while to do this, but make sure it does something useful when it’s building the various sound drivers. You don’t want it to say:

skipping 'boodle.cboodle_pulse' extension

If it says that, you haven’t installed Pulseaudio. Go back and check your apt-get line.

Once it’s built, now install it:

sudo python setup.py install

Now test it:

boodler --hardware --output pulse --testsound

Not merely should you get some pleasant tones from your Raspberry Pi’s audio, but you sound get some informative and non-threatening terminal output. Mine looks like:

Boodler: PulseAudio sound driver.
 PulseAudio library: 2.0.0.
 Sample rate is 44100 fps.
 Samples are 16-bit little-endian.
 Buffer size is 32768.
 21:37:46 (root) Running "Boodler test sound"

If that works, let’s get those crows a-cawin’. Download the soundscapes you need:

boodle-mgr install http://boodler.org/lib/org.boodler.old.crow.1.0.boop
boodle-mgr install http://boodler.org/lib/com.eblong.zarf.crows.1.0.boop

and run it:

boodler --output pulse com.eblong.zarf.crows/ParliamentOfCrows

Crows everywhere!

I really like the Buddha Machine samples. It’s quite big (> 80 MB), so this next set will take a while to download:

boodle-mgr install  http://boodler.org/lib/com.azulebanana.buddhamachine.1.5.1.boop
boodle-mgr install http://boodler.org/lib/com.azulebanana.buddhaagent.1.5.1.boop

It’s worth the wait:

boodler --output pulse com.azulebanana.buddhaagent/ChangingLoops

Boodler has tons of options, prebuilt packages, and instructions to build your own: Boodler Documentation.

One thing I’ve tried to get working, but failed, is streaming from Boodler via icecast. Sure, I can install and run it, it’s just that the results are, um, undesirable. If you want to have a play, here’s how to install icecast:

sudo apt-get install icecast2 ices2 libshout3-dev

Icecast will configure itself, and ask for a couple of passwords. You’ll have to rebuild and reinstall Boodler for it to catch the new configuration. You can then try streaming:

boodler --output shout --define shout-password=mypassword --define shout-mount='/boodler-buddha.ogg' com.azulebanana.buddhaagent/ChangingLoops

If you open a web browser at this address http://raspberrypi:8000/ you should see a config page listing your boodler-buddha.ogg stream. Click on the M3U link next to it, and your streaming music player should start making a joyful noise …

… except in my case, something went very wrong, and it started to produce industrial ultra-glitch nightmare noise: boodler-streaming_test-fail. I’m sure it’s fixable with some tweaking, but I’m not there yet.

X10 for Raspberry Pi on the Cheap [North American Edition]

Now I’ve got my X10 system running and know its limitations, I could have saved a wheen of money not buying stuff I don’t need. Our house appears to have been wired by an, um, spirited amateur, so powerline signalling is of limited use. Thankfully, the tiny and cheap X10 FireCracker CM17A (warning: too many flashing GIFs at this link!) can be driven from heyu [previously]. You can score these on eBay for under $10, and all you need is a serial adapter to drive them.

Leviton X10 controller - cheap!The really cheap bit in my system was discovered in Active Surplus. I found a case of Leviton “Plug-in Frequency Transceiver Modules” for $4/each. One was out of its case, and wouldn’t you know it, it’s the same as a RR501 module, which typically retails for about $30. Sure, these are old stock and are a nasty beige colour, but they provide a way of switching a two-pin appliance. They can also relay remote commands from RF to wired controls.

The only X10 controller I can’t get to work with the Raspberry Pi is the CM19a USB PC Transceiver. I suspect it draws a bit too much power to run from a Raspberry Pi, as it makes the machine unresponsive if it’s plugged it. Running from my bench setup it works fine with the mochad driver, but no dice with the other machine. The CM19a reads wireless RF X10 commands, and it would be useful if I’d added a motion sensor. As is, I’ll stick to the lights going on and off.

(Update: there’s a good chance that my CM19a problems are down to the ancient dwc_otg* fixes I still run on my Raspberry Pi’s kernel. You probably don’t need them, and this device could work fine. One day I will find time to fix ‘em …)

(Incidentally, this is the “North American Edition” because X10 RF controls are completely different in Europe, and none of the above is useful to you. Yeah, I know this article is the equivalent of PC Load Letter to you; sorry.)

hey, it’s the sun … heyu and sunwait and cron on the Raspberry Pi

Yep, springtime’s coming, and today’s the first day I know it, despite the -5.8°C outside. I know spring is coming because my sunrise-adjusted lights came on before my alarm today. I’m controlling them with a Raspberry Pi, cron, and X10.

I’d described how to build and use heyu previously, so I won’t go into it further. I use sunwait to control the timing relative to local sunrise and sunset. Sunwait is a simple C program which builds quickly, and you can put the executable somewhere in your path.

You need to know your latitude and longitude to use sunwait. To check its setting for the day, you can call it with the -p option:

$ sunwait -p 43.729N 79.292W
Using location:             43.729000N, 79.292000W
Date:                        6 Feb 2013 
Local time:                  7:44 
Day length:                 10:13 hours
With civil twilight         11:10 hours
With nautical twilight      12:18 hours
With astronomical twilight  13:25 hours
Length of twilight:  civil   0:28 hours
                  nautical   1:02 hours
              astronomical   1:35 hours
Current specified time zone: EST (-5 from UTC) 
Sun transits meridian 1231 EST
                   Sun rises 0726 EST, sets 1736 EST
       Civil twilight starts 0656 EST, ends 1806 EST
    Nautical twilight starts 0622 EST, ends 1840 EST
Astronomical twilight starts 0548 EST, ends 1913 EST

So for me, today’s sunrise is at 0726, and sunset is at 1736. All sunwait does is wait until a specific solar time is reached, and then exit. Whatever command you call after sunwait, therefore, is what gets run at the right time. So if I wanted X10 device H1 to come on an hour before sunrise, I’d run:

sunwait sun up -1:00:00 43.729N 79.292W; heyu on h1

Remembering to run this every day before sunrise would be a pain, so this is where cron helps. cron uses a slightly odd config file that is edited using the crontab -e command. Here’s the relevant bit of my crontab, showing the light control times:

# m h  dom mon dow   command
 01 00   *   *   *   /usr/local/bin/sunwait sun up -1:00:00 43.729N 79.292W; /usr/local/bin/heyu on h1
 02 00   *   *   *   /usr/local/bin/sunwait sun up +1:00:00 43.729N 79.292W; /usr/local/bin/heyu off h1
 03 00   *   *   *   /usr/local/bin/sunwait sun down -1:00:00 43.729N 79.292W; /usr/local/bin/heyu on h1
 45 22   *   *   *   /usr/local/bin/heyu off h1

(you can view your crontab with crontab -l)

The columns in crontab are:

  • minute
  • hour
  • day of month
  • month
  • day of week
  • command

So the four crontab lines mean:

  1. Every day at 00:01, wait until an hour before sunrise and turn light H1 on
  2. Every day at 00:02, wait until an hour after sunrise and turn light H1 off
  3. Every day at 00:03, wait until an hour before sunset and turn light H1 on
  4. At 22:45, turn light H1 off.

So for quite a bit of the day, there are a couple of sunwait tasks just quietly waiting until sunrise or sunset to do their thing. cron, incidentally, is picky about executable paths; that’s why I specified full paths to both sunwait and heyu.

What I’d really like to do is have time on this machine update without a network connection, because it’s running from a particularly messy router set up in a spare bedroom. I should investigate a real-time clock, with GPS time updates from an I²C GPS, talking through a bluetooth console. In my copious free time, of course.

Simple ADC with the Raspberry Pi

Raspberry Pi wearing an MCP3008

I hadn’t realised it, but the The Quite Rubbish Clock did something that a lot of people seem to have trouble with on the Raspberry Pi: communicating using hardware SPI. Perhaps it’s because everything is moving so fast with Raspberry Pi development, tutorials go out of date really quickly. Thankfully, hardware SPI is much easier to understand than the older way of emulation through bit-banging.

SPI is a synchronous serial protocol, so it needs a clock line as well as a data in and data out line. In addition, it has a Chip Enable (CE, or Chip Select, CS) line that is used to choose which SPI device to talk to. The Raspberry Pi has two CE lines (pins 24 and 26) so can talk to two SPI devices at once. It supports a maximum clock rate of 32 MHz, though in practice you’ll be limited to the rate your device supports.

The device I’m testing here is an MCP3008 10-bit Analogue-to-Digital Converter (ADC). These are simple to use, cheap and quite fast converters with 8 input channels. If you hook them up to a 3.3 V supply they will convert a DC voltage varying from 0-3.3 V to a digital reading of 0-1023 (= 210 – 1). Not quite up there in quality for hi-fi audio or precision sensing, but good enough to read from most simple analogue sensors.

The sensor I’m reading is the astonishingly dull LM35DZ temperature sensor. All the cool kids seem to be using TMP36s (as they can read temperatures below freezing without a negative supply voltage). One day I’ll show them all and use a LM135 direct Kelvin sensor, but not yet.

To run this code, install the SPI libraries as before. Now wire up the MCP3008 to the Raspberry Pi like so:

 MCP 3008 Pin          Pi GPIO Pin #    Pi Pin Name
==============        ===============  =============
 16  VDD                 1              3.3 V
 15  VREF                1              3.3 V
 14  AGND                6              GND
 13  CLK                23              GPIO11 SPI0_SCLK
 12  DOUT               21              GPIO09 SPI0_MISO
 11  DIN                19              GPIO10 SPI0_MOSI
 10  CS                 24              GPIO08 CE0
  9  DGND                6              GND

The wiring for the LM35 is very simple:

 LM35 Pin        MCP3008 Pin
==========      =============
 Vs              16 VDD
 Vout             1 CH0
 GND              9 DGND

The code I’m using is a straight lift of Jeremy Blythe’s Raspberry Pi hardware SPI analog inputs using the MCP3008. The clever bit in Jeremy’s code is the readadc() function which reads the relevant length of bits (by writing the same number of bits; SPI’s weird that way) from the SPI bus and converting it to a single 10-bit value.

# -*- coding: utf-8 -*-
# mcp3008_lm35.py - read an LM35 on CH0 of an MCP3008 on a Raspberry Pi
# mostly nicked from
#  http://jeremyblythe.blogspot.ca/2012/09/raspberry-pi-hardware-spi-analog-inputs.html

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)

def readadc(adcnum):
# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
    if adcnum > 7 or adcnum < 0:
        return -1
    r = spi.xfer2([1, 8 + adcnum << 4, 0])
    adcout = ((r[1] & 3) << 8) + r[2]
    return adcout

while True:
    value = readadc(0)
    volts = (value * 3.3) / 1024
    temperature = volts / (10.0 / 1000)
    print ("%4d/1023 => %5.3f V => %4.1f °C" % (value, volts,

The slightly awkward code temperature = volts / (10.0 / 1000) is just a simpler way of acknowledging that the LM35DZ puts out 10 mV (= 10/1000, or 0.01) per °C. Well-behaved sensors generally have a linear relationship between what they indicate and what they measure.

If you run the code:

sudo ./mcp3008_lm35.py

you should get something like:

  91/1023 => 0.293 V => 29.3 °C
  93/1023 => 0.300 V => 30.0 °C
  94/1023 => 0.303 V => 30.3 °C
  95/1023 => 0.306 V => 30.6 °C
  96/1023 => 0.309 V => 30.9 °C
  97/1023 => 0.313 V => 31.3 °C
  97/1023 => 0.313 V => 31.3 °C
  98/1023 => 0.316 V => 31.6 °C
  99/1023 => 0.319 V => 31.9 °C
  99/1023 => 0.319 V => 31.9 °C
 100/1023 => 0.322 V => 32.2 °C
 100/1023 => 0.322 V => 32.2 °C
 100/1023 => 0.322 V => 32.2 °C
 101/1023 => 0.325 V => 32.5 °C
 101/1023 => 0.325 V => 32.5 °C
 102/1023 => 0.329 V => 32.9 °C
 102/1023 => 0.329 V => 32.9 °C
 103/1023 => 0.332 V => 33.2 °C

Note that the sensor had been sitting over the Raspberry Pi’s CPU for a while; I don’t keep my house at 29 °C. I made the temperature go up by holding the LM35.

So, you’ve just (fairly cheaply) given your Raspberry Pi 8 analogue input channels, so it can behave much more like a real microcontroller now. I remember from my datalogging days that analogue inputs can be pretty finicky and almost always return a value even if it’s an incorrect one. Check the chip’s datasheet to see if you’re doing it right, and if in doubt, meter it!