<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Gaugette</title>
    <link>//guy.carpenter.id.au/gaugette/categories/raspberry-pi/index.xml</link>
    <description>Recent content on Gaugette</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <atom:link href="//guy.carpenter.id.au/gaugette/categories/raspberry-pi/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Google OAuth2 for Devices Revisited</title>
      <link>//guy.carpenter.id.au/gaugette/2017/01/01/google-oauth2-for-devices-revisited/</link>
      <pubDate>Sun, 01 Jan 2017 13:03:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2017/01/01/google-oauth2-for-devices-revisited/</guid>
      <description>&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-06/oauth-2-sm.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;I just dusted off an old project that uses
&lt;a href=&#34;https://developers.google.com/identity/protocols/OAuth2ForDevices&#34; target=&#34;_blank&#34;&gt;Google&amp;rsquo;s OAuth 2.0 for Devices&lt;/a&gt; API to
authenticate against Google Docs, and cleaned up my implementation.&lt;/p&gt;

&lt;p&gt;OAuth2ForDevices is really useful for IoT projects
that use Google APIs.  I&amp;rsquo;m using it for a device that records data directly a Google Sheet.&lt;/p&gt;

&lt;p&gt;While the API itself is pretty straight forward, getting the implementation 100%
battle-hardened takes a bit of work and iteration, so I&amp;rsquo;ll share here what I&amp;rsquo;ve learned.
If you are coding in Python, you might find the OAuth class in the
 &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette&lt;/a&gt; library useful.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;theory-of-operation&#34;&gt;Theory of operation&lt;/h2&gt;

&lt;h3 id=&#34;first-boot-oauth2-flow&#34;&gt;First-Boot OAuth2 Flow&lt;/h3&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/deviceflow.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;The first time a device boots, it needs to request permissions from the user to access
Google Docs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;call the OAuth2 API to specify the permissions required and request an authorisation code.&lt;/li&gt;
&lt;li&gt;show the auth code to the user&lt;/li&gt;
&lt;li&gt;poll the OAuth2 API waiting for confirmation that the user has granted access to the device.&lt;/li&gt;
&lt;li&gt;save the refresh token in persistent storage for next startup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To confirm access, the user uses a web browser on a separate device, and navigates to
&lt;a href=&#34;https://www.google.com/device&#34; target=&#34;_blank&#34;&gt;https://www.google.com/device&lt;/a&gt; to enter the authorisation code.&lt;br /&gt;
The user must be logged in to a Google account when they confirm the permissions, and the
device will be granted access on behalf of that account.  The level of access is determined
by the scope parameters passed by the device, and the user will be shown which permissions
have been requested before they confirm.&lt;/p&gt;

&lt;h3 id=&#34;after-the-first-boot&#34;&gt;After the First Boot&lt;/h3&gt;

&lt;p&gt;On subsequent boots the device can use the saved refresh token to authenticate, so
no further user interaction is required.&lt;/p&gt;

&lt;h2 id=&#34;here-s-what-it-looks-like&#34;&gt;Here&amp;rsquo;s What It Looks Like&lt;/h2&gt;

&lt;h3 id=&#34;1-the-device-presents-a-code&#34;&gt;1. The Device Presents a Code&lt;/h3&gt;

&lt;p&gt;On my time clock, I display the code on the one-line OLED display.  The device code can be quite long - the API docs
recommend ensuring you can display 15 &amp;lsquo;W&amp;rsquo;-sized characters, although current codes are formatted as XXXX-XXXX.  The length of generated codes
has increased since I first started using this API and I now need to use horizontal scrolling to
display the entire code.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/device-auth.png&#34;   /&gt;


&lt;h3 id=&#34;2-the-user-enters-the-code&#34;&gt;2. The User Enters the Code&lt;/h3&gt;

&lt;p&gt;You need to communicate the URL (&lt;a href=&#34;https://www.google.com/device&#34; target=&#34;_blank&#34;&gt;https://www.google.com/device&lt;/a&gt;) to the user somehow.&lt;br /&gt;
This is the web page they will see.  They may first be prompted to log in to their
Google account or select from multiple logged in accounts.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/oauth_1.png&#34;   /&gt;


&lt;h3 id=&#34;3-the-user-confirms-access&#34;&gt;3. The User Confirms Access&lt;/h3&gt;

&lt;p&gt;The permissions listed here are determined by the scope variables you have passed.  The list of
available scopes is &lt;a href=&#34;https://developers.google.com/identity/protocols/googlescopes&#34; target=&#34;_blank&#34;&gt;defined here&lt;/a&gt;.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2017-01-01/oauth_2.png&#34;   /&gt;


&lt;h2 id=&#34;on-the-device&#34;&gt;On the Device&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s what it looks like on the device.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/tZ6XZ1yhHJM&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;h2 id=&#34;making-api-calls-with-oauth2-tokens&#34;&gt;Making API Calls With OAuth2 tokens&lt;/h2&gt;

&lt;p&gt;The most complicated aspect of this API is passing the credentials and handling
exceptions, and a lot has changed since I wrote the earlier Feeds implementation.  Now
I&amp;rsquo;m using the &lt;a href=&#34;https://developers.google.com/api-client-library/python/start/installation&#34; target=&#34;_blank&#34;&gt;Google API Client Libraries for Python&lt;/a&gt;
and passing in the token via a  &lt;a href=&#34;http://oauth2client.readthedocs.io/en/latest/source/oauth2client.client.html#oauth2client.client.GoogleCredentials&#34; target=&#34;_blank&#34;&gt;oauth2client.client.GoogleCredientials&lt;/a&gt;
instance.&lt;/p&gt;

&lt;p&gt;One nasty little surprise I discovered with long-running applications
is that after the device has idled for a long time (say 24 hours without making an API call) I start getting
BadStatusLine exceptions on all API calls.  To handle this and other errors,
I use @wrap from functools to wrap all of the API calls in a retry function.  This keeps
the extra complexity of error recovery nicely abstracted away.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>py-gaugette Gets a Refresh</title>
      <link>//guy.carpenter.id.au/gaugette/2016/11/12/py-gaugette-gets-a-refresh/</link>
      <pubDate>Sat, 12 Nov 2016 14:39:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2016/11/12/py-gaugette-gets-a-refresh/</guid>
      <description>

&lt;p&gt;I&amp;rsquo;ve made some major changes to the py-gaugette library to address
several issues that have accumulated over time, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;added interrupt-driven option to rotary encoder&lt;/li&gt;
&lt;li&gt;fully Python 3 compatible&lt;/li&gt;
&lt;li&gt;works with current version of Py-WiringPi&lt;/li&gt;
&lt;li&gt;uses dependency injection for GPIO and SPI interfaces&lt;/li&gt;
&lt;li&gt;updated Google Sheets code to use new API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;dependency-injection-for-gpio-and-spi&#34;&gt;Dependency Injection for GPIO and SPI&lt;/h2&gt;

&lt;p&gt;Classes that interact with the GPIO or SPI interfaces now take
an instance of that interface as a parameter to the constructor.
This avoids the issue of having multiple classes trying to initialise
the GPIO library, and makes it easy to pass alternative interface
implementations.&lt;/p&gt;

&lt;h2 id=&#34;interrupts-for-rotary-encoders&#34;&gt;Interrupts for Rotary Encoders&lt;/h2&gt;

&lt;p&gt;The original implementation of the rotary encoder library used polling.
On the Raspberry Pi it now supports interrupts.  The previous polling
behaviour is still supported.&lt;/p&gt;

&lt;h2 id=&#34;fully-python-3-compatible&#34;&gt;Fully Python 3 Compatible&lt;/h2&gt;

&lt;p&gt;While the library has been mostly Python 3 compatible, there were a few
exceptions.  In particular the SSD1306 class depended heavily on the Python 2
behaviour of the division operator, which changed in Python 3.  I&amp;rsquo;ve rewritten
the calculations to mostly use bit shifts rather than division.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Updating py-gaugette to wiringpi2</title>
      <link>//guy.carpenter.id.au/gaugette/2013/06/04/updating-to-wiringpi2-py/</link>
      <pubDate>Tue, 04 Jun 2013 16:14:51 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2013/06/04/updating-to-wiringpi2-py/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;https://projects.drogon.net/wp-content/uploads/2013/05/adaLcd-1024x602.jpg&#34;   /&gt;

Phillip Howard and Gordon Henderson recently &lt;a href=&#34;http://pi.gadgetoid.com/post/039-wiringpi-version-2-with-extra-python&#34; target=&#34;_blank&#34;&gt;announced&lt;/a&gt;
the availability of &lt;a href=&#34;http://wiringpi.com/&#34; target=&#34;_blank&#34;&gt;WiringPi2&lt;/a&gt; along with a new python wrapper
&lt;a href=&#34;https://github.com/Gadgetoid/WiringPi2-Python&#34; target=&#34;_blank&#34;&gt;WiringPi2-Python&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The python library name has changed from &lt;code&gt;wiringpi&lt;/code&gt; to &lt;code&gt;wiringpi2&lt;/code&gt;, so any application
code referencing the module needs to be updated.
I&amp;rsquo;ve forked &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette&lt;/a&gt; to create
a &lt;a href=&#34;https://github.com/guyc/py-gaugette/tree/wiringpi2&#34; target=&#34;_blank&#34;&gt;wiringpi2 branch&lt;/a&gt;.  I plan to roll
this into the master branch in the not-too-distant future.  When I do, wiringpi2 will
be a requirement for using py-gaugette.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s how I installed the wiringpi2 libraries on my boxes:&lt;/p&gt;

&lt;h3 id=&#34;install-wiringpi2&#34;&gt;Install WiringPi2&lt;/h3&gt;

&lt;p&gt;First install wiringPi.  At the time of writing, it does &lt;em&gt;not&lt;/em&gt; work to install
with &lt;code&gt;sudo pip install wiringpi2&lt;/code&gt;; the library builds and installs fine, but
the version installed is not compatible with current version of &lt;code&gt;WiringPi2-Python&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;install-wiringpi2-python&#34;&gt;Install WiringPi2-Python&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;git clone https://github.com/Gadgetoid/WiringPi2-Python.git
cd WiringPi2-Python/
sudo python setup.py install
cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;checkout-py-gaugette-for-wiringpi2&#34;&gt;Checkout py-gaugette for WiringPi2&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;git clone git://github.com/guyc/py-gaugette.git
cd py-gaugette
git checkout wiringpi2
cd ..
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>Raspberry Pi Time Clock</title>
      <link>//guy.carpenter.id.au/gaugette/2013/02/03/raspberry-pi-time-clock/</link>
      <pubDate>Sun, 03 Feb 2013 12:18:56 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2013/02/03/raspberry-pi-time-clock/</guid>
      <description>&lt;h2 id=&#34;gaugette-time-clock&#34;&gt;Gaugette Time Clock&lt;/h2&gt;

&lt;p&gt;This build combines a Raspberry Pi with a rotary-encoder, an RGB LED and an OLED
character display to create a time clock that logs my time on tasks directly to
a Google Docs spreadsheet.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3555.jpg&#34;   /&gt;


&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Whenever I have to record time against projects, I find it really hard to
diligently keep my time records up to date. Maybe with a purpose-built time
clock I will keep better records? Hey, it could happen!&lt;/p&gt;

&lt;h2 id=&#34;overview&#34;&gt;Overview&lt;/h2&gt;

&lt;p&gt;The off-the-shelf components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Raspberry Pi model B Rev 1 - &lt;a href=&#34;http://www.adafruit.com/products/998&#34; target=&#34;_blank&#34;&gt;Adafruit has the Rev 2 board.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;128x32 SPI OLED display - &lt;a href=&#34;http://www.adafruit.com/products/661&#34; target=&#34;_blank&#34;&gt;Adafruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rotary Encoder - &lt;a href=&#34;https://www.adafruit.com/products/377&#34; target=&#34;_blank&#34;&gt;Adafruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;5mm RGB LED - &lt;a href=&#34;https://www.sparkfun.com/products/105&#34; target=&#34;_blank&#34;&gt;Sparkfun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Occidentalis 0.2 - &lt;a href=&#34;http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/occidentalis-v0-dot-2&#34; target=&#34;_blank&#34;&gt;Adafruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;6” Female/Female jumper wires - &lt;a href=&#34;https://www.adafruit.com/products/266&#34; target=&#34;_blank&#34;&gt;Adafruit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;3” Female/Female jumpers wires - &lt;a href=&#34;http://littlebirdelectronics.com/products/premium-jumper-wire-50-piece-rainbow-assortment-f-f-3&#34; target=&#34;_blank&#34;&gt;Little Bird Electronics&lt;/a&gt; or &lt;a href=&#34;https://www.adafruit.com/products/794&#34; target=&#34;_blank&#34;&gt;Adafruit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used a common cathode LED from Sparkfun. You could use Adafruit’s &lt;a href=&#34;http://www.adafruit.com/products/159&#34; target=&#34;_blank&#34;&gt;common
anode equivalent&lt;/a&gt; with minor code changes.&lt;/p&gt;

&lt;p&gt;The theory of operation is pretty simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;at start-up, it pulls a list of jobs from a Google Docs spreadsheet,&lt;/li&gt;
&lt;li&gt;rotating the knob scrolls through the list of jobs,&lt;/li&gt;
&lt;li&gt;clicking the knob logs a start time or end time in the spreadsheet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;the-case&#34;&gt;The Case&lt;/h2&gt;

&lt;p&gt;The top of the case is made from a single block of wood.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3532.jpg&#34;   /&gt;


&lt;p&gt;The bottom of the block has been hollowed out to house the RPi board. The RPi
sits in a plastic carriage that screws to the bottom of the block. I have not
provided access to the HDMI, audio or video ports on the RPi since I’m not going
to use them.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3479.jpg&#34;   /&gt;


&lt;p&gt;The carriage for the Raspberry Pi was designed in
&lt;a href=&#34;http://openscad.org/&#34; target=&#34;_blank&#34;&gt;OpenSCAD&lt;/a&gt; and printed on a Makerbot Replicator. The RPi
board doesn’t have mounting holes, so the carriage has edge-clips to grasp the
board. The posts at the corners were originally intended to screw the carriage
to the block, but I found that to be impractical, so I added the two tabs at the
bottom and routed out matching recesses in the block. I left the posts there
because they make the carriage look a little more interesting. Or because I was
too lazy to remove them, I’ve heard it both ways.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/base_preview_featured.jpg&#34;   /&gt;


&lt;p&gt;The OpenScad sources and STL files for the base are available from
&lt;a href=&#34;http://www.thingiverse.com/thing:46892&#34; target=&#34;_blank&#34;&gt;Thingiverse&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&#34;the-circuit&#34;&gt;The Circuit&lt;/h2&gt;

&lt;p&gt;I’m using two of the ground pins originally documented as Do Not Connect (DNC).
The extra grounds are really convenient, and Eben &lt;a href=&#34;http://www.raspberrypi.org/archives/2233&#34; target=&#34;_blank&#34;&gt;has publicly committed&lt;/a&gt; to keeping these available
in future board revisions.&lt;/p&gt;

&lt;p&gt;It’s worth pointing out that I deliberately selected GPIO pin 5 for the push
button because of the &lt;a href=&#34;http://www.raspberrypi.org/phpBB3/viewtopic.php?f=29&amp;amp;t=12007&#34; target=&#34;_blank&#34;&gt;Raspberry Pi Safe
Mode&lt;/a&gt; feature. If
you have a recent &lt;a href=&#34;https://github.com/Hexxeh/rpi-update&#34; target=&#34;_blank&#34;&gt;firmware release&lt;/a&gt;, you
can boot your RPi in safe mode by holding the knob down (shorting pin 5 to
ground) when you power up. In truth my intention here is not so much to make
safe mode available (I’ve never needed it) but to make sure that pin 5 is not
&lt;em&gt;unintentionally&lt;/em&gt; shorted to ground at boot time, as it could be if you used it
for one of the quadrature encoder inputs. Yep, that happened. After I upgraded
to the version of firmware that supports safe mode my box stopped booting.
Lesson learned; be careful with pin 5, or &lt;a href=&#34;http://elinux.org/images/c/ca/Raspi_documented_config.txt&#34; target=&#34;_blank&#34;&gt;disable safe
mode&lt;/a&gt; by adding
&lt;code&gt;avoid_safe_mode=1&lt;/code&gt; to &lt;code&gt;/boot/config.txt&lt;/code&gt;.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/timeclock2_bb.jpg&#34;   /&gt;


&lt;p&gt;For most of the GPIO connections I cut pre-terminated &lt;a href=&#34;https://www.adafruit.com/products/266&#34; target=&#34;_blank&#34;&gt;Female Female jumper
wires&lt;/a&gt; in half and soldered the cut end
to the component. I already had header pins on the SSD1306 OLED module, so I
used &lt;a href=&#34;http://littlebirdelectronics.com/products/premium-jumper-wire-50-piece-rainbow-assortment-f-f-3&#34; target=&#34;_blank&#34;&gt;3” pre-made cables from Little Bird
Electronics&lt;/a&gt;.
It is crucial to keep wiring short and well insulated so that it will all pack
in neatly and without shorts when the case is closed up.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3481.jpg&#34;   /&gt;


&lt;h2 id=&#34;rgb-led-indicator&#34;&gt;RGB LED Indicator&lt;/h2&gt;

&lt;p&gt;For this device I wanted a large, diffuse and interesting state indicator built
around an RGB LED. I use the WiringPi
&lt;a href=&#34;https://projects.drogon.net/raspberry-pi/wiringpi/software-pwm-library/&#34; target=&#34;_blank&#34;&gt;soft PWM&lt;/a&gt;
library to drive the LED, and the
&lt;a href=&#34;https://github.com/guyc/py-gaugette/blob/master/gaugette/rgbled.py&#34; target=&#34;_blank&#34;&gt;py-gaugette RgbLed&lt;/a&gt;
class makes it easy to do animated colour transition loops. My first prototype
was made from the back of a GU10 light bulb. The bulb glass is thick and
diffuses the light nicely, and I thought the terminals would make cool
capacitive switches.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/tRBiQ0ZXFZM&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3560.jpg&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;I liked that a lot, but ultimately settled on a long oven light which had a more
compact footprint. It gives elegant curving internal reflections which look
quite nice.&lt;/p&gt;

&lt;p&gt;When I cut the metal tip of the bulb off with a Dremel I expected to be able to
remove the burned-out filament, but discovered this bulb (like most others I
would guess) is made with an inner glass plug that encases the filament wires
and seals the bulb. It isn’t easily removed, but has a hollow neck just big
enough to receive an LED. So the filament stays. Maybe I should have used a new
bulb!&lt;/p&gt;

&lt;p&gt;I trimmed the red, green and blue leads on the LED quite short and soldered a
270Ω current-limiting resistor to each one. This keeps the resistors tucked up
away from the board. I then added connector wires to each lead, pushed the LED
up into the bulb neck and pumped some hot glue in to keep it all in place.&lt;/p&gt;

&lt;p&gt;I’ve seen advice suggesting I should have selected different values for the
resistors to to get optimal white balance. I didn’t bother. Colour balance is
fine. &lt;a href=&#34;http://www.youtube.com/watch?v=vFWkJuPhApc&#34; target=&#34;_blank&#34;&gt;I aint bovvered&lt;/a&gt;.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3444.jpg&#34;   /&gt;


&lt;h2 id=&#34;rotary-encoder&#34;&gt;Rotary Encoder&lt;/h2&gt;

&lt;p&gt;I documented the encoder library &lt;a href=&#34;//guy.carpenter.id.au/gaugette/blog/2013/01/14/rotary-encoder-library-for-the-raspberry-pi/&#34;&gt;in a previous post&lt;/a&gt;.
I’m using the
&lt;a href=&#34;https://github.com/guyc/py-gaugette/blob/master/gaugette/rotary_encoder.py&#34; target=&#34;_blank&#34;&gt;py-gaugette RotaryEncoder.Worker class&lt;/a&gt;
to poll the encoder GPIOs in the background which keeps the application code
very simple.&lt;/p&gt;

&lt;h2 id=&#34;128x32-ssd1306-oled-display&#34;&gt;128x32 SSD1306 OLED Display&lt;/h2&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp3459.jpg&#34;   /&gt;


&lt;p&gt;I’ve written about using these great little
&lt;a href=&#34;https://www.adafruit.com/products/661&#34; target=&#34;_blank&#34;&gt;128x32 OLEDs&lt;/a&gt; from Adafruit
&lt;a href=&#34;//guy.carpenter.id.au/gaugette/blog/2012/11/11/font-support-for-ssd1306/&#34;&gt;before&lt;/a&gt;. Mounting it in
the block was a challenge. I used a router on the inside of the case to thin the
material down to just a few mm over an area big enough to place the PCB. I then
cut a rectangular hole for the display using a Dremel, file and scalpel, taking
great pains not to crack the thin wood. I couldn’t see a practical way to use
the mounting holes so I hot-glued the board in place. I positioned it with the
display powered up showing a test pattern so I could line up the active part of
the display with the hole.&lt;/p&gt;

&lt;p&gt;The bezel was printed on a Makerbot Replicator and painted with Plaid brand
&lt;a href=&#34;http://www.plaidonline.com/liquid-leaf-copper/89/6160/product.htm&#34; target=&#34;_blank&#34;&gt;copper Liquid Leaf&lt;/a&gt;. I’ve
been looking for a metallic paint that wouldn’t dissolve the ABS. Liquid Leaf is
xylene-based, which &lt;a href=&#34;http://books.google.com.au/books?isbn=0815515812&#34; target=&#34;_blank&#34;&gt;should be safe for ABS&lt;/a&gt;, although maybe
&lt;a href=&#34;http://www.intertradegrp.com/docs/IT-XYLENE-MSDS.pdf&#34; target=&#34;_blank&#34;&gt;not so safe for humans&lt;/a&gt;.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/imgp2505.jpg&#34;   /&gt;


&lt;p&gt;The effect of metallic paint on the printed surface is interesting; it
highlights the individual filaments in the print. I like it. It would be
possible to reduce the relief by brushing the surface with acetone before
painting, but I think the sharp relief is good for what I’m doing here.&lt;/p&gt;

&lt;h2 id=&#34;cooling&#34;&gt;Cooling&lt;/h2&gt;

&lt;p&gt;It occurred to me fairly late in this build that I hadn’t provided for any air
flow to help cool the processor. That got me to wondering, then to worrying… am
I cooking my Pi? And is there no end to the bad pie puns?&lt;/p&gt;

&lt;p&gt;Fortunately a recent firmware update provided a tool that allows us to measure
the CPU temperature in code, so I did a little experiment. I recorded the
temperature using &lt;a href=&#34;http://elinux.org/RPI_vcgencmd_usage&#34; target=&#34;_blank&#34;&gt;vcgencmd&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
while :; do /opt/vc/bin/vcgencmd measure_temp; sleep 3; done
&lt;/pre&gt;


&lt;p&gt;I ran this loop from a cold boot for 25 minutes, first with the top off, then
again (after letting the system cool down) with the case closed up tight. For
the record the ambient temperature in my office was around 26°C.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/RPi-Temperature.png&#34;   /&gt;


&lt;p&gt;The results show that the closed box adds about 4°C to the CPU temperature at
idle. I tried removing the bulb from the centre of the cover to allow hot air to
be convected away, but that made no measurable difference in temperature.&lt;/p&gt;

&lt;p&gt;These temperatures were taken at idle. My application code runs around 20% CPU
utilization. With application running and the lid off the temperature settles in
around 46°C, and with the lid on at around 51°C.&lt;/p&gt;

&lt;p&gt;Based on these results I’m happy to ignore air flow for now. 51°C isn’t
worryingly high, and it looks like it would take a lot of work to improve air
flow enough to make an appreciable difference.&lt;/p&gt;

&lt;h2 id=&#34;software&#34;&gt;Software&lt;/h2&gt;

&lt;p&gt;The code for all of the I/O devices used here is available in the
&lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette library&lt;/a&gt;. I will release the application
source soon; there are a few loose ends I want to tidy up first.&lt;/p&gt;

&lt;h2 id=&#34;all-together-now&#34;&gt;All Together Now&lt;/h2&gt;

&lt;p&gt;In the video below, the LED colours are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;purple is idle - time not being logged&lt;/li&gt;
&lt;li&gt;slowly pulsing blue is active - time is being logged against a task, pulses slowly&lt;/li&gt;
&lt;li&gt;flashing is busy - updating the spreadsheet via Google Docs&lt;/li&gt;
&lt;/ul&gt;

&lt;iframe allowfullscreen=&#34;allowFullScreen&#34; frameborder=&#34;0&#34; height=&#34;390&#34; mozallowfullscreen=&#34;mozallowfullscreen&#34; src=&#34;http://www.youtube.com/embed/su-CXqMPJxM&#34; webkitallowfullscreen=&#34;webkitAllowFullScreen&#34; width=&#34;640&#34;&gt;&lt;/iframe&gt;

&lt;p&gt;The resulting spreadsheet looks like this:&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-02-03/TimeClockSpreadsheet.png&#34;   /&gt;</description>
    </item>
    
    <item>
      <title>Rotary Encoder Library for the Raspberry Pi</title>
      <link>//guy.carpenter.id.au/gaugette/2013/01/14/rotary-encoder-library-for-the-raspberry-pi/</link>
      <pubDate>Mon, 14 Jan 2013 20:49:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2013/01/14/rotary-encoder-library-for-the-raspberry-pi/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a quick overview of the rotary encoder I/O class in
the &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The encoder I&amp;rsquo;m using is a 2-bit quadrature-encoded rotary encoder,
&lt;a href=&#34;http://www.adafruit.com/products/377&#34; target=&#34;_blank&#34;&gt;available from Adafruit&lt;/a&gt;.&lt;br /&gt;
The &lt;a href=&#34;http://www.adafruit.com/datasheets/pec11.pdf&#34; target=&#34;_blank&#34;&gt;datasheet is here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The documentation for this encoder says that it gives 24 pulses per 360&amp;deg; rotation,
which I interpreted to mean 24 resolvable positions, but after trying it I see that
it has 24 detent positions, and between each detent is a full 4-step quadrature cycle,
so there are actually 96 resolvable steps per rotation.  This unit also includes
a momentary switch which is closed when the button is pushed down.  Takes a solid
push to close the switch.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-01-14/rotary-encoder.png&#34;  class=&#34;center&#34;   /&gt;


&lt;p&gt;The diagram above shows how I&amp;rsquo;ve connected the rotary encoder to the Raspberry Pi.
I&amp;rsquo;m using pin 9, one of the &amp;ldquo;Do Not Connect&amp;rdquo; (DNC) pins to get a second ground pin for convenience.
Eben &lt;a href=&#34;http://www.raspberrypi.org/archives/2233&#34; target=&#34;_blank&#34;&gt;made a public commitment&lt;/a&gt;
to keep the extra power and ground pins unchanged in future releases, so
I think it is safe to publish circuits using them.  Right?  Here&amp;rsquo;s a pinout
highlighting the functions of the DNC pins, along with the wiringpi pin numbers.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/pi-pinout.png&#34;   /&gt;


&lt;h2 id=&#34;decoder-logic&#34;&gt;Decoder Logic&lt;/h2&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2013-01-14/quadrature.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;The implementation configures pins A and B as inputs, turns on the internal pull-up resistors for each,
so they will read high when the contacts are open, low when closed.  The inputs
generate the following sequence of values
as we advance through the quadrature sequence:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SEQ&lt;/th&gt;
&lt;th&gt;B&lt;/th&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;A ^ B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;One non-obvious detail here: the library uses the bitwise xor value &lt;code&gt;A ^ B&lt;/code&gt; to
efficiently transform the input bits into an ordinal sequence number.  There is
no reason behind the xor other than it gives us the bit sequence we want.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;        seq = (a_state ^ b_state) | b_state &amp;lt;&amp;lt; 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because we are pulling our inputs high and
shorting to ground when the contacts close, our inputs for A and B are actually
inverted against those shown in Quadrature Output Table figure above.
It turns out you can ignore this inversion in the decode logic; inverting the signals moves
the quadrature half a cycle forward, but makes no difference at all to
the decode logic.&lt;/p&gt;

&lt;p&gt;Once the library has computed the sequence value, it determines the direction of movement
by comparing the current sequence position against the previous sequence position,
like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;delta = (current_sequence - previous_sequence) % 4
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;which will yield values in the range 0 through 3, interpreted as follows:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;delta&lt;/th&gt;
&lt;th&gt;meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;no change&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1 step clockwise&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2 steps clockwise &lt;em&gt;or&lt;/em&gt; counter-clockwise&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;1 step counter clockwise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;If we get a value of 2, we know we have missed a transition (oops!) but we don&amp;rsquo;t
know if the encoder has turned clockwise or counter-clockwise.  In this
case the library assumes the direction is the same as the previous rotation.
Of course if the encoder has actually moved 3 steps between reads, it will decode as 1 step
in the wrong direction.  You can only fix this by polling faster or using interrupts.&lt;/p&gt;

&lt;h2 id=&#34;polling-vs-interrupts&#34;&gt;Polling Vs Interrupts&lt;/h2&gt;

&lt;p&gt;The current implementation of the &lt;code&gt;RotaryEncoder&lt;/code&gt; class uses polling to monitor the inputs rather than
using GPIO interrupts.  It looks like the plumbing is in place within wiringpi to use interrupts on GPIOs,
but I&amp;rsquo;ll leave that for another day.  Instead I have included an optional worker thread class that can be used
to monitor the inputs, leaving the main thread free to go about its business.&lt;/p&gt;

&lt;p&gt;The push switch is handled by a separate Switch class that doesn&amp;rsquo;t do anything clever
like debounce - it just reads and returns the current switch state.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s how to read the rotary encoder and switch &lt;strong&gt;&lt;em&gt;without&lt;/em&gt;&lt;/strong&gt; starting a worker thread.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import gaugette.rotary_encoder
import gaugette.switch

A_PIN  = 7
B_PIN  = 9
SW_PIN = 8

encoder = gaugette.rotary_encoder.RotaryEncoder(A_PIN, B_PIN)
switch = gaugette.switch.Switch(SW_PIN)
last_state = None

while True:
    delta = encoder.get_delta()
    if delta!=0:
        print &amp;quot;rotate %d&amp;quot; % delta

    sw_state = switch.get_state()
    if sw_state != last_state:
        print &amp;quot;switch %d&amp;quot; % sw_state
        last_state = sw_state
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Spin the knob and you should see something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo python rotary_worker_test.py
switch 0
rotate 1
rotate 1
rotate -1
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using the class as shown above, you must call &lt;code&gt;encoder.get_delta()&lt;/code&gt; frequently enough
to catch all transitions.  A single missed step is handled okay, but 2 missed steps will
be misinterpreted as a single step in the wrong direction, so if you turn the knob too quickly
you might see some jitter.&lt;/p&gt;

&lt;p&gt;To ensure the inputs are polled quickly enough, even if your application&amp;rsquo;s main thread
is busy doing heavy lifting, you can use the worker thread class
class to monitor the switch positions.  Using the worker class is trivial;
instantiate &lt;code&gt;RotaryEncoder.Worker&lt;/code&gt; instead of &lt;code&gt;RotaryEncoder&lt;/code&gt; with the same
parameters, and call the &lt;code&gt;start()&lt;/code&gt; method to begin polling - only lines 8 and 9 below have changed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import gaugette.rotary_encoder
import gaugette.switch

A_PIN  = 7
B_PIN  = 9
SW_PIN = 8

encoder = gaugette.rotary_encoder.RotaryEncoder.Worker(A_PIN, B_PIN)
encoder.start()
switch = gaugette.switch.Switch(SW_PIN)
last_state = None

while 1:
    delta = encoder.get_delta()
    if delta!=0:
        print &amp;quot;rotate %d&amp;quot; % delta

    sw_state = switch.get_state()
    if sw_state != last_state:
        print &amp;quot;switch %d&amp;quot; % sw_state
        last_state = sw_state
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here&amp;rsquo;s a video showing the rotary encoder at work.  In this case
I use the main thread to service the OLED scrolling, with the worker thread
keeping an eye on the rotary encoder.  There is another worker thread that
manages the RGB led transitions.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/AWssNKI06oE&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Alternative Raspberry Pi SSD1306 Library</title>
      <link>//guy.carpenter.id.au/gaugette/2012/12/21/alternative-raspberry-pi-ssd1306-library/</link>
      <pubDate>Fri, 21 Dec 2012 17:09:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/12/21/alternative-raspberry-pi-ssd1306-library/</guid>
      <description>&lt;p&gt;The SSD1306 code in the &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette library&lt;/a&gt; has been
modified at &lt;a href=&#34;https://github.com/andig/AdaPi&#34; target=&#34;_blank&#34;&gt;andig/AdaPi&lt;/a&gt; with several
extensions including I&amp;sup2;C support, and the addition of geometric drawing functions from
&lt;a href=&#34;https://github.com/adafruit/Adafruit-GFX-Library&#34; target=&#34;_blank&#34;&gt;Adafruit&amp;rsquo;s GFX Library&lt;/a&gt;.
If you need to drive the I&amp;sup2;C version of this display from a RPi,
this is the place to start.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Better Fonts for the SSD1306</title>
      <link>//guy.carpenter.id.au/gaugette/2012/11/11/font-support-for-ssd1306/</link>
      <pubDate>Sun, 11 Nov 2012 16:42:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/11/11/font-support-for-ssd1306/</guid>
      <description>&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-08/ssd1306.jpg&#34;  class=&#34;right&#34;   /&gt;

The first release of the SSD1306 support library &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette&lt;/a&gt;
used the 5x7 pixel fonts from the
&lt;a href=&#34;https://github.com/adafruit/Adafruit-GFX-Library/blob/master/glcdfont.c&#34; target=&#34;_blank&#34;&gt;Adafruit GFX library&lt;/a&gt;.
That&amp;rsquo;s a fine and compact font, but wouldn&amp;rsquo;t it be nice to have some pretty high-res fonts
to take advantage of the memory and resolution we have to work with?&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;generating-font-bitmaps&#34;&gt;Generating Font Bitmaps&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-11/tahoma_16.jpg&#34;  class=&#34;right&#34;   /&gt;

I started with &lt;a href=&#34;http://www.pavius.net/2009/07/the-dot-factory-an-lcd-font-and-image-generator/&#34; target=&#34;_blank&#34;&gt;The Dot Factory&lt;/a&gt; by Eran Duchan.  Its a handy C# (Windows) tool for generating C and C++ bitmap files quickly, and &lt;a href=&#34;https://github.com/pavius/The-Dot-Factory&#34; target=&#34;_blank&#34;&gt;source code is available&lt;/a&gt;.  I modified it to generate Python code, and to add a kerning table to store the minimum number of pixels the cursor must move between any two characters to avoid collison.&lt;/p&gt;

&lt;p&gt;The kerning isn&amp;rsquo;t completely right yet  - I noticed that the underscore character can slip beheath other characters.  I&amp;rsquo;ll need to look at that some more in due time - and I&amp;rsquo;d also like to replace the C# app for a command-line tool to generate the rasterized image files.&lt;/p&gt;

&lt;p&gt;Each font is stored in a module like the following.  The size suffix (16 in this case) indicates the character height in pixels.
The descriptor table specifies the width of each character and the character&amp;rsquo;s offset in the bitmap.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Module gaugette.fonts.arial_16
# generated from Arial 12pt                                                                                                         

name        = &amp;quot;Arial 16&amp;quot;
start_char  = &#39;#&#39;
end_char    = &#39;~&#39;
char_height = 16
space_width = 8
gap_width   = 2

bitmaps = (
    # @0 &#39;!&#39; (1 pixels wide)
    0x00, #  
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x80, # O
    0x00, #  
    0x80, # O
    0x00, #  
    0x00, #  
    0x00, #  

    # @16 &#39;&amp;quot;&#39; (4 pixels wide)
    0x00, #     
    0x90, # O  O
    0x90, # O  O
    0x90, # O  O
    0x90, # O  O
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     
    0x00, #     

    # @32 &#39;#&#39; (9 pixels wide)
    0x00, 0x00, #          
    0x11, 0x00, #    O   O
    0x11, 0x00, #    O   O
    0x11, 0x00, #    O   O
    0x22, 0x00, #   O   O  
    0xFF, 0x80, # OOOOOOOOO
    0x22, 0x00, #   O   O  
    0x22, 0x00, #   O   O  
    0x22, 0x00, #   O   O  
    0xFF, 0x80, # OOOOOOOOO
    0x44, 0x00, #  O   O   
    0x44, 0x00, #  O   O   
    0x44, 0x00, #  O   O   
    0x00, 0x00, #          
    0x00, 0x00, #          
    0x00, 0x00, #          
...
)

# (width, byte offset)
descriptors = (
    (1,0),# !
    (4,16),# &amp;quot;
    (9,32),# #
...
)

# kerning[c1][c2] yeilds minimum number of pixels to advance
# after drawing #c1 before drawing #c2 so that the characters
# do not collide.
kerning = (
    (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,),
...
)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the font is a module, not a class, because it allows a very concise syntax:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from gaugette.fonts import arial_16
textSize = led.draw_text3(0,0,&amp;quot;Hello World&amp;quot;,arial_16)
&lt;/code&gt;&lt;/pre&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-11/old_english_text.jpg&#34;  class=&#34;right&#34;   /&gt;


&lt;h2 id=&#34;supporting-horizontal-scrolling&#34;&gt;Supporting Horizontal Scrolling&lt;/h2&gt;

&lt;p&gt;In the process of testing these fonts, I realized I would like to be able to scroll horizontally,
and the SSD1306 doesn&amp;rsquo;t have hardware support for that.  Vertical scrolling is accomplished using
the &lt;code&gt;SET_START_LINE&lt;/code&gt; command, but the horizontal scrolling commands do not support scrolling
through an image that is wider than the display.  We need to do it in software.&lt;/p&gt;

&lt;p&gt;It turns out that blitting memory from the Pi to the SSD1306 over SPI is pretty fast; fast enough
to get a reasonable horizontal scroll effect by blitting complete frames from the Pi&amp;rsquo;s
memory to the SSD1306.  There&amp;rsquo;s just one thing - the default memory mode of the
SSD1306 is &lt;a href=&#34;http://en.wikipedia.org/wiki/Row-major_order&#34; target=&#34;_blank&#34;&gt;row-major&lt;/a&gt;, and
for horizontal scrolling we really want to send a &lt;strong&gt;vertical slice&lt;/strong&gt; of the memory buffer
over SPI.  To avoid buffer manipulation I switched the Pi-side memory buffer to use
&lt;a href=&#34;http://en.wikipedia.org/wiki/Column-major_order#Column-major_order&#34; target=&#34;_blank&#34;&gt;column-major order&lt;/a&gt;,
and use &lt;code&gt;MEMORY_MODE_VERT&lt;/code&gt; on the SSD1306 when blitting.&lt;/p&gt;

&lt;p&gt;To illustrate: the memory buffer is stored as a python list of bytes.  Consider a virtual
buffer that is 256 columns wide and 64 rows high.  Using column-major layout
we can address the 128 columns starting at column 100 using the python
list addressing &lt;code&gt;buffer[100*64/8:128*64/8]&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;buffer = [0] * 256 * 64 / 8                              # buffer for 256 columns, 64 rows, 8 pixels stored per byte
start = 100 * 64 / 8                                     # byte offset to 100th column
length = 128 * 64 / 8                                    # byte count of 128 columns x 64 rows
led.command(led.SET_MEMORY_MODE, led.MEMORY_MODE_VERT)   # use vertical addressing mode
led.data(buffer[start:start+length])                     # send a vertical slice of the virtual buffer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that using column-major layout we cannot easily blit a &lt;strong&gt;horizontal&lt;/strong&gt;
slice of the virtual memory buffer into display ram, so we can&amp;rsquo;t use the same method for
vertical scrolling.  Stick with &lt;code&gt;SET_START_LINE&lt;/code&gt; for vertical scrolling.  The combination
of these methods gives us fast horizontal and vertical scrolling.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/fSCDr8A_ItU&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;p&gt;An updated &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;library&lt;/a&gt; with &lt;a href=&#34;https://github.com/guyc/py-gaugette/blob/master/samples/font_test.py&#34; target=&#34;_blank&#34;&gt;sample code&lt;/a&gt; is available on github.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Controlling an Adafruit SPI OLED with a Raspberry Pi</title>
      <link>//guy.carpenter.id.au/gaugette/2012/11/08/controlling-an-adafruit-spi-oled-with-a-raspberry-pi/</link>
      <pubDate>Thu, 08 Nov 2012 10:31:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/11/08/controlling-an-adafruit-spi-oled-with-a-raspberry-pi/</guid>
      <description>&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-08/ssd1306.jpg&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;Adafruit&amp;rsquo;s lovely little &lt;a href=&#34;http://www.adafruit.com/products/661&#34; target=&#34;_blank&#34;&gt;128x32 monochrome SPI OLED module&lt;/a&gt;
uses a SSD1306 driver chip (&lt;a href=&#34;http://www.adafruit.com/datasheets/SSD1306.pdf&#34; target=&#34;_blank&#34;&gt;datasheet&lt;/a&gt;),
and Adafruit have published &lt;a href=&#34;http://learn.adafruit.com/monochrome-oled-breakouts&#34; target=&#34;_blank&#34;&gt;excellent tutorials&lt;/a&gt; and
&lt;a href=&#34;https://github.com/adafruit/Adafruit_SSD1306&#34; target=&#34;_blank&#34;&gt;libraries&lt;/a&gt; for driving this from an Arduino.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;When &lt;a href=&#34;http://adafruit.com/forums/viewtopic.php?f=47&amp;amp;t=33040&#34; target=&#34;_blank&#34;&gt;asked in their forum&lt;/a&gt;
about Raspberry Pi support, Adafruit have said
that &lt;em&gt;there is a huge backlog of libraries to port to the RasPi and (they) don&amp;rsquo;t have any ETA on the SSD1306&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m working on a project that was originally intended for an Arduino, but I&amp;rsquo;ve decided to
switch to the Raspberry Pi, so I need to get this display working with the Pi.
To that end, I&amp;rsquo;ve partially ported Adafruit&amp;rsquo;s SSD1306 library to Python for the Raspberry Pi.  The port is partial
in that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it only supports the 128x32 SPI module (unlike the original that supports the I&amp;sup2;C and 128x64 modules) and&lt;/li&gt;
&lt;li&gt;it only supports pixel and text drawing functions (no geometric drawing functions).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;signal-levels&#34;&gt;Signal Levels&lt;/h2&gt;

&lt;p&gt;The SSD1306 operates at 3.3V, and the Adafruit module has built-in level-shifters for 5V operation.
However I want to drive it at 3.3V from the Pi, and I wasn&amp;rsquo;t confident from the documentation that
it would operate at 3.3V without modification.  However the back-side silkscreen says very clearly 3.3 - 5V
and I can confirm it works very happily with both Vin and signalling at 3.3V.&lt;/p&gt;

&lt;h2 id=&#34;spi-signals&#34;&gt;SPI Signals&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&#34;http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus&#34; target=&#34;_blank&#34;&gt;SPI nomenclature&lt;/a&gt;
MISO is &lt;em&gt;master in, slave out&lt;/em&gt;, MOSI is &lt;em&gt;master out, slave in&lt;/em&gt;.
The SSD1306 module is &lt;em&gt;write-only&lt;/em&gt; using SPI, and so there is no MISO connection available,
and &lt;strong&gt;MOSI is labelled DATA on the module&lt;/strong&gt;.
Of course SPI always reads while it writes, but it is fine to leave MISO disconnected.  It will
be pulled low, so if you ever looked at the data you would see all zeros.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;D/C&lt;/strong&gt; (Data/Command) signal on the module is not part of the SPI specification, and it took a little
experimenting to understand exactly what it is used for.  The data sheet says
&lt;em&gt;&amp;ldquo;When it is pulled HIGH (i.e. connect to VDD), the data
at D[7:0] is treated as data. When it is pulled LOW, the data at D[7:0] will be transferred
to the command register.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Initially I supposed &lt;em&gt;data&lt;/em&gt; to include the
argument bytes that follow the opcode when sending multi-byte commands.  For example the &amp;ldquo;Set Contrast Control&amp;rdquo;
command consists of a one-byte opcode (0x81) followed by a one-byte contrast value, so I was sending
the first byte with D/C high, and pulling it low for the argument byte.  Wrongo!  That&amp;rsquo;s not what they
mean by &lt;em&gt;data&lt;/em&gt;; &lt;strong&gt;keep the D/C line high for all bytes in a command, and pull it low
when blitting image data into the image memory buffer&lt;/strong&gt;.  Simple as that.&lt;/p&gt;

&lt;h2 id=&#34;platform&#34;&gt;Platform&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m running Python 2.7.3 on a Rasberry Pi Model B (v1) with the following software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/occidentalis-v0-dot-2&#34; target=&#34;_blank&#34;&gt;Occidentalis 0.2&lt;/a&gt; boot image,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/WiringPi/WiringPi-Python&#34; target=&#34;_blank&#34;&gt;WiringPi-Python&lt;/a&gt; for python access to the GPIO pins,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/doceme/py-spidev&#34; target=&#34;_blank&#34;&gt;py-spidev&lt;/a&gt; for python bindings to the spidev linux kernel driver.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;wire-up&#34;&gt;Wire Up&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s how I&amp;rsquo;ve wired it up.  You can freely change the GPIOs for D/C and Reset.
&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-08/raspberrypi_and_ssd1306.jpg&#34;   /&gt;
&lt;/p&gt;

&lt;h2 id=&#34;test-code&#34;&gt;Test Code&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note that pin numbers passed in the constructor are
the &lt;a href=&#34;https://projects.drogon.net/raspberry-pi/wiringpi/pins/&#34; target=&#34;_blank&#34;&gt;wiring pin numbers&lt;/a&gt;,
not the connector pin numbers!&lt;/strong&gt;
For example I have Reset wired to connector pin 8, which is &lt;em&gt;BCP gpio 14&lt;/em&gt;, but &lt;em&gt;wiringPi pin 15&lt;/em&gt;.
It&amp;rsquo;s confusing, but just refer to the &lt;a href=&#34;https://projects.drogon.net/raspberry-pi/wiringpi/pins/&#34; target=&#34;_blank&#34;&gt;wiringPi GPIO table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The python library for the SSD1306 has been rolled into the
&lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;py-gaugette library&lt;/a&gt; available on github.&lt;/p&gt;

&lt;p&gt;The test code below vertically scrolls vertically between two display buffers, one
showing the current time, one showing the current date.&lt;/p&gt;


&lt;div style=&#34;position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;//www.youtube.com/embed/U2uF2-zGiAM&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%;&#34; allowfullscreen frameborder=&#34;0&#34;&gt;&lt;/iframe&gt;
 &lt;/div&gt;


&lt;p&gt;This sample code is &lt;a href=&#34;https://github.com/guyc/py-gaugette/blob/master/samples/ssd1306_test.py&#34; target=&#34;_blank&#34;&gt;included in the py-gaugette library&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import gaugette.ssd1306
import time
import sys

RESET_PIN = 15
DC_PIN    = 16

led = gaugette.ssd1306.SSD1306(reset_pin=RESET_PIN, dc_pin=DC_PIN )
led.begin()
led.clear_display()

offset = 0 # buffer row currently displayed at the top of the display

while True:

    # Write the time and date onto the display on every other cycle
    if offset == 0:
        text = time.strftime(&amp;quot;%A&amp;quot;)
        led.draw_text2(0,0,text,2)
        text = time.strftime(&amp;quot;%e %b %Y&amp;quot;)
        led.draw_text2(0,16,text,2)
        text = time.strftime(&amp;quot;%X&amp;quot;)
        led.draw_text2(8,32+4,text,3)
        led.display()
        time.sleep(0.2)
    else:
        time.sleep(0.5)

    # vertically scroll to switch between buffers
    for i in range(0,32):
        offset = (offset + 1) % 64
        led.command(led.SET_START_LINE | offset)
        time.sleep(0.01)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;about-fonts&#34;&gt;About Fonts&lt;/h2&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-08/steve-jobs-does-not-approve.jpg&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;This test code uses the 5x7 bitmap font from the
&lt;a href=&#34;https://github.com/adafruit/Adafruit-GFX-Library/blob/master/glcdfont.c&#34; target=&#34;_blank&#34;&gt;Adafruit GFX library&lt;/a&gt;
scaled to x2 and x3. It works, but &lt;strong&gt;Steve Jobs would
not approve!&lt;/strong&gt;  It isn&amp;rsquo;t taking advantage of the very high resolution of these
lovely little displays.  Larger fonts with kerning would be a great addition.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Using Google OAuth2 for Devices</title>
      <link>//guy.carpenter.id.au/gaugette/2012/11/06/using-google-oauth2-for-devices/</link>
      <pubDate>Tue, 06 Nov 2012 13:03:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/11/06/using-google-oauth2-for-devices/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been working on a Raspberry Pi based device that needs to log data to a Google Docs spreadsheet.
There are some fine classes like &lt;a href=&#34;http://code.google.com/p/gdata-python-client/&#34; target=&#34;_blank&#34;&gt;gdata&lt;/a&gt; and &lt;a href=&#34;https://github.com/burnash/gspread&#34; target=&#34;_blank&#34;&gt;gspread&lt;/a&gt;
that do just this.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;However if you read the &lt;a href=&#34;http://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/connecting-to-google-docs&#34; target=&#34;_blank&#34;&gt;tutorial at Adafruit&lt;/a&gt;
which uses the &lt;a href=&#34;http://pypi.python.org/pypi/gspread/&#34; target=&#34;_blank&#34;&gt;gspread library&lt;/a&gt; you will see that
it uses the ClientLogin API for authentication, and so somewhere you need to include your Google username and password in plain text.
There are several problems with this in the context of an embedded device:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to provide a way for the user to enter their credentials on the device which may have no keyboard or GUI,&lt;/li&gt;
&lt;li&gt;The credientials are stored in a non-secure way,&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://developers.google.com/accounts/docs/AuthForInstalledApps&#34; target=&#34;_blank&#34;&gt;ClientLogin API is officially deprecated&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;I personally live in fear of accidentally committing code with plain-text credentials to GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I don&amp;rsquo;t want to use ClientLogin.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-11-06/oauth-2-sm.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;It turns out the Google&amp;rsquo;s OAuth2 implementation has a great alternative for embedded applications; &lt;a href=&#34;https://developers.google.com/accounts/docs/OAuth2ForDevices&#34; target=&#34;_blank&#34;&gt;OAuth 2.0 for Devices&lt;/a&gt;.  Here&amp;rsquo;s the high-level overview of how the authentication works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Just once, register your application with the &lt;a href=&#34;https://code.google.com/apis/console/&#34; target=&#34;_blank&#34;&gt;Google APIs console&lt;/a&gt; and get a &lt;strong&gt;client_key&lt;/strong&gt; and &lt;strong&gt;client_secret&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;When your application runs for the first time, it sends an authentication request to Google which returns a short plain-text &lt;strong&gt;user_code&lt;/strong&gt;,&lt;/li&gt;
&lt;li&gt;Your device shows the &lt;strong&gt;user_code&lt;/strong&gt; to the user and gives them instructions to enter that code at &lt;a href=&#34;http://www.google.com/device&#34; target=&#34;_blank&#34;&gt;http://www.google.com/device&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Your application starts polling a Google web service waiting for confirmation that the user has approved the application,&lt;/li&gt;
&lt;li&gt;The user enters the code to Google&amp;rsquo;s form, and confirms the level of permissions the application has requested,&lt;/li&gt;
&lt;li&gt;Your application gets a response from the web service it has been polling with an &lt;strong&gt;access_token&lt;/strong&gt; and a &lt;strong&gt;refresh_token&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You pass this &lt;strong&gt;access_token&lt;/strong&gt; in the header of all API requests&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;access_token&lt;/strong&gt; will expire after a relatively short time (1 hour?).  When the token expires,
it can be refreshed by making another API call using the &lt;strong&gt;refresh_token&lt;/strong&gt;.  This returns a fresh &lt;strong&gt;access_token&lt;/strong&gt;
but does not return an udpated &lt;strong&gt;refresh_token&lt;/strong&gt;.  The original &lt;strong&gt;refresh_token&lt;/strong&gt; does not expire.&lt;/p&gt;

&lt;p&gt;I could not find any documentation explaining how to
use the &lt;strong&gt;access_token&lt;/strong&gt; with any of the existing API libraries.
As far as I can tell Google&amp;rsquo;s python gdata library doesn&amp;rsquo;t have explicit
support for this form of authentication, but it turns out you can make it work
if you send an appropriately formatted Authorization header to the
service constructor like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;headers = {
  &amp;quot;Authorization&amp;quot;: &amp;quot;%s %s&amp;quot; % (token[&#39;token_type&#39;], token[&#39;access_token&#39;])  
}
client = gdata.spreadsheet.service.SpreadsheetsService(additional_headers=headers)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The extra header will be something like &lt;code&gt;Authorization: Bearer 1/fFBGRNJru1FQd44AzqT3Zg&lt;/code&gt;.
I&amp;rsquo;ve wrapped up what I&amp;rsquo;ve figured out so far into an
&lt;a href=&#34;https://github.com/guyc/py-gaugette/blob/master/src/gaugette/oauth.py&#34; target=&#34;_blank&#34;&gt;oauth class&lt;/a&gt;
in the &lt;a href=&#34;https://github.com/guyc/py-gaugette&#34; target=&#34;_blank&#34;&gt;python gaugette library &amp;ldquo;py-gaugette&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s an example of how it can be used to authenticate and add a row to the end of a spreadsheet.  The library saves
the authentication tokens to the local file system so that the user only has to authenticate the device once.
The explicit token-expiration handling isn&amp;rsquo;t great.  In ruby I could encapsulate that nicely using block parameters,
but I haven&amp;rsquo;t yet figured out a clean abstraction for python.
The user can revoke access to the device via &lt;a href=&#34;https://accounts.google.com/IssuedAuthSubTokens&#34; target=&#34;_blank&#34;&gt;this Google page&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import gaugette.oauth
import datetime
import gdata.service
import sys

CLIENT_ID       = &#39;your client_id here&#39;
CLIENT_SECRET   = &#39;your client secret here&#39;
SPREADSHEET_KEY = &#39;your spreadsheet key here&#39;

oauth = gaugette.oauth.OAuth(CLIENT_ID, CLIENT_SECRET)
if not oauth.has_token():
    user_code = oauth.get_user_code()
    print &amp;quot;Go to %s and enter the code %s&amp;quot; % (oauth.verification_url, user_code)
    oauth.get_new_token()

gd_client = oauth.spreadsheet_service()
spreadsheet_id = SPREADSHEET_KEY
try:
    worksheets_feed = gd_client.GetWorksheetsFeed(spreadsheet_id)
except gdata.service.RequestError as error:
    if (error[0][&#39;status&#39;] == 401):
        oauth.refresh_token()
        gd_client = oauth.spreadsheet_service()
        worksheets_feed = gd_client.GetWorksheetsFeed(spreadsheet_id)
    else:
        raise

worksheet_id = worksheets_feed.entry[0].id.text.rsplit(&#39;/&#39;,1)[1]

now = datetime.datetime.now().isoformat(&#39; &#39;)
row = {
    &#39;project&#39;: &#39;datatest&#39;,
    &#39;start&#39;  : now,
    &#39;finish&#39; : now
    }

try:
    gd_client.InsertRow(row, spreadsheet_id, worksheet_id)
except gdata.service.RequestError as error:
    if (error[0][&#39;status&#39;] == 401):
        oauth.refresh_token()
        gd_client = oauth.spreadsheet_service()
        gd_client.InsertRow(row, spreadsheet_id, worksheet_id)
    else:
        raise

print &amp;quot;done&amp;quot;    
&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    
    <item>
      <title>Analog Gauges Using I2C on the Raspberry Pi</title>
      <link>//guy.carpenter.id.au/gaugette/2012/09/14/i2c-with-raspberry-pi/</link>
      <pubDate>Fri, 14 Sep 2012 15:49:00 +1000</pubDate>
      
      <guid>//guy.carpenter.id.au/gaugette/2012/09/14/i2c-with-raspberry-pi/</guid>
      <description>&lt;img src=&#34;http://guy.carpenter.id.au/gaugette/resources/thermo_backlit.png&#34;  class=&#34;right&#34;   /&gt;


&lt;p&gt;I&amp;rsquo;ve been intending to try driving Switec X25.168 motors using the MCP23008 I&amp;sup2;C I/O port
expander chip from an Arduino, but it occurs to me that it might be more interesting
to try this on a &lt;a href=&#34;http://www.raspberrypi.org&#34; target=&#34;_blank&#34;&gt;Rasberry Pi&lt;/a&gt;.  If it works, it will demonstrate
a simple and very inexpensive method for driving analog gauges from the Raspberry Pi without
the need for high-current drivers.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The MCP23008 provides 8 I/O lines controlled via an I&amp;sup2;C interface.&lt;br /&gt;
The &lt;a href=&#34;//guy.carpenter.id.au/gaugette/resources/2012-09-14/MCP23008.pdf&#34;/&gt;datasheet is available here&lt;/a&gt;
.
The pins are rated to source and sink 20mA each.  That&amp;rsquo;s around half what an Arduino offers, but
should be (just) enough to drive our little Switec steppers.
These chips are available &lt;a href=&#34;http://www.adafruit.com/products/593&#34; target=&#34;_blank&#34;&gt;from Adafruit&lt;/a&gt;,
along with the doubly awesome &lt;a href=&#34;http://www.adafruit.com/products/732&#34; target=&#34;_blank&#34;&gt;16-port MCP23017&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since this is my first Raspberry Pi project, I&amp;rsquo;ll include detailed setup notes.&lt;/p&gt;

&lt;h2 id=&#34;step-1-installing-adafruit-s-occidentalis-kernel-image&#34;&gt;Step 1 - Installing AdaFruit&amp;rsquo;s Occidentalis Kernel Image&lt;/h2&gt;

&lt;p&gt;Adafruit have prepared a modified version of the Wheezy Linux distribution for the RPi that
includes I&amp;sup2;C tools and drivers (plus SPI, one wire, and plenty of other hackable goodness.)
The first step is to create a bootable SD card containing Adafruit&amp;rsquo;s Occidentalis image.
The following instructions are for OSX.&lt;/p&gt;

&lt;p&gt;Insert a 4GB SD card and figure out it&amp;rsquo;s device name using
&lt;code&gt;diskutil list&lt;/code&gt;.  It is easy to recognise the SD card in the list below as &lt;code&gt;/dev/disk2&lt;/code&gt;
because of the 4GB size.&lt;/p&gt;

&lt;pre&gt;
euramoo:misc guy$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                         320.1 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            319.2 GB   disk0s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk0s3
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     Apple_partition_scheme                         12.3 MB    disk1
   1:        Apple_partition_map                         32.3 KB    disk1s1
   2:                  Apple_HFS Flash Player            12.3 MB    disk1s2
/dev/disk2
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                         4.0 GB     disk2
   1:             Windows_FAT_32                         58.7 MB    disk2s1
   2:                      Linux                         3.9 GB     disk2s2

&lt;/pre&gt;


&lt;p&gt;Next unmount the disk with &lt;code&gt;diskutil unmountDisk&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;
$ diskutil unmountDisk /dev/disk2
Unmount of all volumes on disk2 was successful
&lt;/pre&gt;


&lt;p&gt;Download Occidentalis from &lt;a href=&#34;http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro&#34; target=&#34;_blank&#34;&gt;AdaFruit&lt;/a&gt;.
I&amp;rsquo;m using &lt;a href=&#34;http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/occidentalis-v0-dot-2&#34; target=&#34;_blank&#34;&gt;Version 0.2&lt;/a&gt;.
Unzip it, verify the checksum, and copy it to the SD card.  I know this a big file, but I was still surprised it took half an hour
to write to the SD card.&lt;/p&gt;

&lt;pre&gt;
$ mv ~/Downloads/Occidentalisv02.zip .

$ unzip Occidentalisv02.zip
Archive:  Occidentalisv02.zip
  inflating: Occidentalis_v02.img    

$ shasum Occidentalis_v02.img
a609f588bca86694989ab7672badbce423aa89fd  Occidentalis_v02.img

$ sudo dd bs=1m if=Occidentalis_v02.img of=/dev/disk2
Password:
...time passes
2479+1 records in
2479+1 records out
2600000000 bytes transferred in 2099.207512 secs (1238563 bytes/sec)
&lt;/pre&gt;


&lt;h2 id=&#34;step-2-test-the-boot-image&#34;&gt;Step 2 - Test the Boot Image&lt;/h2&gt;

&lt;p&gt;Boot the RPi from the newly copied SD image and log in.  The default username is &amp;lsquo;pi&amp;rsquo;, password &amp;lsquo;raspberry&amp;rsquo;.  DHCP and ssh are enabled by default
so you can login headless if you can figure out the IP address from the DHCP server.&lt;/p&gt;

&lt;p&gt;Confirm that the I&amp;sup2;C tools are installed and working by doing an I&amp;sup2;C
scan of bus 0.  You should see nothing on the bus, as shown below.&lt;/p&gt;

&lt;pre&gt;

pi@raspberrypi ~ $ sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --   

&lt;/pre&gt;


&lt;h2 id=&#34;step-3-wire-up&#34;&gt;Step 3 - Wire Up&lt;/h2&gt;

&lt;p&gt;The Raspberry Pi expansion port pinout is:&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-09-14/raspberrypi.png&#34;   /&gt;


&lt;p&gt;The MCP23008 pins are:&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-09-14/MCP23008.png&#34;   /&gt;


&lt;p&gt;There are 4 wires connect the RPi to the MCP23008:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SDA RPi pin 3 to MCP23008 pin 2&lt;/li&gt;
&lt;li&gt;SCL RPi pin 5 to MCP23008 pin 1&lt;/li&gt;
&lt;li&gt;5V RPi pin 2 to MCP23008 pin 18&lt;/li&gt;
&lt;li&gt;GND RPi pin 6 to MCP23008 pin 9&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that I&amp;rsquo;m powering the chip from 5V instead of the 3.3V because
I want to power the motor windings at 5V.  I have read that there
is no problem connecting 3.3V and 5V circuits over I&amp;sup2;C.&lt;/p&gt;

&lt;p&gt;In addition you must make the following connections on the chip.
It is very important that you do not let the address pins or the reset pin float!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP23008 address pins 3,4,5 to Vdd or Vss to set the bus address.&lt;/li&gt;
&lt;li&gt;MCP23008 reset pin 6 to Vdd.  Pull it high.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need current limiting resistors on the address or reset pins and the RPi
has built-in pull-up resistors on SDA and SCL so you do not need to provide them.  Too easy, right?&lt;/p&gt;

&lt;p&gt;The I&amp;sup2;C 7-bit address will be binary &lt;code&gt;[ 0 0 1 0 A2 A1 A0 ]&lt;/code&gt; so
if all address lines are pulled to ground it will be at 0x20, if they
are all high, it will be at 0x27.  I&amp;sup2;C addresses are sometimes confusingly
left-shifted 1 bit and expressed as 8-bit addresses,  which are 2x the 7-bit
address, like this &lt;code&gt;[ 0 1 0 A2 A1 A0 0 ]&lt;/code&gt;.  Can&amp;rsquo;t we all just get along?
Side note - if you are reading I&amp;sup2;C protocol diagrams, I&amp;sup2;C sends the most
significant bit first.&lt;/p&gt;

&lt;h2 id=&#34;step-4-probe-it&#34;&gt;Step 4 - Probe It&lt;/h2&gt;

&lt;p&gt;Power up and repeat the &lt;code&gt;i2cdetect&lt;/code&gt; command.  This time you should
see device on the bus.  Mine is at 0x20 because I pulled all of the
address lines low.&lt;/p&gt;

&lt;pre&gt;

pi@raspberrypi ~ $ sudo i2cdetect -y  0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                         

&lt;/pre&gt;


&lt;p&gt;You can read the IODIR register (0) which should return all 1&amp;rsquo;s
(all pins configured as inputs), and the OLAT register (10 or 0xA) which should return all 0&amp;rsquo;s.&lt;/p&gt;

&lt;pre&gt;
pi@raspberrypi ~ $ sudo i2cget -y 0 0x20 0
0xff
pi@raspberrypi ~ $ sudo i2cget -y 0 0x20 10
0x00
&lt;/pre&gt;


&lt;h2 id=&#34;step-5-spin-a-motor&#34;&gt;Step 5 - Spin a Motor!&lt;/h2&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-09-14/raspberrypi_and_mcp23008.png&#34;   /&gt;


&lt;p&gt;I wired up a VID29 to pins GP0 to GP3 on the driver chip and kludged
together some C code to cycle through the 6 signal states used to drive the motor.
I&amp;rsquo;m using a VID29 motor with the &lt;a href=&#34;//guy.carpenter.id.au/gaugette/blog/2012/04/04/pulling-out-the-stops/&#34;&gt;stops removed&lt;/a&gt;
so I can let it spin continuously without hitting the stop.
The &lt;a href=&#34;https://gist.github.com/3735664&#34; target=&#34;_blank&#34;&gt;test code is here&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;
$ sudo ./i2ctest
Register 0 = 255
Register 1 = 0
Register 2 = 0
Register 3 = 0
Register 4 = 0
Register 5 = 0
Register 6 = 0
Register 7 = 0
Register 8 = 0
Register 9 = 0
Register 10 = 0
done
error writing i2c gpio register
error writing i2c gpio register
...
&lt;/pre&gt;


&lt;p&gt;Yeah, so those errors aren&amp;rsquo;t good.  The results of reading the 10 registers
look fine, but as soon as it starts trying to turn the motor we are
getting errors.  After some fiddling I confirmed that
the errors only happen when the motor is attached, so it looks like the
RPi&amp;rsquo;s 5V power rail isn&amp;rsquo;t able to supply the necessary current.  This is
&lt;a href=&#34;http://www.raspberrypi.org/phpBB3/viewtopic.php?t=12498&amp;amp;p=151035&#34; target=&#34;_blank&#34;&gt;not actually a surprise&lt;/a&gt;,
and it isn&amp;rsquo;t a big problem either.&lt;/p&gt;

&lt;p&gt;I happen to have a &lt;a href=&#34;http://adafruit.com/products/658&#34; target=&#34;_blank&#34;&gt;beefy 10A 5V supply&lt;/a&gt; on the bench,
so used that to power the MCP23008.  Problem solved, motor turns, errors are gone.&lt;/p&gt;

&lt;p&gt;This is the final circuit.&lt;/p&gt;

&lt;img src=&#34;//guy.carpenter.id.au/gaugette/resources/2012-09-14/circuit_bb.png&#34;   /&gt;


&lt;h2 id=&#34;speed-tests&#34;&gt;Speed Tests&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NOTE: Since writing this I discovered that the supply voltage used in these tests
was down-regulated to around 3.9V instead of 5.0V, which accounts for the disappointing
speeds noted below.  I will repeat these tests when I get a chance.
Initial tests indicate that at a full 5.0V the motor has roughly the
same speed limits when driven by the MCP23008 as it does when
driven directly from Arduino digital IO ports.
It is also worth noting that the overhead for sending each motor pulse update
over I&amp;sup2;C is about 400&amp;mu;S.  This could probably be improved using byte mode
(to avoid sending the register address over I&amp;sup2;C on each update) or by selecting
a higher I&amp;sup2;C baud rate.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have previously measured &lt;a href=&#34;//guy.carpenter.id.au/gaugette/blog/2012/05/08/how-fast-is-it/&#34;&gt;the maximum speed&lt;/a&gt;
that the Arduino can turn a VID29 stepper when driving directly from the I/O pins,
and found it was a little over 500&amp;deg;/S.&lt;/p&gt;

&lt;p&gt;I repeated these tests with the RPi and found a maximum speed of around 215 &amp;deg;/S,
presumably lower because of the reduced current capacity. (Correction - it is due to
an accidentally low supply voltage.  See above.)
I tried ganging two pins from the MCP23008 to each of the motor pins, thinking
I might squeeze a little extra current out of the chip.  That boosted the maximum
speed a little, but still fell well short of the Arduino.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Min &amp;mu;S/step&lt;/th&gt;
&lt;th&gt;Max &amp;deg;/S&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Arduino&lt;/td&gt;
&lt;td&gt;649&lt;/td&gt;
&lt;td&gt;513&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;RPi + MCP23008&lt;/td&gt;
&lt;td&gt;1550&lt;/td&gt;
&lt;td&gt;215&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;RPi + MCP23008 paired pins&lt;/td&gt;
&lt;td&gt;1426&lt;/td&gt;
&lt;td&gt;233&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&#34;conclusions&#34;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;The MCP23008 will indeed drive a Switec X25.168 (or clone)
but the limited current capacity means that the motor&amp;rsquo;s maximum speed is
noticably less than when driving from an Arduino.&lt;/p&gt;

&lt;p&gt;If you aren&amp;rsquo;t bothered by the reduced maximum speed, you can drive lots
of these little stepper motors without running out of I/O pins.
One very tidy solution would be to use the &lt;a href=&#34;http://macetech.com/store/index.php?main_page=product_info&amp;amp;products_id=23&#34; target=&#34;_blank&#34;&gt;Centipede Shield&lt;/a&gt;
which would in theory drive up to 16 motors per shield - although at some point you will probably
hit CPU limits trying to service the I/O.&lt;/p&gt;

&lt;p&gt;Not surprisingly, the 5V power rail on the Raspberry Pi isn&amp;rsquo;t up to powering even one
micro stepper, but the MCP28003 conveniently allows us to inject 5V power from a separate supply,
so that isn&amp;rsquo;t a serious problem.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>