Bluetooth Low Energy (BLE) on the Raspberry Pi

Bluetooth Low Energy – BLE – Bluetooth 4.0 is an industry-standard wireless protocol built for the Internet of Things – IoT, it is designed to provide connectivity for devices operating from low capacity power sources such as coin cell batteries.

Raspberry Pi2 with ASUS USB-BT400 Bluetooth 4.0 Dongle

In this introduction to BLE I’ll be configuring a Raspberry Pi2 computer to talk to a smart watch. We will be installing the latest version of BlueZ from source, enabling BLE support. This is not a tutorial on decoding the data from the watch I am just using it as an example, although I may write about decoding it in a future posting.

I am using a ASUS USB-BT400 Bluetooth 4.0 Dongle on a Raspberry Pi2 but this will work on any computer with a Debian based distribution. Your dongle must be BLE/Bluetooth 4.0 capable otherwise this won’t work. I am using an ID107HR activity tracker with pedometer and heart rate monitor, randomly chosen from the list of cheap ones available on Amazon. While using the Pi to talk to the the watch make sure Bluetooth on the phone is off as it can only connect to one device at a time.

The current distribution of Raspbian – jessie on the Raspberry Pi comes with version 5.23 of the BlueZ Bluetooth stack that’s rather old, dating from September 2014 which lacks many of the features we will be needing. The current version 5.44 of the BlueZ has many changes in the package with many familiar components such as hcitool and gatttool being depreciated, so I will be ignoring those and using the available commands, bluetoothctl, on the terminal.

Installing BlueZ

With Raspbian – jessie installed we will need to update the Pi make sure some packages are installed and then installing the latest version of BlueZ. But first, remove the installed version 5.23 of BlueZ:

Next, perform the traditional housekeeping updates then install the build tools and USB libraries. Those parts that are installed already will be automatically skipped.

Now, download the source code, at time of writing the current stable release is version 5.44, check the BlueZ site for the latest version.

Inside the BlueZ directory, configure, make (this takes a while), and install. The experimental option adds BLE support and enabling the library allows for python use later on:

Configuring and Starting BlueZ

At this stage we will need to check that the installation worked and that we can see your bluetooth dongle. With your bluetooth dongle in a USB port you should see it on your list of USB devices, here you see mine as device ID: 0b05:17cb ASUSTek Computer, Inc.:

You will also need to enable the experimental services, edit the file /lib/systemd/system/bluetooth.service and in the [Service] section change the ExecStart line to end with –experimental:

Start the bluetooth service, and while we are at it enable it to load on boot:

Once started, check the status of the bluetooth daemon with:

Should you need to, the service can be stopped and prevented from loading on boot with:

Finally, you may want to enable auto-power on for the device, to do so create this bluetooth config file:

and add these two lines:

You should restart the Pi at this point and check that the daemon has loaded properly with sudo systemctl status bluetooth

Testing BlueZ

Start the bluetooth controller, you should see your dongles MAC address and alias:

for first time use, try scanning to find your watch, if it doesn’t appear it is out of range, its battery is flat, or your dongle does not support BLE, here you can see it as ID107 HR:

bluetoothctl remembers your devices, so when you next use the program the watch appears on the list at the start. The controller has a number of options, these can be seen with help command. You can use show to view the status of your dongle:

The list of UUID’s show the services supported by the Dongle. Now we can power the dongle on, set the agent – this manages the connection, and then connect to the watch on which the bluetooth symbol will appear. Once connected there will be a pause then you will see a list of attributes supported by the watch, it is advertising the services available:

and now that we have connected we can ask for some info:

These UUID’s are used to describe the sevices available on the device, some are pre-defined and can be found in the a href=”https://www.bluetooth.com/specifications/gatt/characteristics” target=”_blank” rel=”noopener noreferrer”>GATT schema, others are vendor specific and unless they publicly release these, decoding can become rather difficult. There are four types of attribute:

  • Services – collections of characteristics and relationships to other services that encapsulate the behavior of part of a device
  • Characteristics – attribute types that contain a single logical value
  • Descriptors – defined attributes that describe a characteristic value
  • Declarations – defined GATT profile attribute types

Each attribute is identified by a 128 bit ID, for example, one of the characteristics from the list above: 00002902-0000-1000-8000-00805f9b34fb, the first eight bits are used as an unique identifier: 00002902 and are shown as UUID’s: 0x2902. Data is contained in services, each service has a number of characteristics that may contain further descriptions depending on the requirement of the characteristic. You can see how the data is mapped out in this chart:

Service Containers

A spreadsheet with the watch data reformatted and tastefully coloured to illustrates this. Observe the Service URL column, it looks a lot like a directory structure:

Here we see two services /service0008 and /service000c looking further into the second service: /service000c we see that it has four characteristics, and to of those have descriptors. We can interrogate the characteristics and descriptors to glean further information by selecting the attribute and reading, like so:

Which is all very nice, but not particularly helpful as the manufacturer has chosen to use custom, proprietary, UUID’s for the watch. We don’t know the instructions to send to have the watch realease its data.

Those Scripting BlueZ

Inevitably, you’ll be wanting to automate connections. This becomes easy with the automation scripting language expect. Install, then make a script file:

In this example the script forgets the watch, finds the watch, connects to the watch, gets some info and then disconnects:

in the script, send sends a command, don’t forget to add the carriage return – \r and expect is used to wait for a response within the timeout period, here it is set to 10 seconds. expect -re is using regex when looking for a reply, otherwise it uses a literal string. So much more can be done with expect and there are many tutorials, such as this one written by FluidBank.

More Bluetooth Data

For analysing bluetooth data a couple of very useful tools are available, Wireshark and Android data logging. I will go through the installation but not look at the data in any detail, this posting is getting a bit long. This Section is in two parts, installing Wireshark and Android Debug Bridge.

Sniffing with the Shark
Wireshark is a network and bluetooth packet sniffer, it shows you network and bluetooth traffic occurring on your Pi. Here is a quick installation method for a reasonably new version of Wireshark (v2.2.4) from the backports, answer yes to the question “Should non-superusers be able to capture packets?”:

and if you get a message about permissions, reconfigure the package and answer yes:

Start Wireshark and double click your bluetooth device on the list, in my case bluetooth0. There is not much to see as Wireshark will only see traffic between the watch and the Pi:

Wireshark Data Capture

Android Debug Bridge – ADB
For Anroid 4.2.2 and above, activate developer mode on the phone, go to Settings, tap About Phone and at the bottom of the list tap Build Number three times. Back in the main settings page Developer Options has appeared, tap developer and turn USB debugging On. With the phone plugged into a USB port a little Android head should appear in the information bar at the top-left of the screen. To begin we will need to install some udev rules written by Nicolas Bernaerts:

Install the android tools, confirm that you have at least version 1.0.31, and start ADB

At this point on the phone an allow USB debugging dialog will appear, give permission and always trust to authorise it. ADB will now show the device as a device:

If the device list is empty, with everything plugged in good and proper and the phone setup in developer mode, start your diagnosis by checking udev; open another terminal window and view logging with udevadm monitor –environment and reload with sudo udevadm control –reload I’m not entirely sure what I did to get it from ‘not working’ to ‘working’. If all else fails elevate yourself to root.

Data Capture
With ADB now setup we can capture the Bluetooth data being exchanged. With bluetooth off, in the Developer Settings find Enable Bluetooth HCI snoop log and turn it On. In the smartwatch app synchronise with your watch, once complete turn Bluetooth off manually – this is to minimise the amount of captured data. Don’t forget to turn logging off on the phone when done. To find where the log file has been stored and copy the file from the phone to the Pi use:

We can now use Wireshark to read the log file…

Wireshark reading the Android Bluetooth Log

This wasn’t quite the posting I originally had in mind, I wanted to decode the data from the watch for my own use, making something more useful, impressive graphs and charts, than that provided by the Android App VeryFit 2.0 but as the manufacturer has chosen to use proprietary GATT codes it makes the job that much harder. It may be much simpler to just buy an expensive FitBit and download the data from them. But with writing this I now know a few things that were previously unknown, and I hope that this has provided some light to your BlueZ (a pun!, right at the end!).

Links and Sources

Controlling the Zoom H2n Audio Recorder with Arduino

In Part One I covered the byte codes sent by the Zoom Remote Controller RC1 and decoded data sent over the wire to the remote from the Zoom H2n Recorder.

In this post I will be covering the use of an Arduino style micro-controller to decode the signals sent by the remote, then control the recorder. I have used a Tennsy 3.1 Arduino clone as this is a small controller with two additional hardware serial ports, works with 3.3volt logic, and a with the addition of a crystal and button battery a real-time clock.

Arduino control of the Zoom H2n

Setup and Connections

The connections on the remotes four pin 2.5mm jack, with pin one being the tip:

  1. Remote Receive – RX
  2. Remote Transmit – TX
  3. Ground
  4. 3.1V – Power

On the Teensy there are two hardware serial UARTs available in addition to that used by the USB port, UART2: Pin 9 (RX2), Pin 10 (TX2) and UART3: Pin 7 (RX3), Pin 8 (TX3). Serial data is sent at 2400 baud, 8 bits, no parity, 1 stop (8n1). The response data shown is for when the recorder is in XY Stereo mode (0x20, 0x21), different codes are returned when other recording modes are used, see the end of Part One for details.

Serial Monitor

This first chunk of code is for monitoring the outputs of the remote control and recorder. Connect Remote Receive – RX on the remote to RX2 – Pin 9 on the Teensy and Remote Transmit – TX to RX3 – Pin 7 and Ground to Ground on the Teensy. This program will output data received to the Arduino IDE’s serial monitor.

The output is in four columns; the UART seeing activity, current milliseconds and the received data in hexadecimal and decimal values.

Taking Control – But Not Listening

Sending the command to the recorder blindly is quite straight forward, just send the bytes to the Remote Transmit – TX pin on the recorder (Zoom RX). This can be seen in the following, when run it starts the recorder recording for ten seconds. Connect: Remote TX to TX2 on the Teensy, Remote RX to RX2 and Ground to Ground.

Taking Control – And Listening for a Reply

The next stage is to have the Teensy control the Zoom and listen for a response from the recorder. Again, as before connect: Remote TX to TX2 on the Teensy, Remote RX to RX2 and Ground to Ground. For the demonstration I have added three buttons to act as the controller.

Zoom Control with three buttons

The following code needs more development work, I ran out of time, but I think gives a good starting point for further investigation. I have placed the commands for the remote in a structure, each command; record, pause and mark has four components, the command to transmit to the Zoom, the expected responses when starting and stopping and a flag to store the status.

There is a problem when resuming from pause, because the Zoom sends codes to flash the LED on the remote this can pick up the wrong pair of bytes; such as 0x21 0x21 instead of the expected 0x20 0x21.

I expect to be revisiting this, adding a timer function plus external battery for long running. I’m not sure how useful listening for a response is, sending the record command toggle on its own seems fairly robust without the need to check.

Links and Sources

Hacking the Zoom H2n Remote Control

The Zoom H2n is a portable sound recorder looking like an old fashioned microphone it is a handheld device that provides an assortment of stereo and surround recording modes, it records onto an SD card in MP3 or WAV format with options for various bitrates and frequencies. The unit is powered internally by two AA batteries and can also be powered from the USB port. The recorder I am experimenting on has firmware version 2.00 installed.

A not at all contrived image of the Zoom H2n Portable Recorder

The Zoom Remote Controller RC2 is a wired four pin 2.5mm jack plug connection, this remote has three buttons: record, mark, and pause there is also an LED to show when the H2n is recording. It is purchased separately from the recorder and only appears to be available bundled in an accessory pack. It looks difficult to take apart without leaving some damage, and this may not be necessary for decoding.

Zoom Remote and breadboard for testing

In this post I am looking to see how the remote works and find what control method it employs so in Part Two I can use an Arduino style micro-controller to provide an external trigger such as for timed recordings.

Setup for Testing

For testing I have made a breakout lead, this is essentially an extension cable split in half with a couple of molex style connectors allowing me to plug it into a breadboard. With this I have found the cable has the following connections, with pin one being the tip of the 2.5mm jack plug:

  1. Remote Receive – RX
  2. Remote Transmit – TX
  3. Ground
  4. 3.1V – Power

When checking with a multimeter I found continuity from the negative of the left battery (on the Mic Gain side) to pin three, ground, of the jack, there is also a connection between the positive of the right-hand battery to pin one of the jack but on the multimeter in diode mode there looks to be a capacitor, the voltage rises until no apparent connection is indicated. With no activity on the recorder the RX and TX pins show ~2.7 volts.

Determining the RX and TX pins turned out to be straightforward. When you press the record button after a moment the recording LED lights up, on the oscilloscope I can see three different square wave patterns for the three different buttons on the TX pin and a single type of square wave on RX to light the LED. The following images show the signal for the record button then that sent in response to to light the LED.

Signal sent by the remote when Record pressed
Signal sent by the Zoom recorder to light the LED in the remote

Also when buttons are pressed on the recorder data is seen on the RX line. For a more detailed examination I will need to break out the logic analyser.

Signal Analysis

Following some research where the remote for a Zoom H4n was examined, I set both channels being used on the logic analyser to the following:

  • Protocol: UART
  • 2400 baud, 8 bits, no parity, 1 stop (8n1)
  • Bit Order: LSB first, inverted logic: No
Decoding of the first part of the stop recording command

First I decoded the buttons on the remote with the trigger on the logic analyser set to falling edge on the Remote TX line. On TX there is a pause between the two pairs of command bytes which appears to be the length of time the button was pressed, around 350-500ms, there is also a pause between bytes in the RX response, the value of the response changes depending on which recording mode you are in, those shown below are when the recorder is in XY Stereo:

Record Start
TX: 0x81 0x0 ~ 0x80 0x0
RX: 0x20 1.85s 0x20 0x21 record LED on
Record Stop
TX: 0x81 0x0 ~ 0x80 0x0
RX: 0x21 0x21 0x20 1.9s 0x20 0x20 record LED off
Pause (while recording)
TX: 0x80 0x2 ~ 0x80 0x0
RX: 0x21 51ms 0x21 0x20 then this repeats
492ms 0x20 0x21 to flash the LED
492ms 0x21 0x20 until pause is pressed again
Resume from Pause
TX: 0x80 0x2 ~ 0x80 0x0
RX: 0x21 0x21 LED on
Mark
TX: 0x80 0x1 ~ 0x80 0x0
RX: 0x21 492ms 0x20 0x21 LED on

I was also able to capture the following activity sent to the remote when various buttons were pressed on the recorder itself with the recorder in XY Stereo mode. Other models of the recorders made by Zoom have more advanced remotes, such as the RC4 as featured in this hack of the H4n. I suspect they would work on this machine too. This time I set the logic analyser to trigger with a falling edge on Remote RX. I think the 0x20 code is used to indicate the display illumination has been turned off. I saw activity on all buttons except the Mic Gain knob.

Power On – Without remote attached
TX: Lots of random activity
RX: 0x10 400ms 0x80 0x81
1.2s 0x10 0x0 0x80 0x0
140ms 0x0 0x0 0x80 0x80 0x0
~2ms 0x0 0x80 0x0 0x0 0x80 0x0
Power On – With remote attached
TX: 0x0 five pulses 30ms apart
30ms 0x0 0xA1 0x80 0x0 0xA1
RX: following pulses on TX 0x80 0x81 0x80 0x10
1.2s 0x10 0x0
148ms 0x0 0x0
~4ms 0x0 0x0 0x0
Record Start
RX: 0x20 20ms 0x20 0x21 LED on
Record Stop
RX: 0x21 0x21 0x21 0x20 ~ 0x20
~283ms 0x20 0x20  LED off
Menu \ Home – Into Menu
RX: 0x20 0x20 0x0
Exit from Menu
RX: 0x20 45ms 0x20
Play Switch: Up/Down/Press
RX: 0x20 55ms 0x20
Clipping detect (tapping the microphone with a pen)
RX: 0x10 0x2 56ms 0x2
59ms 0x10
60ms 0x10
354ms 0x10
Volume: Up and Down
RX: 0x20
Recording Mode Change: 4 channel surround
RX: 0x10 0x10 0x30 14ms 0x30 0x30
122ms 0x34
60ms 0x30
60ms 0x30
Recording Mode Change: XY Stereo
RX: 0x30 0x30 0x20 216ms 0x20
Recording Mode Change: 2 channel surround
RX: 0x20 0x20 0x30 0x30 18ms 0x30
148ms 0x30
164ms 0x30 0x6
56ms 0x14 0x30
477ms 0x30
Recording Mode Change: MS Stereo
RX: 0x30 0x30 0x10 170ms 0x10
50ms 0x12

I think these response codes are to light up various LED’s on the more advanced Zoom RC4 remote, this suggests that other remotes would work in this recorder.

The following table shows the response codes given with different microphone configurations when record is clicked to start recording:

TX: 0x81 0x0 ~100ms delay 0x80 0x0
XY Stereo: 0x20 750ms delay 0x20 0x21
2 Channel Surround: 0x30 750ms delay 0x30 0x31
MS Stereo: 0x10 750ms delay 0x10 0x11
4 Channel Surround: 0x30 750ms delay 0x30 0x31

In Part Two I will be covering the use of a Arduino style micro-controller as an alternative remote control.

Links and Sources

Fixing the Arduino incoming network connections error on the mac

On the Apple Mac if you use the Teensy micro-controller with the Arduino IDE you may have come across a persistent firewall error message when starting the IDE, I have seen this error for quite a while over a range of system and software upgrades. I have applied this fix to:

  • OS X 10.10 Yosemite and above / macOS 10.12 Sierra
  • Arduino IDE 1.6.13 – all versions, at least 1.5 and above.
  • Teensydunio 1.33 – and older versions

The Arduino IDE is installed in the default applications folder, as is the Teensyduino. Some knowledge of using the terminal is required.

Symptoms

On your Apple Mac, you installed the Teensyduino software for the Teensy and now when you start the Arduino IDE this error message appears:

Do you want the application “Arduino.app” to accept incoming network connections?
Clicking Deny may limit the application’s behaviour. This setting can be changed in the Firewall pane of Security & Privacy preferences.

Incoming Network Connections Error

Cause

When the Arduino IDE is installed it includes a certificate to assure the system that everything is correct, the Teensyduino installation makes changes to the IDE configuration and this causes a mismatch and the signature in the certificate does not match the installation.

You can verify the failed certificate in the terminal with the spctl command:

Without the Teensyduino software installed, the certificate shows correctly:

Another check is to use codesign

Fix

To fix this, first we need to create a self-signed certificate. In finder Keychain Access can be found in Applications > Utilities > Keychain Access

Keychain Access certificates

From the menu choose: Keychain Access > Certificate Assistant > Create a Certificate… and set the following:

  • Name: anything useful, without spaces. You will be using this name later to apply the certificate – I used ‘arduino’
  • Identity Type: Self Signed Root
  • Certificate Type: Code Signing
  • Check the box “Let me override defaults”, this is important
Certificate Creation

click continue, and continue again past the security warning, then over the next few pages:

  • Serial Number: 1 – The serial and certificate name combination must be unique
  • Validity Period: 3650 – this will give you ten years
  • Email, name, etc: anything you like, or leave blank
  • Key pair info: set to RSA, 2048 bits
  • On the next four screens, from “Key usage extension” to “Subject Alternate Name Extension” accept the defaults
  • Location: login keychain.

Once created and back in the list, choose your certificate and from the menu go to File > Get Info (Cmd-i). In the Trust section at the top change: When using this certificate to Always Trust.

Trusted Certificate

Now that the certificate has been created, you need to apply it to the application, in terminal use the codesign command, this takes a few moments:

You’ll be asked to verify this, click ‘always allow’. To verify that your certificate has worked, check with codesign, using spctl will not work as this is a self-signed certificate.

Now, when you start the IDE on first run it will give you the allow/deny message again, click Allow and on subsequent use it will open as expected.

Links and Sources

Exploring Interrupts on the Arduino

Interrupts are a handy way of having the micro-controller listen for triggers and respond to them, instead of polling, constantly checking, the controller listens while getting on with other things, this is analogous to when the door bell rings you interrupt what you are doing to answer the door rather than repeatedly going and checking the door every few minutes to see if anyone is there. The interrupt is handled by micro-controller hardware and reacts very quickly and efficiently to a detected event, different micro-controllers have different interrupt pins available, for example the one used in the original Uno only has two digital pins available but on more recent models such as the Genuino 101 or the Teensy 3.2 all digital pins can be used.

In your program when an interrupt is triggered the action performed by your function – the Interrupt Service Routine (ISR) should be kept simple so as not to keep the controller occupied and possibly miss other trigger events, interrupts are for listening and monitoring to tell your main program that something has happened. The micro-controller can react to four different types of trigger:

  • LOW – trigger whenever the pin is low
  • CHANGE – trigger whenever the pin changes value
  • RISING – trigger when the pin goes from low to high
  • FALLING – when the pin goes from high to low

Square Wave Edges
Square Wave Edges

On the oscilloscope screen above we can see these conditions on a square wave, the change trigger can be said to be all the corners. If your input is being pulled high and goes low when triggered (as shown), then choose Falling or Low, it is better to detect a falling or rising edge as using low can cause the interrupt to trigger multiple times for the duration of the low state.

Hardware

To illustrate the use of interrupts I have written a program to find the rotation and wind speeds of a 30cm Desk Fan. To do this I added a hall effect switch and magnet to find the rotation speed of the blades and bought a cheap Anemometer to find the speed of air being pushed out by the fan.

Circuitry for the Hall Effect Switch, Anemometer and monitor LED's
Circuitry for the Hall Effect Switch, Anemometer and monitor LED’s

To monitor the speed of the fan I have used a A1120EUA-T Hall Effect Switch and 10K pull-up resistor and glued this to the body of the fan near the motor shaft and on the shaft itself glued a small magnet.

Glued to the fan is a Hall Effect Switch with pull-up resistor and magnet on fan shaft.
Glued to the fan is a Hall Effect Switch with pull-up resistor and magnet on fan shaft.

The Anemometer is not particularly robust and could be seriously damaged by a pigeon. Taking the cap off you will find a bearing to allow the top to rotate freely as well as a magnet, inside there is a small reed switch that closes every time the magnet passes over it. I have connected this to the Teensy in the same way as would a button switch with a pull-down resistor.

The cheap Anemometer
The cheap Anemometer
Reed Switch inside the Anemometer
Reed Switch inside the Anemometer

The the reed switch in the anemometer creates a bit of noise when it closes as you can see on the oscilloscope below, these are picked up as false positives by the micro-controller and will give you bad readings. Fortunately this can be fixed in software by having the interrupt handler ignore further events for a few milliseconds.

Reed switch noise, after the first rise when the switch closes, the contacts bounce about for a short while before settling.
Reed switch noise, after the first rise when the switch closes, the contacts bounce about for a short time before settling.

A thing I found useful when testing this was to have the multimeter set to its frequency counter (Hz) and check that roughly the same cycles per second were displayed on the meter and on the Arduino serial out.

Software

The Arduino commands to look out for are attachInterrupt and digitalPinToInterrupt to convert the named digital pin as you see on the board/piece of card to the interrupt name used by the controller. There are a few rules to remember when using interrupts:

  • Keep it simple – the function – Interrupt Service Routine (ISR) called by your interrupt should be short and simple, any extra data processing should be done in the main program.
  • Delay() won’t work, and don’t use Serial.print()
  • Make variables shared with the main code volatile – this tells the complier that the variable can change at any time, so it must be reloaded every time its referenced.

Data

Here is a chart of the information gathered, it might even be interesting for someone with an interest in aerodynamics, anemology or something. The fan is a three speed SFC-300BP 12″/30cm Air Circulator and the Anemometer was placed one meter away from the fan positioned to capture the strongest wind.

fan anemometer
setting RPM Hz RPM Hz m/s
1. 1045 17 150 2.5 1.10
2. 1223 20 201 3.35 1.47
3. 1366 22.7 214 3.5 1.5

I took 60 readings for each fan speed then averaged them, in my program I used the following formula to work out the wind speed from the Anemometer in meters per second:

    \[ v = \frac{2\pi rN}{60}\]

where:

v = velocity in meters per second
r = radius in meters – distance from the centre to the middle of the cup
N = Revolutions Per Minute (RPM)

Links & Sources

More than one MCP23017?

I have a had a few requests on how to add more than one MCP23017 port expander to the Arduino via the i2c bus, this chip is a very useful and easy to use component that adds up to 16 digital I/O ports to the Arduino. This demonstration uses two MCP23017’s with three LEDs for output, one RGB LED to loop through a selection of colours, a single colour that blinks on and off, and another RGB LED that is controlled by a four button keypad. I have written the program using the millis() timer rather than the delay() function to maintain the illusion of multi-tasking.

Two MCP23017s and a Teensy
Two MCP23017s and a Teensy

Addressing the MCP23017

The port expander has a three pins, A0, A1, and A2 for which an address can be set, each MCP23017 on your i2c bus must be set to have its own address, this is a three bit address and up to eight expanders can be used. Although I suspect things may noticeably slow down as you add more expansion. There is an SPI version available, the MCP23S07, that may be better for use with larger setups.

MCP23017 pinout

The address connections are shown the chart below, where zero is a connection to ground and one is a connection to 5V (or 3.3 volts). The MCP Address column refers to the address used by the Adafruit driver as you will see later.

chip
address
hardwired address i2c
address
MCP
address
A2 A1 A0
000 GND GND GND 0x20 0
001 GND GND 5v 0x21 1
010 GND 5v GND 0x22 2
011 GND 5v 5v 0x23 3
100 5v GND GND 0x24 4
101 5v GND 5v 0x25 5
110 5v 5v GND 0x26 6
111 5v 5v 5v 0x27 7

In my circuit I have assigned the first expander address 0x20 and the second 0x21.

Powering the Expanders

The port expander has been designed to run on a supply of 2.5v to 5.5v, so using a 5v supply from the USB port should be OK for a modest number of LED’s, you will need to calculate what your power requirements will be, approx 20mA per LED, so in this demonstration: 7 LED’s x 20mA = 140mA, plus whatever the chip itself is using. Bear in mind that each GPIO pin on the expander can only handle a maximum of current 25mA, and that the maximum total power dissipated must not exceed 700mW (after which point it’ll let the magic smoke out).

A Teensy 3.2 has a 3.3V supply but this is rated at 250mA maximum, the Ardunio UNO looks to be around 450mA on the 5V and only 50mA on the 3.3V output. For running from a battery I would look to use a 6v supply and a buck converter such as this Pololu step-down regulator.

The Hardware

On the left we see the Arduino UNO with the two i2c wires coming from pins A4 – SDA and A5 – SCL, two 4.7K ohm resistors are used for pullup, the port expanders are daisy chained along this bus, using pins 12 – SCL and 13 – SDA. See how the addresses are set on pins 15, 16 and 17, and note the 1K ohm resistor on the reset pin (18), without this resistor the circuit will work for a while then stop. The GPIO pins are connected as appropriate and the button switches do not need pull-up resistors as the port expanders internal pull-ups are turned on in the software.

Connecting two MCP23017 port expanders
Connecting two MCP23017 port expanders (click to enlarge)

Also if you are using RGB LED’s you will want to adjust the values I have given here, different colours have different power requirements so different resistor values are required to get a properly balanced colour LED. The RGB LEDs I have used are common anode, 5v is applied to the common and the path to ground to through the expander, this inverts the logic so setting the pin HIGH turns the LED off, and LOW turns it on.

The Software

The Adafruit MCP23017 library assigns each GPIO pin a number as you can see in the following diagram:

MCP23017 pin assignments

On both expanders the RGB LEDs are on ports 8,9 and 10 (to save me writing separate code for each RGB LED), the blink LED on port 7 of the first expander, and the buttons occupy ports 4, 5, 6, and 7 of the second. The first three buttons are used to toggle the red, green and blue in the second RGB LED while the fourth turns them all off. The other two LEDs are just doing things to show that they can do stuff.

Links

Captive Nut How-To

A quick captive nut how-to, for when you are making a wooden box that has a lid you need to remove on an irregular basis. Wood screws tend to maul the wood after a while and then the lid falls off, these captive nuts are easy to do and just work.

You will need:

  • Nut and bolt
  • two part expoy adhesive
  • drill bit as large as the nut and a drill
  • Vaseline or any other petroleum jelly
parts needed
parts needed

In this example I am using an M4 nut and bolt and an 8mm drill bit. You may need to cut your bolt to length.

1. Drill your hole
in this case about 1 cm, deep enough so when you insert the nut and bolt the expoy will cover the nut. Clean it up, removing wood shavings and other debris.

Hole Drilled
Hole Drilled

2. Grease Up
To prevent the expoy sicking to the bolt smear some Vaseline onto your bolt, only a small amount is required, but you should get it into the thread, make sure you keep the nut clean. Thread the nut back onto the bolt, leaving 4-5mm of bolt protruding, as shown:

grease your bolt
grease your bolt

3. Mix up the Expoy
Mix a blob about the size of a marrowfat pea, enough to fill half of the hole. Drizzle this into the hole.

drizzle the expoy
drizzle the expoy

4. Plunge the nut and bolt into the hole
Wiggle it about a bit to make sure the expoy is well distributed. Position the bolt how you would like and leave to set. If you see the bolt moving use some sticky tape to hold it in place.

plunged bolt
plunged bolt

5. Remove the bolt
After about 10 to 15 minutes, the expoy will have set (unless you got that weird stuff). Use a screwdriver for at least the first turn as there will be a little adhesion, but it’ll come out cleanly.

If you have any excess expoy protruding it’s still quite soft at this time so cut it way with a Stanley knife as I have done in the example. Once fully cured expoy makes a hard plastic that can be difficult to cut.

the nut is captured
the nut is captured

The amount to cut off your bolt is the length of your bolt less the thickness of your lid less a bit of wiggle room, I use a cutting disc on a Dremel, and file the cut edge smooth. You need to ensure its long enough to go through the nut once cut as the expoy has a thread that gives a misleading nutness (technical term!) that soon wears away.

I hope you enjoy your captive nuts, I am sure they will give you many years of service. The same principle can also be applied to making captive bolts, especially if you wanted to use Wing Nuts for easier access.

Using a Thumb Slide Joystick

Here are some notes on using the Sparkfun Thumb Slide Joystick on an Ardunio. This is a small two way X-Y variable resistor based controller that uses two analogue pins on the Arduino and works with both the 5 volt logic of the Uno as well as the 3.3 volts of the Teensy.

Thumb Sliding Joystick
Thumb Sliding Joystick

I found that this joystick works well for giving the eight positions found at the stick limits crosswise and diagonally but it doesn’t seem sensitive enough for reporting accurate positions.

Connecting

On the underside of the joystick there are four solder pads, looking from above with the screw holes pointing towards you, the connections are:

  1. X-Axis
  2. +5 volts
  3. Y-Axis
  4. GND
Connections, looking from above and circuit diagram

Should you take one to bits, you will find two sliders with small metal contacts and a circuit board with carbon tracks acting as a variable resistor. The sliders move in a parallel configuration, and the joystick control has a spring to return it to centre when released.

Inside the Joystick showing the contacts
Inside the Joystick showing the contacts
6N2A5558
Carbon tracks on the circuit board, solder pads top left

These can be tricky to put back together afterwards.

Underside of the joystick, with some wires soldered to the connections
Underside of the joystick, with some wires soldered to the connections

The pads on the base are spaced at 2mm but with some bending it is possible to attach standard 2.54mm (0.1inch) header pins, solder the inside two first before attaching the outers.

Thumb Joystick test setup with a Teensy
Thumb Joystick test setup with a Teensy,

When mounting in a case or panel you will need to drill a 18mm hole for the controller and the thumb pad is raised about 3mm above the surface of the body. I would secure the controller in place with a couple of blobs of hot glue  rather than use the small screw holes.

Programming

For my setup I am using the Teensy’s 3.3 volt output to power the joystick and the X-Axis connected to Analog pin 0, and Y-Axis to Analog pin 1,

This test program shows the position of the joystick through the serial port, it attempts to calibrate itself and set the values for the chosen direction, if this is not always successful when returning to the centre position try experimenting with the tolerance and maxRange values.

Links

Hacking a Vacuum Fluorescent Display

I’ve had this Vacuum Fluorescent Display – VFD recovered from a broken DVD player in the bits box for quite a while. I shall turn it into a clock and have it display the date at the press of a button, it will also set its time using the internet and the Network Time Protocol over a WiFi connection, I’ll be using a Teensy 3.1 Ardunio compatible micro-controller as this is compact and with the addition of a crystal and button battery has a clock built in.

VFD Digital Clock

This project is a complete replacement of the logic and driver that came in the DVD player, I have also used general electronic components as these are what I have available: 74HC595 8-Bit Shift Registers, ULN2803A Darlington Arrays and PNP transistors, rather than dedicated VFD driver chips, such as the MAX6920AWP+, Philips NE594N or the TI SN75518N available from eBay. If I were undertaking this again I would use a dedicated driver.

How A Vacuum Fluorescent Display Works

The VFD is made up of three layers, starting at the back these are:

  • The Anodes – these are elements of your display that illuminate
  • The Grid – to control a block of Anode elements
  • The Cathode – also referred to as Filaments or the Heater
A VFD showing the white Anode elements with a row of three illuminated, next are the honeycomb lattice grids and the five Cathode filament wires on top.

“The filament is heated, which causes it to release electrons, a process called thermionic emission. Since electrons are negatively charged, if there is a nearby piece of metal with a electrical charge more positive then the electrons from the cathode, the electrons will be attracted to it, allowing a current to flow.

The grid is positioned between the Anode and Cathode. If the grid is driven more negative than the cathode, it repels the electron cloud, which prevents any current from flowing. Since the grid is not heated, it does not emit any electrons itself.

A VFD is basically triode, except the anode is coated with phosphor. Therefore, when the the anode is more positive then the cathode, the free electrons in the cathode’s electron cloud flow towards the anode, and in the process strike the phosphor, exciting it.” Connor Wolf on stackexchange.com

The display brightness is set by the difference in voltage between the Cathode and Anode. The Cathode filament should be set to a low voltage, no more than 4 volts as it is made from thin tungsten wires which can melt very easily. The Anode uses a higher voltage around 12 to 15 volts.

Multiplexing is used to display the output. Each grid controls a fixed number of elements, the element connections are common to each grid. For a clock you will need to loop between the grids selecting the correct elements to display before moving onto the next, the persistence of vision effect maintains an illusion of a complete display.

Further information

Connecting and testing your Vacuum Fluorescent Display

You will need to find the connections that your VFD uses as well as the best voltages to supply. Unless you are really lucky its unlikely you will find a datasheet for your display, so a little reverse engineering is required.

A selection of test hooks are very useful at this stage. You will also need two power supplies, one low voltage for the Cathode filament, I use 3.3 volts supplied from the Teensy/Arduino. For the gates and Anodes a variable DC supply you can adjust from 10 to 20 volts preferably with the current limited to 1mA, in some cases displays from older equipment will need a higher voltage, 50V and above. The ground on both your power supplies will need be connected together.

The flat VFD’s you see in consumer electronics, such as the DVD player, all have a similar layout. The two pairs of outer pins connect to the Cathode and the pins between these divide into two blocks one side will be for the grids and the other for the Anode elements.

First, establish that the pins you suspect are for the filament are indeed so, with your multimeter in continuity (beep) mode you should see a connection when you probe across these pins. Connect your 3.3v supply to these pins, it doesn’t matter which way round.

6N2A4212
VFD Element being illuminated, with 3.3V across the Cathode filaments (red and black connections). with the first grid on the white connection, and third from last element connected to the green.

The following connections should be made:

  • 3.3 volts across the Cathode filaments (the red and black, above).
  • Ground on the 3.3 volts is shared with the power supply.
  • Two probes connected to the positive on the power supply for connecting to one of the Grids and one for connecting to a Cathode (white and green).

Next, set your variable power supply to its lower setting and with your positive power supply probes  attach one probe to a Grid pin, and the other to an Anode element, on my display I started with a pin furthest left and another furthest right, see if anything lights up, at a low voltage this will be rather dim. If an element has lit up has then increase the voltage until the brightness is what you would expect. If nothing lights then first check you have connected a grid and an element not two grids or two elements by choosing different pins. Or if you are reasonably sure then carefully increase the voltage.

When you are driving the display as a clock, the multiplexing will make each element appear dimmer I increased the display voltage to 15 volts to fix that.

VFD Pin mappings for my display
VFD Pin mappings for my display

Now you can map out the grids and elements, on mine, there are eleven grids the first and last grids are for special characters and the rest contain digits. With a Grid connected, go through each element and make notes, each element will have the same connection on each grid, so all the digit elements and special characters/icons have the same pins.

VFD pin numbers for the digits
VFD pin number mapping for the digits

Driving the Display

While the Cathode filaments are permanently on at 3.3V the 12V grid and Anodes require some kind of high voltage level shifter to have the 5V logic output from the Ardunio (or 3.3V logic on the Teensy) switch the 12V required at the display. The method I have used for switching is a NPN, PNP complimentary (Sziklai pair) output.

Transistor Control
Transistor Control

The NPN transistor is the switch controlled by the Ardunio this in turn switches the PNP transistor, the NPN transistor is being used to isolate the Ardunio from the high voltage required for the display. As the current being drawn is very low we only need small signal transistors NPN: BC549 and for the PNP: BC556.

For the PNP transistor to switch off the Base voltage needs to be close to that of the Emitter, as the Ardunio’s 5V logic is nowhere near the 12V used a NPN stage is added so when the Base of the NPN is on this pulls the Base of the PNP low and allows current to flow to the display. There are three resistors, R1 100K limits the current to the base of the NPN transistor to protect the transistor and Adrduino, R2 10K is biasing the output, working as the bottom half of a voltage divider, and R3 10K is both the top half of the voltage divider and pulls the PNP Base high keeping it off when not required.

Transistors as switches, further reading:

To reduce the component count and size of the project I have replaced the NPN transistors and the resistors R1 and R2 with ULN2803A Darlington transistor array, however the PNP transistor remains as the display requires a sinking output to provide a grounded connection to the load through the cathode.

Two of the four drivers, with, from the top, the Registers, Darlington Arrays, and PNP transistors
Two of the four drivers, the other two are underneath. with the Registers, Darlington Arrays, and PNP transistors.

Connecting to the Arduino

The next stage is to connect the 32 pin display to the Arduino. Obviously the micro-controller does not have enough I/O for this, so instead I have used four easy to use 74HC595 8-Bit Shift Registers with only a data, clock and latch to set up, they can be used to extend the number of output pins on the Arduino.

74hc595_serial_schem
74HC595 Serial Connections (click to enlarge)

I have used the ShiftOutX library for my clock, but it helps to look at the Ardunio’s ShiftOut tutorial to see how they work.

Power

To power this Digital Clock I am using a mains to 12V DC brick from some old electronics equipment, I then use a Buck power supply to provide a 5 volt supply for the Teensy and electronics, and for the display a Boost supply to bump the 12V to 15V, search for XL6009 Module on ebay, check that it has the XL6009 rather than the older LM2577 and set the output voltage before connecting the display.

Digital Clock Power Supplies, 5 volts, small board on the right, 12V to 15V from the larger board on the left

The Driver Circuit

Here is a quarter of the driver circuitry, for the 32 pin display I made four of these. You can see that there is an extra transistor, as the Darlington Array has seven inputs/outputs and also note that on the 74HC595 8-Bit Shift Register the Ardunio data pin connects to DS (pin 14)  and the next register in series connects to to Q7S (pin 9) of the previous register.

VFD Driver circuit (click to enlarge)

Software

This demonstration uses the ShiftOutX library. It loops through each grid and each element within that grid, it does not use multiplexing.

This second demonstration counts from 0 to 9999, with the digits right aligned on the display, it uses multiplexing and the display will appear dimmer than before:

Sources and References

Upgrading the Python Oracle Client

This is a follow up to one of my previous postings: Python and the Oracle Client. The main databases here are being upgraded to Oracle 12 and I’ve taken the opportunity to update the client used by my Python scripts, also its good practice to install new clients when old versions go out of support.

Current Setup

The system I am upgrading here has the following configuration, but this should work with any RPM based distribution, such as CentOS and SUSE :

  • Red Hat Enterprise Linux Server release 6.6 (Santiago)
  • Python 2.6.6
  • python connector: cx_Oracle – 5.1.2
  • oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64
  • oracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64

To find the versions of your currently installed software:
$ python
Python 2.6.6 (r266:84292, Nov 21 2013, 10:50:32)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>> print cx_Oracle.version
5.1.2

and the Oracle client:
$ rpm -qa | grep oracle
oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64
oracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64

Preparing

If you have the old versions installed you will need to do some tidying up by removing the client and python connector, version 11 of the client despite being RPM packaged had some non-standard elements. Use rpm to delete the old version of instant client, remove devel first:
$ sudo su
# rpm -ev oracle-instantclient11.2-devel-11.2.0.4.0-1.x86_64
# rpm -ev oracle-instantclient11.2-basic-11.2.0.4.0-1.x86_64

you may also need to remove the library reference from a previous installation:
# rm /etc/ld.so.conf.d/oracle.conf
# ldconfig

to remove the Python oracle connector, there are two methods. Manually, by finding the previously installed package deleting the files and editing the package list:
# find / -name cx_Oracle.py -print
/usr/lib/python2.6/site-packages/cx_Oracle-5.1.2-py2.6-linux-x86_64.egg/cx_Oracle.py
# cd /usr/lib/python2.6/site-packages
# rm -rf cx_Oracle-5.1.2-py2.6-linux-x86_64.egg

now edit the easy-install.pth file
# nano /usr/lib/python2.6/site-packages/easy-install.pth
and remove the line:
./cx_Oracle-5.1.2-py2.6-linux-x86_64.egg

Or do it the easy way, if you have pip installed:
# sudo pip uninstall cx_Oracle
easy_install does not have an uninstall option.

Installing

Download and install version 12 of the Instant Client and SDK (devel), these can be gotten from: http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html For Linux choose the correct flavour for your installed operating system: x86 or x86-64 for 64bit operating systems, you will need to register on the site gain access the files.
# rpm -i oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
# rpm -i oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm

Now to install the python connector:
# easy_install cx-Oracle
or, the recommended method:
# pip install cx-Oracle
Installation for the version 12 client is much more straight forward than that for version 11.

Testing

A quick test to ensure that the expected versions appear, and that you can connect to the database.
Python 2.6.6 (r266:84292, Nov 21 2013, 10:50:32)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cx_Oracle
>>> cx_Oracle.version
'5.2'
>>> oraConn = "<USERNAME>/<PASSWORD>@<DATABASE HOST>:<DATABASE PORT>/<SERVICE>"
>>> ocDB = cx_Oracle.connect(oraConn)
>>> ocDB.version
'12.1.0.2.0'

Sources