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
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.


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 in Colour on the i2c Bus

This is a follow-up to my previous writings on the subject of rotary encoders: Rotary Encoders on the i2c Bus. This time I am using the Sparkfun Rotary Encoder – Illuminated (RGB) (Part: COM-10982), this has the same rotary goodness as the SparkFun 12-step rotary encoder but with the addition of three LED’s to provide a whole host of colours on the rotating shaft.

Test Setup

Again I will be using the MCP23017 port expander to add 16 digital I/O ports to the Arduino via the i2c bus,  the rotary encoder part operates in the same manner as before and we can use the internal pull-up resistors to reduce the number of components. The LED’s operate with a common anode and the push button also operates on 5v rather than the usual switching to ground.

For my test setup I have connected the rotary encoder to GPA0 and GPA1, the push button to GPA2 and the Red, Green and Blue LED’s to GPA5, GPA4 and GPA3. Note the 10K pull-down resistor on the push button.

My program on the Arduino changes the colours as you rotate the shaft, you will see seven colours, to see more you would need to use PWM to control the LED’s brightness. With the common anode on the LED’s the logic for switching them is inverted, so HIGH = off, LOW = on. You will need the Adafruit MCP23017 Arduino Library.


How-To: Raspberry Pi as a 3G/4G Router

Recently I have needed to find an emergency alternative to my broadband due to the regional wide area network, Digital Region, being shut down, and the ISP Origin making a mess of getting all their cutomers onto ASDL. To get quickly back onto the internet, I have bought an ZTE MF823 4G Mobile Broadband Dongle as supplied by the badly named ‘three’ mobile phone company. As I have my own internal wired network, with multiple computers and ‘things’ there is a need to have something more sophisticated than just plugging the dongle into a single PC.

network diagram

Here is my recipe for setting up a Raspberry Pi as a router with an ZTE MF283 Dongle. In this setup all the computers are on a wired Ethernet connection using a switch for the network. The Pi has Raspbian Debian Wheezy installed (June 2014) with all the latest updates made. For testing, the dongle is plugged into the USB port via a powered hub, and the Pi connected to a switch with another PC running Linux Mint.

Setup the Dongle

This USB dongle has its own built in dialer so you do not need ppp or wvdial installed, it appears as a USB ethernet device on the Raspberry Pi. You will need a powered USB hub as the dongle can draw more power than the Pi can provide, the symptoms of too much of power being drawn will be the Pi behaving erratically or restarting unexpectedly.

With the dongle plugged in, check that it is recognised by the Pi with lsusb, it can be seen here as ‘ZTE WCDMA Technologies MSM’:

The device ID is 19d2. and 1405 is the mode, this should be 1405 – CDC ethernet. If it is not, try removing the micro-SD card and rebooting the Pi, the device modes available are:

  • 1225 – Default mode. USB Mass Storage Device + CD-ROM + card reader.
  • 1403 – Modem mode. RNDIS + Mass Storage Device.
  • 1405 – CDC ethernet
  • 0016 – Download mode

As the dongle also has a Mass Storage Device the Raspberry may not switch to CDC ethernet. If the mode does not change, try the following with usb-modeswitch:
$ sudo apt-get install usb-modeswitch
$ sudo usb_modeswitch -v 0x19d2 -p 0x1405 -d

I did not have to change the mode as it was correct already, and it didn’t change when I tried setting it as a Mass Storage device, I have not explored this any further.

When first plugged in the dongle was recognised as a ethernet device but it did not obtain an IP address:

if this is the case with you, add the following two lines to the end of sudo nano /etc/network/interfaces:
auto usb0
iface usb0 inet dhcp

the dongle provides its own address to the computer. Reboot, and you should see the obtained address:

The address is now the internet address of the computer the dongle always assigns this address, there is also a useful web status page on

Configuring the network

first of all enable ip4 forwarding, edit the file sudo nano /etc/sysctl.conf and uncomment the line:
this will enable forwarding on reboot, you can also enable IP forwarding immediately with:
$ sudo sysctl -w net.ipv4.ip_forward=1

We now need to give the Pi a static IP address on the internal network. Edit sudo nano /etc/network/interfaces so you end up with a file that looks like this:

this gives the Pi a static IP address of


The next stage is to give the other computers on your network an IP address, this is done with a dhcp server:
$ sudo apt-get install isc-dhcp-server
you will need to configure dhcp sudo nano /etc/dhcp/dhcpd.conf, here is mine:

This will assign IP addresses in the range to to any computer connected to your network. I have used Open DNS for the Domain name Servers, if you wish to use google’s use:
option domain-name-servers,;instead. Reboot the Pi and then your test computer.

Your test computer should now have an IP address (, and the gateway point to the Pi (

Accessing The Internet

The final part is to have the incoming traffic on the the Ethernet port eth0, go out on the dongle usb0. This is achieved with iptables, a firewall and traffic router. Install with:
$ sudo apt-get install iptables
and you need to setup Network Address Translation, NAT and forwarding. This short bash script clears any old settings before applying the new rules:

Where LAN is your internal network, and WAN is the internet. The final line allows you access to the Dongle’s built in web status page from any browser on your internal network, just use:

Save the file in your home directory as ~/, make it executable and run the script.

$ chmod +x ~/
$ sudo ~/

From your test computer, you will now be able to access the internet.

Finally, you now need to have iptables reload when you start the Pi. Export the iptables settings to a file with:

$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

and create a file sudo nano /etc/network/if-up.d/iptables with the following contents:

and make it executable sudo chmod +x /etc/network/if-up.d/iptables

after a reboot you can see your iptables with sudo iptables -L and sudo iptables -t nat -L and you can see web traffic passing through the router with sudo tcpdump -i any -nn port 80.

Adding a Proxy Server

This is optional, but a transparent proxy server and cache will reduce the amount of traffic on your 3G/4G connection. I have used squid3 for this.
sudo apt-get install squid3
Update the squid3 configuration /etc/squid3/squid.conf so it has the following. The original is rather large, so you may want to make a copy and create a new one:

then restart squid3
sudo /etc/init.d squid3 restart
add the following iptables rule to redirect all traffic on port 80 to squid3:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128
you should now be able to watch the web traffic being processed through squid3 with:
sudo tail /var/log/squid3/access.log -f
finish off by exporting your iptables again, so they are reloaded on reboot:
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

Raspberry Pi - 4G Router

References and sources:

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.

hardwired address i2c
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.



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.



Arduino Laser CNC Engraving Machine

Warning: This project uses a laser. It will hurt you if you are not careful. Please take care when handling the laser. Do not look at the beam, do not point it at yourself or anyone else. Remember that an IR Laser can damage the eye just as easily as a visible light one. A good pair of laser goggles must be worn, they must be designed to filter the colour of laser you are using and compliant to  EN207 standards.

Laser CNC

I have built a Laser CNC machine out of a couple of old DVD-RW drives, an Arduino UNO with Grbl v0.8 installed, two EasyDriver Stepper Motor Controllers and bits of wood I have around the home. The laser came from one of the DVD-RW drives.

My Engraver is vaguely based upon the Pocket Laser Engraver by Groover, except I have used an Arduino UNO and have added limit switches. G-Code is a industry standard, of sorts, used to control CNC (Computer Numerical Control) Machines, such as lathes, routers, and in this case Laser Engravers.

Here I will be providing additional information about the electronics and Grbl configuration I discovered while building the Laser CNC. I have used the following software:


Stepper Motor Controller

There are four electronic parts to this setup. The 5v power supply, a relay circuit to control the laser driver, the Laser Driver to control power to the laser, and the limit switch circuit used by Grbl to provide a stop indication on the axes.

The Power supply is a nothing glamorous, its a basic 7805 design giving a 5v output.
5v Power Supply
I use a 2A Switched Mode Power Supply plugged into the mains, similar to this 17W Switched Mode AC/DC Multi Voltage Power Supply from Maplins. Using 7.5v as the input is enough to keep the 7805 running without it having to convert too many volts into heat.

To control the laser from the Arduino, I have added a relay circuit. The 5v relay is powered by the power supply above, on one side of the normally open switches is a 5v fan to blow the smoke away, and on the other the Laser Driver, remember to switch the laser driver circuit rather than the laser diode.
relay circuit

The Laser driver using a LM317 Adjustable Regulator is a little more involved, as calculations have to be made to establish the output current. You want enough power to scorch or cut card, but not so much as to burn the laser diode out.
Laser Driver

The power output of the Laser Driver is set by the resistors R1 and R2. This video tutorial gives some explanation. Going above 500mA with a red laser will definitely cause it to blow, I have limited the power to 330mA as I only have a limited supply of lasers. I used this page for calculating resistors in parallel. Here are some milliamp output values using a couple of standard resistors.

Resistors volts / ohm mA
2 x 10R 1.25v / 5R 250mA
2 x 9R1 1.25v / 4R5 270mA
2 x 8R2 1.25v / 4R1 300mA
2 x 7R5 1.25v / 3R7 330mA

The final circuit is for the limit switches, and is based upon one found here:
limit switches
The switches need to be very sensitive, I found using that the motors were not strong enough to push button switches. I used those found in the one of the drives, and a couple from an old cassette deck. Check that you have connected up the switches correctly, X to X, Y to Y, confusion arises when they are the wrong way round and Grbl doesn’t say which switch has made contact.

In Grbl set $16=0 (hard limits, bool) if your image is larger than the allowed size then will just make your drawing look wrong, setting it to 1 (true) will cause the G-Code program to be aborted. $17=1 (homing cycle, bool) will cause Grbl to expect an $H (home) command when started, $H will cause your axes to move to their start positions.



Software Configuration

The only real issue with setting up Grbl, was getting the X and Y axes operating in the expected direction. There are two problems, getting the right start point, and having them go in the correct direction. You will be wanting the image in Inkscape to appear correctly. There are two settings within grbl v0.8 that need to be configured so that it works: $6 (step port invert mask) and $18 (homing dir invert mask). Having spent a while trying out various settings, I wrote a little mask calculator to assist me with this, to find your mask, click the checkboxes, or you can enter the current mask number and click set to find the binary code.

Invert Bit: $6=0

The documentation says that the first two bits are not used for inversion, but have found that there is a change in the direction of the motors.

Test with your favorite terminal program, on this Linux box I used: minicom -b 9600 -D /dev/ttyAMA0, turn local echo on with Ctrl-A E. Make the table go forward 1cm with X10, or in reverse X-10, Same for the Y axis, Y10, Y-10 further experimentation may be needed when you first start etching, I had a images and text appearing mirrored at first.

Now it is a case of loading your line-art into Inkscape, thin lines work best, creating the G-Code file using the laserengraver option in the extensions menu. Then sending the file to the Arduino with the Universal G-Code Sender. A Guide

My Grbl settings:



The Case of OpenCV and the Missing SURF

I have been wanting to have a play with the OpenCV computer vision framework on Python for a while and finally got some time to some experimenting, I am looking to have the computer recognise LEGO parts, after much research and mucking about it seems I should be using cv2.SURF and/or cv2.SIFT for what I want to do. However on Fedora 19 these are not included in the distribution RPM as they are nonfree in that they are not open source. Attempts to use SIFT or SURF result in the following error:

$ python
Python 2.7.5 (default, Nov 12 2013, 16:18:42)
[GCC 4.8.2 20131017 (Red Hat 4.8.2-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print cv2.__version__
>>> i = cv2.SURF()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SURF'
This is annoying as OpenCV will now need to be re-installed the old fashioned way, but there are instructions on the OpenCV site and I will be using them here with additional information I have discovered while following them.

Change to root and add the free and nonfree repositories as ffmpeg and libv41 are unavailble from Fedoras, followed by an update (it seems that Fedora 19 always has something to update):

& sudo su
# yum localinstall --nogpgcheck$(rpm -E %fedora).noarch.rpm$(rpm -E %fedora).noarch.rpm
# yum update

Remove the existing OpenCV packages:

# yum erase opencv*

There are a few packages to install in preparation to compiling the code, you may have some of all of these already but yum will skip those. Install the mandatory packages, these are for compiling the source and using GTK for the GUI:

# yum install cmake python-devel numpy gcc gcc-c++ gtk2-devel libdc1394-devel libv4l-devel ffmpeg-devel gstreamer-plugins-base-devel git wget

Install the optional dependencies, I have gone for the install everything approach, they may be useful later:

# yum install libpng-devel libjpeg-turbo-devel jasper-devel openexr-devel libtiff-devel libwebp-devel tbb-devel eigen3-devel python-sphinx texlive

Now, we are ready to get the latest source, here there are two ways to do this, install the latest development version using GIT, or download the latest stable version. My preference is to use the latest stable version.

With GIT, exit back to yourself from root, change to your home directory and download OpenCV:

# exit
$ cd ~
$ git clone
Cloning into 'opencv'...
$ cd opencv
$ mkdir build
$ cd build

Or using the latest build, at time of writing this is v2.4.7. Get this via the downloads page and save it to your home directory:

# exit
$ cd ~
$ tar -zxvf opencv-2.4.7.tar.gz
$ cd opencv-2.4.7
$ mkdir build
$ cd build

Now configure:


When complete you should check that your options agree with those displayed. There are many others available. Support for other programming languages may be missed out if they are not already installed. In my case those for Java, if I were to try OpenCV in Java I would need to install the appropriate Java packages using yum, then recompile OpenCV.

Now build and install, this can take a while:

$ make
$ sudo make install

You now need to move the module to anywhere on the Python Path, to find this:

$ python
Python 2.7.5 (default, Nov 12 2013, 16:18:42)
[GCC 4.8.2 20131017 (Red Hat 4.8.2-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.path
['', '/usr/lib/python2.7/site-packages/PIL-1.1.7-py2.7-linux-x86_64.egg', '/usr/lib64/', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib64/python2.7/site-packages/PIL', '/usr/lib64/python2.7/site-packages/gst-0.10', '/usr/lib64/python2.7/site-packages/gtk-2.0', '/usr/lib/python2.7/site-packages', '/usr/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg-info']

The directory /usr/lib/python2.7/site-packages looks suitable:

$ sudo mv /usr/local/lib/python2.7/site-packages/ /usr/lib/python2.7/site-packages

And add your new installation to the PYTHONPATH, and add the export to the end of your .bashrc so it survives a reboot:

$ export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages
$ echo export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages >> ~/.bashrc

Now to test:

$ python
Python 2.7.5 (default, Nov 12 2013, 16:18:42)
[GCC 4.8.2 20131017 (Red Hat 4.8.2-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> print cv2.__version__
>>> i = cv2.SURF()

Sorted. Now, perhaps, I can get on with what I actually want to do….