RPI AD/DA Extend Board SKU:EP-0022

From 52Pi Wiki
Jump to: navigation, search

RPI AD/DA Extend Board


This RPI AD/DA extend board reads analog voltage by PCF8591 chip, it can drive DAC module but can not offer power output.
It can be read by shell scripts and it can measure from 0V to 5V. It may has some different value due to different environment.

Because of the conversion speed is a little bit slow and poor accuracy , power consumption is large, worst case needs 200mA.


  • 1)Support I2C protocol
  • 2)Convert Speed: Less than 1Ksps
  • 3)Do Not offer input protect, so please be caution of the range of power supply.
  • 4)Analog Output: 250nA
  • 5)On-chip trace
  • 6)8bit A/D convert
  • 7)Dimensions: 1.9cm × 3.35cm



Package includes

  • 1x RPI AD/DA Extend Board

How to use

WiringPi supports an extension module for the PCF8591 Analog IO expander IC.
The Raspberry Pi has one I2C bus and the PCF8591 has a 3-bit address select port, so in-theory you can connect up 8 PCF8591’s to your Pi.
The PCF8591 has a 4-channel, 8-bit analog input port and a single channel analog output port.
It is the device used on the Quick2Wire analog board.


#include <wiringPi.h>
#include <pcf8591.h>


pcf8591Setup (int pinBase, int i2cAddress) ;

The pinBase can be any number you like above 64 and the i2cAddress is the address of the device in the I2C bus – 0x48  is the default but they can change if you have multiple devices.
Use the i2cdetect command (gpio i2cd) to probe your I2C bus to work out the right address to use.
You can call pcf8591Setup() as many times as needed for each PCF8791 you have in the system – just give it a different pin base and I2C bus address.
You don’t need to specify the number of pins here – the PCF8791 has 4 pins – the analog output uses base pin number 0 – the same as analog input 0.

The board normally uses the 3.3v supply as the reference voltage, so:
The input voltage is determined with:

vIn = value * 3.3 / 255

and the output voltage is:

vOut = value / 255 * 3.3

or to find the value for a given voltage:

value = vOut / 3.3 * 255


You need to load the I2C kernel modules before you can use I2C devices. Use the gpio command: gpio load i2c
Use the i2cdetect program to scan your I2C bus to make sure the Pi can see your devices. PCF8591’s will normally show up as 0x48, but when using multiple ones, they’ll each have a unique address (or should have!)
If you have a Rev 1 Pi, then the i2cdetect command is: i2cdetect -y 0 if you have a Rev. 2 Pi, then use i2cdetect -y 1
The gpio command supports the i2cdetect command and automatically caters for board revision. Simply type: gpio i2cd
The wiringPi PCF8591 driver knows which revision Pi you have, so you know need to take any special precautions – your code will work on either a Revision 1 or 2 Pi.
The PCF8591 does not have programmable internal pull-up resistors, but the pins when in input mode effectively have an internal pull-up active.
The analog output pin is normally in a high impedance mode until the very first read or write to the device. It may be prudent to perform an initial analog write to the device to set it to the initial value you need. 

How to setup and configure it

  • 1. Enable I2C function by editing configuration file as below:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

# blacklist spi and i2c by default (many users don't need them)
blacklist spi-bcm2708
#blacklist i2c-bcm2708   

comment this line : blacklist i2c-bcm2708, and save it, reboot your pi.

  • 2. Install python library and i2c-tools

sudo apt-get -y install python-smbus
sudo apt-get -y install i2c-tools

  • 3.Detect I2C address.

sudo i2cdetect -y -a 1


  • 4. Python Scripts:
#Read a value from analogue input 0 
#in A/D in the PCF8591P @ address 0x48
from smbus import SMBus
bus = SMBus(1)
print("Read the A/D")
print("Ctrl C to stop")
bus.write_byte(0x48, 1) # set control register to read channel 1
last_reading =-1
while(0 == 0): # do forever
   reading = bus.read_byte(0x48) # read A/D
   if(abs(last_reading - reading) > 2):
      last_reading = reading

Save it as PCF.py, then run it.
sudo python PCF.py

  • If you want use C Language to test it, you can follow those steps:
    • Install ncurses library support

sudo apt-get install libncurses5-dev
sudo vim.tiny PCF.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <ncurses.h>
int main( int argc, char **argv )
   int i;
   int r;
   int fd;
   int aout;
   unsigned char command[2];
   unsigned char value[4];
   unsigned char str[8];
   useconds_t delay = 5000;
   char *dev = "/dev/i2c-1";
   int addr = 0x48;
   int j;
   int key;
   nodelay(stdscr, true);
   printw("PCF8591 Test");
   mvaddstr(10, 0, "AIN0");
   mvaddstr(12, 0, "AIN1");
   mvaddstr(14, 0, "AIN2");
   mvaddstr(16, 0, "AIN3");
   fd = open(dev, O_RDWR );
   if(fd < 0)
      perror("Opening i2c device node\n");
      return 1;
   r = ioctl(fd, I2C_SLAVE, addr);
   if(r < 0)
      perror("Selecting i2c device\n");
   command[1] = 0;
   aout = 0;
      for(i = 0; i < 4; i++)
         command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i
         r = write(fd, &command, 2);
         // the read is always one step behind the selected input
         r = read(fd, &value[i], 1);
         if(r != 1)
            perror("reading i2c device\n");
         sprintf(str, "%3d", value[i]);
         mvaddstr(10+i+i, 12, str);
         value[i] = value[i] / 4;
         move(10 + i + i, 16);
         for(j = 0; j < 64; j++)
            if(j < value[i])
               addch(' ');
      key = getch();
      if(key == 43)
      else if(key == 45)
      else if(key > -1)
   printf("%d\n", key);

  • Compile it and run it.

gcc -o PCF PCF.c -lcurses
sudo ./PCF
You will see a lot of analog values output, you can use ctrl + C to interrupt it.


[How to drive PCF8591 using I2c|http://www.52pi.net/forum.php?mod=viewthread&tid=813]

Purchase Links

Shopping car.png
52Pi Store