Category Archives: Hardware

Multiple buttons on one pin with an Arduino

Here is a circuit that allows you to use five buttons; up, down, left, right and select, on one analogue pin with the Arduino. It is a adaptation of one used on this LCD shield manufactured by DF Robot. I have used a 10K pull-up resistor and added a 100nF capacitor to help with debounce. The downside is that this can only detect one button press at a time, the button with the lowest resistor value is returned, and the output varies when different voltages are used to power it requiring an update to your software.

In this post I am looking to explore the effect of the existing resistor values, and how to choose your own resistors. This kind of circuit is called a multiple voltage divider or voltage ladder where each rung of the ladder, the switches in the diagram above, produces a different output voltage. Pressing one of the buttons on our circuit changes the output to the analogue port from 5V to a lower one determined by the number of resistors (R1 to R4) in series before the button, as you go down the ladder the output voltage to the pin increases. Here is a short sketch I used to test the circuit and show the voltage reading for each button:

The results from this are shown in the chart below, for the power I used the regulated 5V and 3.3V outputs on the Ardunio Uno, if you run this set-up yourself you may notice an anomalous reading when you release the button, more about this later. Note that a button press drops the power down to the recorded value, the pin is normally high (5V/3.3V) through the 10K resistor.

Resistance1 at 5v at 3v3
Btn Value Meter reading2 volt reading2 volt
S1 none 0 0V 0 0V
S2 330Ω 334Ω 31 0.15V 19 0.10V
S3 950Ω 964Ω 88 0.43V 57 0.29V
S4 1950Ω 1948Ω 166 0.81V 108 0.53V
S5 5250Ω 5270Ω 352 1.72V 230 1.14V
1: Total value of the resistors in series at the button. 2: this is an average, the actual reading can vary.

There are two columns for the resistance, the value marked on the resistors and the multimeter reading. It is best to use 1% tolerance resistors for this circuit to reduce the chances of the readings drifting close to the next. A good spread of output voltages ensures accurate switching.

All this works very well, but what to do if you wish to add more buttons, or have different output voltages? Looking at the circuit, each button can be seen as a voltage divider, such as shown in the diagram on the left. Where R1 is the 10K pull-up resistor and R2 is the sum of the resistors for the button being pressed.

With this simplified model we can calculate any missing value, but for now there are a couple of things to do; calculate the output voltage for the given input voltage and resistance and more usefully for us, work out a value for R2 to give us the desired output voltage.

Calculating the Output Voltage

Using Switch 2 in our existing circuit for example, with 5 volt power:

    \[ Vout = Vin \times \frac{R_2}{R_1 + R_2} \hspace{15 mm}with\ numbers:\hspace{4 mm} 5 \times \frac{330}{10,000 + 330} = 0.16V \]

And again with Switch 4. This has three resistors in series so the value for R2 in the voltage divider is: 330R + 620R + 1K = 1950 ohm:

    \[5 \times \frac{1,950}{10,000 + 1,950} = 0.82V \]

its rather satisfying when your calculations closely agree with the real world readings.

Setting the output Voltage

So, lets try working out some resistors based on the following specification: powered at 5V with five buttons, each 0.20V apart; S1: 0V, S2: 0.20V, S3: 0.40V etc. We know the input voltage, output voltage, and resistor R1, but not R2, here is the formula for finding the resistance of R2:

    \[ R_2 = Vout \times \frac{R_1}{Vin - Vout} \]

    \[ S2: 0.20 \times \frac{10,000}{5 - 0.20} = 417\X\Omega \hspace{5 mm} S3: 0.40 \times \frac{10,000}{5 - 0.40} = 870\X\Omega \hspace{5 mm} S4: 0.60 \times \frac{10,000}{5 - 0.60} = 1364\X\Omega \hspace{5 mm} S5: 0.80 \times \frac{10,000}{5 - 0.80} = 1905\X\Omega\]

These values show the resistance required for each switch and to find the resistor the previous resistance value needs to be deducted. As these values probably won’t be in the E24 Standard Value range and won’t be available in the shops I have the nearest available value in the Standard Resistor column:

Btn Resistance Resistor Standard
Resistor
S1 none
S2 417Ω 417Ω R1: 390Ω
S3 870Ω 453Ω R2: 430Ω
S4 1364Ω 494Ω R3: 560Ω1
S5 1905Ω 541Ω R4: 560Ω
1: actually the nearest is 510Ω, but 560Ω was the closest I had

Obviously, we will need to get this onto breadboard for testing.

Using the same sketch as before I re-ran the tests with the new resistor values, the results are shown below; I have also included an Expected column to show the calculated voltage using the method shown earlier.

at 5v at 3v3
btn Resistor Resistance expected reading volt expected reading volt
S1 none 0 0V 0 0V
S2 R1 390Ω 390Ω 0.19V 39 0.19V 0.12V 25 0.12V
S3 R2 430Ω 820Ω 0.38V 76 0.37V 0.25V 50 0.25V
S4 R3 560Ω 1380Ω 0.61V 122 0.60V 0.40V 81 0.40V
S5 R4 560Ω 1940Ω 0.81V 165 0.81V 0.53V 108 0.53V

That, to me, looks close enough to the 0.20V separation at 5V specified to provide some stable hardware. Here is a short sketch to demonstrate the use of analogue buttons, it returns a number corresponding to the button pressed. When you release a button its resistance changes momentarily to give the Arduino a false reading, to fix this I have added de-bounce functionality to this program:

With this substitution on R3, changing the desired 510 ohm resistor for a 560 ohm, It may be interesting to see what kind of tolerance range we may be able to use. So, for the 0.60V output the optimal resistor would be 494 ohm but we only have Standard Resistor values available and to find the resistance value for our calculation to find the output voltage we need to add 820 ohm (R1 + R2) to R3:

Resistor Resistance Volts
430Ω 1250Ω 0.5556V
470Ω 1290Ω 0.5713V
510Ω 1330Ω 0.5869V
560Ω 1380Ω 0.6063V
620Ω 14400Ω 0.6294V

Clearly, using four decimal places shows is that a 510 ohm resistor is rounded up to 0.60V, while the 560 ohm rounds up to 0.61V, so for our purposes both are suitable. The other resistors will be outside the specification.

Finding the Power Consumption

We also need to look at how much power our circuit is consuming, this is for two reasons: to ensure that our resistors are properly rated and that the power supply can supply enough power. The Ardunio Uno provides a regulated supply of 20mA at 5V and 50mA at 3.3V. The calculation is done with Ohms law:

    \[ I = \frac{V}{R} \]

So, in the original circuit the shortest path to ground is through Switch 1 and the 10K resistor:

    \[\frac{5}{10,000} = 0.0005A \times 1000 = 0.5mA \]

a very low current, this is the maximum the circuit can use. Optionally, to work out the power use for another button add up all the resistors before the switch, for example in the original circuit Switch 5 comes to: 15250 ohm

    \[\frac{5}{15,250} = 0.00034A \times 1000 = 0.34mA \]

Voltage Divider Calculations

Just to round things off, here are four formulae for finding any resistor and voltage in the divider circuit:

    \[find\ resistor\ value: R_1 = \frac{Vin \times R_2}{Vout}-R_2 \hspace{20 mm} R_2 = Vout \times \frac{R_1}{Vin - Vout}\]

    \[find\ the\ voltage: Vin = \frac{Vout \times (R_1 + R_2)}{R_2} \hspace{20 mm} Vout = Vin \times \frac{R_2}{R_1 + R_2}\]

Links and Sources

Solenoids on the Arduino with MOSFET power

I am needing to control a solenoid from the Arduino to do some high speed water splash photography. The Solenoid works at 12v and draws up to 2.5w when open, obviously a direct connection to the Arduino is out of the question. Looking in my parts bucket I found an FQP30N06L MOSFET and recalled that I’d used these to control a small motor.

The FQP30N06L MOSFET in a TO-220 package,
the heatsink tab is connected to the Drain

The FQP30N06L is a N-Channel MOSFET and can switch up to 60V DC at 32A, this is more than chunky enough for the solenoid. For use with the Arduino it needs to have ‘logic-level’ switching of 5V, looking at the datasheet for the Static Drain-Source On-Resistance – RDS(on) we can see a test condition where VGS=5V (or 4.5V) exists then we know the MOSFET is suitable.

Looking for logic-level volts in the On Characteristics (source: FQP30N06L datasheet)

The Circuit:

  • D1: 1N4002 Diode – provides surge suppression from the solenoid, this protects the MOSFET from inductive voltage ‘kickback’.
  • L1: the Solenoid or motor (a solenoid is just a linear motor)
  • Q1: FQP30N06L MOSFET being used as a switch
  • R1: 220R Resistor – current limiting, see below.
  • R2: 100K Resistor – this keeps the Gate closed when the Arduino output is off/LOW

The resistor R1 is there to protect the Arduino. On a MOSFET when a voltage is first applied to the Gate it can appear as a short to ground, limiting the current will prevent a surge that may cause damage. The Arduino supplies 5V at 40mA on a digital I/O pin.

A MOSFET switches when there is a charge at the Gate, the higher the charge the wider the gate opens and more current can flow through the Source to the Drain. Looking on the datasheet for our MOSFET the Gate Threshold Voltage VGS(th) shows a minimum of 1V and a maximum of 2.5V, this means that below 1V the gate is closed, at 1V the gate is ajar, as the voltage increases the gate opens wider until you reach 2.5V where it is fully open, power can go above this but the gate will not open any further. Going above 20V on the gate VGS will break the MOSFET.

So we need a resistor low enough to fully open the gates, but high enough to prevent the Arduino spluttering. So I chose to limit the current to 20mA and calculated the resistor with Ohms Law:
R = V / I
5V / 20mA = 250R (I used a 220R as that’s the nearest I had, this limits the current to 23mA)

Ground on the Ardunio is shared with the 12V power supply for the solenoid.

Programming

Connect the circuit to your Arduino, the MOFSET’s gate to a digital output and ground. You may want to avoid digital pins 0 and 1 as these are on the serial port and can cause the solenoid to rattle unexpectedly.

Here is the Solenoid equivalent of blink, with the solenoid circuit connected to digital pin 3 it is switched on and off once a second:

Comedy effect can be had by reducing the timings to milliseconds, although keeping that up for too long will probably knacker the solenoid.

Solenoid Control

References and Links:

Rotary Encoders on the i2c bus

I have been getting to grips with rotary encoders on the Arduino, and to add a little drama I have gotten this working on the i2c bus. Here I will be showing how to set up the necessary hardware and demonstrate a program for the Arduino. I have used a similar setup to control an LED RGB light strip, with three rotary encoders to control the Red, Green and Blue and a fourth for special effects.

The i2c bus

The i2c bus allows connection of multiple devices to the Arduino on just two wires, these can be just about anything from temperature sensors to motor controllers with each device having its own address, up to eight of these can be used using just two wires from the Arduino.

For this project I’ll be using a single MCP23017 port expander, with which I can add sixteen digital I/O pins to the Arduino

MCP23017 pinout

The address for the expander is set on pins 15, 16 and 17 (A0, A1 and A2), for a single encoder set all of these to ground. Should you require more expanders the addresses can be set as in the table below, the MCP address is for the Arduino program.

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

Rotary Encoders

The  encoders I’m using are the SparkFun 12-step rotary encoder with integrated push-button

rotary encoder

Inside they have mechanical contacts that output two square waves when rotated, A and B these are 90o out of phase with each other so when rotated clockwise output A is ahead of B, and counter-clockwise output B takes the lead, this is a two bit Grey code.

rotary encoder square wave
rotary switch outputs (source: datasheet)

So by comparing the two outputs we can determine the direction of rotation.

A Test Circuit

My test setup comprises of two rotary encoders, one Arduino Uno, one MCP23017 port expander, and a couple of resistors. External pull-up resistors are not required on the GPx input ports as the MCP23017 has these internally. Encoder A uses GPA0, GPA1 and GPA2 for the push button. Encoder B is on GPA4, GPA5, and GPA6.

MCP23017 rotary encoder test circuit

Programming

My program uses the Adafruit MCP23017 and standard wire libraries. The Adafriut library addresses the GPx ports from 0-15, so GPA2 is 2, and GPB2 is 9. I have written this to output the state of rotation to the serial port at 9600 baud.

 

links:

Infra-Red Coin Detector for Arduino

For something I’m building I need have the Arduino detect a coin being dropped trough a slot, for this I have built an IR detector, it comprises of an IR LED, IR Photo-Diode, Op-amp and ATtiny85 micro-controller.

IR Coin Detector (Mk3)

The circuit works by having the IR LED flood the Photo-diode so that when an object passes between them the Photo-diode stops letting current through, this is fed into the op-amp to provide a consistent output for the ATtiny85 micro-controller to detect the change in signal to then flash a couple of LED’s and provide a signal to an Arduino.

IR Coin Detector (Mk3)

Here is a program that flashes a couple of LED’s and makes output pin 4 high:

Sources:

  1. DIY Science: Measuring Light with a Photodiode II
  2. Pin Change Interrupt on the ATtiny
  3. Programming an ATtiny85 with an Arduino

Recording Sound on the Raspberry Pi

The Raspberry Pi does not have a microphone socket, which is inconvenient when you wish to record sound. To fix this you will need a USB Sound Card, for which I bought a Creative Sound Blaster Play! for about £20 and a short USB extension lead as the sound card is slightly too large and blocks the other USB port.

With the latest Raspbian “wheezy” installed on a Pi Model B with 512Mb of RAM and the overclocking set to High in raspi-config, here is a recipe for getting your Raspberry Pi to record sound from the command line. For the test setup I connected my iPod to the microphone port of the sound card, plugged everything in and powered up.

Raspberry Pi Records

After logging into the Pi, check that the computer can see the card, use lsusb to find it, here the card is highlighted in blue:
$ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 046d:c52e Logitech, Inc.
Bus 001 Device 005: ID 041e:30d3 Creative Technology, Ltd Sound Blaster Play!
remember that different makes of card will have different names and ID’s

Your user will need to be in the audio group, check this with groups <username>:

$ groups pi
pi : pi adm dialout cdrom sudo audio video plugdev games users netdev input
if not, then add them with:$ sudo usermod -a -G audio <username>

There is/was an issue with the Pi’s USB port that meant it can/could become overwhelmed1 with data which causes popping and bubbling noises to be included in your recordings, this can be fixed with an update of the Pi’s firmware:

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install rpi-update
$ sudo rpi-update

The Raspbian image already has the alsa-utils for sound already installed, the programs I am using for recording and playback are:

  • alsamixer – GUI for setting the recording and playback levels
  • amixer – Command Line for setting the recording and playback levels
  • alsactl – for saving the settings set in alsamixer or amixer to use again after a reboot
  • arecord – For recording the sound
  • aplay – For playing back your recording

All of these programs have a –help option.

There are two methods for setting up the the microphone port on the card, the first is alsamixer:

alsa mixer

$ alsamixerPress F6: Select Sound Card, and choose yours from the list, the bcm2835 ALSA is the on-board sound, for me the one to pick was: USB Device 0x41e:0x30d3 and take a note of the card number, in my case: 1. Now select the Mic and increase the volume to 52, or the first white blob, you’ll need to change it later, but its a good place to start. The Auto Gain Control wants to be off, select the gain control and press M to toggle so it displays [MM] for mute. Press Esc to exit and save the settings with:$ sudo alsactl store 1 where 1 is the card number.

Alternatively, you can use amixer. First find your sound card, in amixer there does not appear to be a method of listing the available cards, but on a Raspberry Pi I guess it will always be card 1, you can list the cards current status with:

$ amixer --card 1 contents
numid=1,iface=MIXER,name='Mic Playback Switch'
; type=BOOLEAN,access=rw------,values=1
: values=off
numid=2,iface=MIXER,name='Mic Playback Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=32,step=0
: values=21
| dBminmax-min=0.00dB,max=47.81dB
numid=5,iface=MIXER,name='Mic Capture Switch'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=6,iface=MIXER,name='Mic Capture Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=16,step=0
: values=7
| dBminmax-min=0.00dB,max=23.81dB
numid=7,iface=MIXER,name='Auto Gain Control'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=3,iface=MIXER,name='Speaker Playback Switch'
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=4,iface=MIXER,name='Speaker Playback Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=151,step=0
: values=52,52
| dBminmax-min=-28.37dB,max=0.06dB

So I want to turn the Auto Gain Control off, and the recording volume to 14:
$ amixer -c 1 cset numid=7,iface=MIXER,name='Auto Gain Control' 0
numid=7,iface=MIXER,name='Auto Gain Control'
; type=BOOLEAN,access=rw------,values=1
: values=off
$ amixer -c 1 cset numid=6,iface=MIXER,name='Mic Capture Volume' 14
numid=6,iface=MIXER,name='Mic Capture Volume'
; type=INTEGER,access=rw---R--,values=1,min=0,max=16,step=0
: values=14
| dBminmax-min=0.00dB,max=23.81dB

again, store the settings so that they will be used again on a reboot:$ sudo alsactl store 1

Now we are ready to do a test recording, first check that arecord will see your card:

$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: U0x41e0x30d3 [USB Device 0x41e:0x30d3], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

and now for a ten second test recording, this will create a file called rectest.vav in your home directory. Remember to set the Device (-D plughw:1) number to the right card (card 1):

arecord -D plughw:1 --duration=10 -f cd -vv ~/rectest.wav the vv option displays extra information on the screen as well as a volume meter, this should be peaking at around 95% on the loudest sounds, if it is at 100% all a lot of the time then you are probably recording distortion. Playback the recording with aplay:

aplay ~/rectest.wav

the default settings will play the wav fie through the TV if it is connected by HDMI, To playback through the USB sound card set the device to the card number, like in arecord:

aplay -D plughw:1 ~/rectest.wav

Congratulations, you now have a fully working Pi Recording Device. Remember to experiment with the volume levels, too high and your recording will sound distorted.

References:

  1.  Raspberry Pi Usb Audio fix (10 May 2013)

Taking Photos on the Canon EOS with an Arduino

For my Spangaly Stick project, more of which later, I have been wanting to add a remote control function for the camera for a while now and with the extended winter I found I had the time. I am using an Arduino micro-controller fitted with an XBee wireless shield to respond to a keyword sent by another Arduino with a similar setup, or from a computer with an XBee on a USB port.

take a picture - board

This board had been built to work with the Canon EOS DSLR range of cameras, but should work with other makes of camera fitted with an electronic remote socket. For basic use the camera should be set in Aperture Priority (Av) mode with the lens set to manual focus and if your using a tripod switch off any image stabilization.

For this project you will need:

  • A Windows (XP and above) Computer
  • An Arduino Uno R3
  • Two XBee’s
  • An XBee USB adapter
  • An XBee Shield for the Arduino
  • A battery to power the Arduino, I use a 12v 1.3Ah Sealed Lead Acid.
  • A remote lead for your camera
  • Ability to solder, read circuit diagrams, etc..

For this remote to work, you will need to configure two XBees to talk to each other. The easy way to do this is using the X-CTU tool (unfortunately it is Windows only) and a XBee USB Adapter. The XBees come in two main types, the Series One (S1) and Series Two (S2) they will need to be of both the same series to talk to each other, I have used Series One bees here, but not the ones without the sticking out antenna as I suspect they may be a bit delicate.

While the XbeeSheid configuration is documented on the arduino site, I shall summarise here. With the XBee plugged into the USB adapter and the adapter plugged into the computer wait for it to be detected by Windows then you can configure it. In X-CTU, on the PC Settings Tab, select the USB Serial Port. By default the XBee is set to baud: 9600, flow: None, data: 8, parity: None, stop: 1. Click the Test/Query button you should see some basic XBee settings, if it says it cannot communicate, try a different baud rate. Higher baud rates are available, but whats the rush?

Now click the Modem Configuration tab, under Modem Parameter and Firmware, click Read, after a pause at the top of the list The modem indicated will be whatever model you have, in my case XB24, select the function set we will be using: XBEE 802.5.4 RS485 ADAPTER and the firmware version: 13E8. You will need to set the Networking & Security Channel (CH) and the PAN ID (ID) to the same on both, as well as check the Serial Interfacing are set correctly, Interface Data Rate (BD): 3 – 9600, Parity (NB): 0 – NONE. Click Write to save the settings to the XBee.

For testing the XBee’s, I had one plugged into the USB adapter and the other placed into the the XBee Shield, an LED fitted across Digital Output 12 and Ground, and sent the following program to the Arduino, remembering to flick the little switch on the shield to USB for programming, and Micro for XBee emissions.

The circuit I made for taking photos includes the focus, this is optional but I have included it so the camera can be woken up before the picture is taken. An ILD74 opto-isolater is used to electrically separate the camera from the Arduino, it also simplified the circuit not having to use transistors. The LED’s are useful additions but are optional.

The diagram also shows the Canon Remote connections. Most use a 2.5mm stereo jack plug, but the more expensive cameras have a proprietary Canon N3 connector, to get the lead you will need to sacrifice a wired remote, one of these can be gotten of ebay very cheaply, about £3.00. The colours for the wires can be anything, so you will need check with a continuity tester.

The program on the Arduino listens for a keyword, in this case ‘PHOTO’ which then triggers the picture taking sequence first by setting the focus to wake the camera up then taking the picture. The Indicator LED is used to show activity on the serial port.

Can a Pi Raspberry?

The Raspberry Pi is a small computer, and as such an obvious but important question occurred to me, and despite Google, I was unable to find an answer. So using science, LEGO, a balloon, and a compressed air supply I set out to discover if the Raspberry Pi could indeed blow a raspberry.

To embark on this scientific discovery, first, I needed to be able to control a motor, for this I built a dual relay board that can be switched using a couple of the Pi’s GPIO pins:

LEGO PF Motor Controller v3

Here is the circuit diagram:

LEFO PF Motor Controller v3

And the Python source code:

To which I connected a large LEGO PF motor. This is used to switch the pneumatic valves via a clutch cog and a large cog. I used a 9v power supply for this, but a PF Battery box can be used, cut an PF extension lead in half, use the light grey side for the motor, and the dark grey end to connect to the battery box. My compressed air supply operates at 2bar / 30 psi, it was built to work with LEGO pneumatics, I found that anything much above that pressure would cause the pipes to pop off the connectors.

The Pi Raspberry Project

Obviously I needed something that would make a sound. For this, a balloon (the sausage type), a small pop bottle, and some more LEGO were suffice. The air is injected into the bottle trough a couple of holes at the rear.

The Pi Raspberry Project

I would like to say thanks to the people on the Raspberry Pi forum for their advice on the electronics: http://www.raspberrypi.org/phpBB3/ and further reading about LEGO PF motors can be found here: http://www.philohome.com/pf/pf.htm, and the raspberry http://en.wikipedia.org/wiki/Blowing_a_raspberry