P011 ADC


The P011/2 is an ADC (Analogue to Digital Converter) that also has 3 digital outputs. Using this Chip can not only save on I/O pins but should anything untoward happen it will also protect the host (RPi, Arduino or ByPic system).

The Chips come in two flavours, P011 (Serial) and P012 (I2C). Both work in identical ways except that the interface is different.

The IC can be used in a stand alone project or it can be used with the purpose made PCB that attaches to the back of the display. The circuit diagram for the PCB is on the data sheet.

When using the IC without the PCB make sure that the reset and F pins are tied high. The reset of course can be tied with a resistor and an external device can use this line to do a hard reset.

Windows Serial

The chip has TX and RX connections that can be connected to a USB to serial device. If the PCB is not used then only one device at a time can be connected to the serial bus. If the PCB is used then many can be used as the PCB TX attaches to an open collector (more or less) output.

No handshaking is required simply connect TX to RX and RX to TX as shown. It is important that the F and reset pins are tied to +V.

Once connected use BV_COM, this is free and does not need installing, just run the exe.

Set echo on, set the correct COM port.

The P011 has a default address of 'h'

For here some commands can be entered through the terminal for example:

  • hH - check if it is connected okay
  • ha9 - get value of ADC channel 9 (indicates temperature of IC)
  • hd1,1 - set digital channel to 1


If the prompt coming back from the device is '>' then it needs inverting do this by entering:

  • hI

The return should be [06]

This mechanism is provided so that the IC can be used directly or with an open collector output as is the case when using the PCB10. The invert command is a toggle and it will stay even after power remove, so it is a one time operation.

The '>' is easy to detect on automated systems and so can be handled by them.

A much easier way to use the device on windows is to run the sws software that works with the Python language. It is not that difficult to install, the instructions are given here.

This is the Python screen that can be seen with Windows and Linux systems, either using serial or I2C the screen is the same. The update button simply updates the dialog box as internal to the Chip the ADC values are being updated all of the time.

Windows I2C

There is no output on a Windows PC that will give I2C and so some other device is required. For this a BV4221_V2 device is used that allows an I2C device to be connected via the USB. The Python code 'BV4221_i2c.py' is given in the link as the BV4221_V2 does require setting up for this it is best to follow the instructions on that link. If you have the dialog box running above then you can run the 'swsi2c.py' code and obtain the dialog box as above but this time via the I2C interface.

Raspberry Pi Serial

Voltages: A feature of using PCB 10 is that it has the circuit shown below. This means that you can run the IC at 5V but yet still use the 3.3V host wich would otherwise be a problem. This is because the TX output will be at the voltage supplied to the +V pin, i.e. 5V. The PCB however that can be supplied with this IC has the following circuit:

RB7 is the TX pin form the IC and D1 is a 3.3V* zener diode thus limiting the output to the RPi and providing a safe serial interface. This circuit also has the added bonus that multiple devices can share the TX line and thus the same serial bus.

*The diode may in fact be rated at a higher voltage due to the low resistance characteristic of zener diodes at low current.

Install the serial software as given in the instructions on this site. The connections to the RPi are as shown above. Note that the 5V supply is used to provide the power, it is therefore important to have the above circuit, which the PCB has.

If using the IC without the PCB then it must be supplied with 3V3.

Raspberry Pi I2C

Connection to the RPi via the I2C lines. Here the logic voltage is not important as the PRi will control this with its own internal pull up resistors.

1) Install all of the RPi software, this does take a bit of time.

2) Check that you have connected the device correct by by using I2C detect:

  • Older rpi: sudo i2cdetect -y 0
  • Newer rpi: sudo i2cdetect -y 1

If it can't find i2cdetect then the software has not been installed correctly, go back to step 1) For just the P012 connected it should look exactly like the above 0x34 (decimal 52) is the address of the device.


There are two libraries for the Arduino depending on the interface. Both are for version 1.01.

Both use the same library functions except the constructor which is slightly different. The example can be found in the appropriate (P011 or P012) library.

  • get(channel) returns the value on the ADC channel, maximum value is 1023 (10 bits). The channel is numbered from 1 to 9
  • digital(channel, value) Sets the digital output to be either high (1) or low (0). The channel number is 0 to 3
  • ref(value) sets the voltage reference, see the data sheet for the reference values. The value is from 0 to 4 and each one sets a different reference value.

Mini Project

This is a simple little project that can be built onto the prototyping area or the I/O connector can be used to fly-lead to a solderless breadboard.

The project consist of an LDR, and LED and a trimmer potentiometer. The trimmer sets the switching point and the LED comes on when it gets dark.


This is the circuit. The Python code gets the value from the trimmer via AN2 and this acts as a trigger point, values above this will turn on the LED and values below this will turn it off. The value for turning the LED on and off are obtained form the LDR. The LDR will give a higher reading the darker it gets, having the independent trimmer set the trigger point will work for most lighting conditions. The LED is simply attached to one of the digital outputs.

To use, when the Python code is running set the trimmer so the LED just turns off, cover the LDR with the hand and the LED will turn back on again.

The p011A class has the following methods:

  • adc.get(chan) # gets the value on a selected channel
  • adc.dout(chan,value) # sets one of the digital outputs to high (value=1) or low (value=0)
  • adc.vref(ref) # sets the voltage reference for values of ref, see the data sheet

The project consists of 4 files can can be downloaded in the downloads section

Below is a copy of the miniproject and is used from the command line as shown

For Windows:

python miniproj.py 0 COM21 115200 52 # I2C using BV4221 on COM21
python miniproj.py 1 COM14 9600 h # SERIAL on com14 with address 'h'

For RPi

python miniproj.py 0 1 "" 52 # I2C using bus 1
python miniproj.py 1 /dev/ttyAMA0 9600 h # SERIAL on ttyAMA0 with address 'h'


#! /usr/bin/python
# Mini Project for the PO11 see http://www.pichips.co.uk
# wget http://www.pin1.org/download/py/p015/p011A.py
# wget http://www.pin1.org/download/py/p015/sv3A.py
# wget http://www.pin1.org/download/py/p015/miniproj.py

import p011A     # adc class
from sv3A import sv3Bus
import sys
from time import sleep
LED = 1
POT = 2
LDR = 1
HYST = 5 # hysotresis
def adc_test(bustype,bus,adr):
    if bustype == '1':
        # serial
        adc = p011A.p011(bus,adr) # adr is string
    if bustype == '0':
        # i2c 
        adc = p011A.p011(bus,int(adr)) # adr will be a number 

    while 1: # do forever - probably not a good idea stop with ^ c
        setpoint = adc.get(POT) # get value on ch2 connected to pot
        v = adc.get(LDR) # get value of adc chan 1
        if v > setpoint + HYST:
            adc.dout(LED,1) # turn on led
        if v < setpoint - HYST:
            adc.dout(LED,0) # turn off led
        sleep(.1) # give other things a chance                

if __name__ == "__main__":
    # type = 1 for serial 0 for i2c
    # usage python mimiproj.py 1 COMx Baud h // for serial
    #       python mimiproj.py 0 COMx Baud 54 // for indows i2c
    #       python mimiproj.py 0 1 "" 54// for rpi i2c using bus 1
        bus = sv3Bus(int(sys.argv[1]),sys.argv[2],sys.argv[3]) # open bus for all devices
        msg = 'Cant open comport,'+str(sys.argv[2])+' use: see file miniproj.py'
        print msg

The project was built on the prototyping area and it looks like this.

Top and underside.


Example of using the P011A class

1) You need to install the software as described above.

2) Type python to get the
>>> prompt

Depending on the host platform (Windows, Rpi) and the method of access (Serial, I2C) will depend on how the bus is activated.

Windows Serial
>>> import p011A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(1,'COM14',9600) # open bus for all devices
>>> adc = p011A.p011(bus,'h')

Windows I2C using a BV4221 device
>>> import p011A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'COM21',115200) # open bus for all devices
>>> adc = p011A.p011(bus,52)

RPi Serial
>>> import p011A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'/dev/ttyAMA0',115200) # open bus for all devices
>>> adc = p011A.p011(bus,52)

>>> import p011A
>>> from sv3A import sv3Bus
>>> bus = sv3Bus(0,'1','') # change to '1' to '0' for older RPi
>>> adc = p011A.p011(bus,52)

If any of the above reports errors then go back and re-install the software, it is likely that something has been missed.

Try a few commands:

adc.ID() # get the identiy

adc.get(3) # gets the value on channel 3