How to setup 2 Axis analog joystick with Orange Pi Zero

We will now be setting up a 2 Axis Joystick with Orange Pi zero. Since this board does not have an analog input, you need to use an external analog to digital convertor. So in this case, I have used MCP3208.

Hardware required:

Below are the list of hardware components that will be needed to set this up.

and  an MCP3208 Chip and lots of connecting wires.

I have written an article on how to setup mcp3208 with orange Pi.

Circuit Connection:


After setting up the connection it looks like the picture below.

Software installation:

I have used Armbian image as the base operating system and installed the required python packages in a python virtual environment.


apt-get install python-dev python-pip
virtualenv localpy
source localpy/bin/activate
pip install spidev
git clone
cd orangepi_PC_gpio_pyH3
python install

Refer to my article on how to setup GPIO for Orange Pi Zero for more information on GPIOs.

After everything is done, copy this code to your orange Pi Zero and run.

import spidev
import time
from pyA20.gpio import gpio
from pyA20.gpio import connector
from pyA20.gpio import port

class MCP3208:
        def __init__(self, spi_channel=0):
                self.spi_channel = spi_channel
                self.conn = spidev.SpiDev(1, spi_channel)
                self.conn.max_speed_hz = 1000000 # 1MHz

        def __del__( self ):

        def close(self):
                if self.conn != None:
                        self.conn = None

        def bitstring(self, n):
                s = bin(n)[2:]
                return '0'*(8-len(s)) + s

	def ReadInput(self,Sensor):
		adc = self.conn.xfer2([1,(8+Sensor)<<4,0])
		data = ((adc[1]&3) << 8) + adc[2]
		return data

        def read(self, adc_channel=0):
                # build command
                cmd  = 128 # start bit
                cmd +=  64 # single end / diff
                if adc_channel % 2 == 1:
                        cmd += 8
                if (adc_channel/2) % 2 == 1:
                        cmd += 16
                if (adc_channel/4) % 2 == 1:
                        cmd += 32

                # send & receive data
                reply_bytes = self.conn.xfer2([cmd, 0, 0, 0])

                reply_bitstring = ''.join(self.bitstring(n) for n in reply_bytes)
#                print reply_bitstring

                # see also... (page.20)
                reply = reply_bitstring[5:17]
                return int(reply, 2)

if __name__ == '__main__':
        spi = MCP3208(0)
	button = port.PA12
	gpio.setcfg(button, gpio.INPUT)
	gpio.pullup(button, gpio.PULLUP)
        a1 = 0
        a2 = 0
        while True:
                a1 = spi.ReadInput(1)
                a2 = spi.ReadInput(2)
		state = gpio.input(button) 
		print "X Axis=%04d, Y Axis=%04d, Switch :%d" % (a1, a2,state)

Output :

Check the output here in this video below.


Are you interested in how to setup joystick with   Arduino? Check out the link.

Feel free to share your ideas and feedback in the comment section below.

10 thoughts on “How to setup 2 Axis analog joystick with Orange Pi Zero

  • Pingback: Awesome Geeky Sensor Kit for Arduino and Pi boards – Codelectron

  • March 7, 2018 at 1:42 pm

    Hi there!
    Thanks for your article!

    Did you integrated this with GPIO buttons as well?

    I am using retrorangepi on orange pi and I am using the GPIO button driver to use GPIO buttons as control. I checked the driver and it use :
    – pyA20 to get the GPIO button signals
    – uinput python package to simulate the gamepad.

    If you have done it or know how to do it could you help on that ? 🙂

  • July 4, 2018 at 1:29 pm

    Another question, why did you not used the PYA20 SPI package? As you’r using PYA20 GPIO already.

    What are the numbers you’r reading? The 0512 0520 … As I think I need to have numbers between 0 and 255 for the uinput package. Not sure to understand how we go from the read voltage on Ch0 and Ch1 to this number.

    • July 4, 2018 at 2:51 pm

      Hi, I dont remember for sure, but the PYA20 was not working for me and I wanted to find a way out. It could also be that I did something incorrect. You may try if it works.
      The ADC MPC3208 has 10 bit resolution which means you get value from 0 upto 1024. You can map the values just like how it is done in Arduino –
      If this might help –

      Let me know if it help, Just curious,may I know what project you are working on.

      • July 11, 2018 at 8:46 am

        Thanks for your reply!!

        But how the MCP3208 know which voltage is 1024 and what voltage is 0 ?
        Obviously we need GND to be 0 and 1024 to be 5V but where is it setup? What if I need to use 3.3V instead ?

        • July 11, 2018 at 4:55 pm

          Obviously 0 is GND. Check out Reference Voltage Input – Pin No 15 (MCP3208). The range scale according to voltage based on v ref.

          • July 11, 2018 at 8:06 pm

            Of course! Sorry I missed that, thanks! 🙂
            I’ll try to have it working!

      • July 17, 2018 at 2:26 pm

        Oh sorry I have forgot to tell you the project I’m working on.
        I’m the maker of RetroStone, which is a H3 based game console.
        I made a H3 custom PCB, on which I put the layout for the MCP3208 and the layout for a small analog joystick. And now I’m trying to write the driver to have this joystick working on retrorangepi 🙂

        • January 1, 2019 at 4:55 am

          I’m working with a orange pi zero, i use the gpio for retrorangepi, the buttons now work great, but i want to add a joistick,

          Did you make this posible?


Leave a Reply

Your email address will not be published. Required fields are marked *