Raspberry Pi and the PI-SPI-2AO 4-20mA Output Interface

Posted by Vytas Sinkevicius on

The 4-20 mA analog signal is still a major part of process control infrastructure. The Raspberry Pi coupled with the PI-SPI-2AO Analog Output Interface provides 2 channels of 4-20 mA Outputs. The VDC outputs are the buffered VDC signal going to the output current generator.

 Raspberry Pi 4-20 mA Output PI-SPI-2AO Interface

 The PI-SPI-2AO Interface uses a dual 12 bit DAC, the MCP4922. Each mA output has a mirror VDC output. The output circuit requires an external supply voltage. This example uses a wall adapter style 24 VDC power supply. Each output has a signal strength LED, in this example mA Output 1 is set to 20 mA and mA Output 2 is set to 4 mA.

Here is an excerpt of the schematic:

Raspbery Pi 4-20 mA Output PI-SPI-2AO Schematic Excerpt


The complete schematics can be found on the product page Pi-SPI-2AO link.

The MCP4922 is a dual channel 12 bit DAC, the above shows the output for channel 1. Here is a simplified description of how this circuit works:

  • The output from the DAC (0 to 4095 counts = 0 to 3.3 VDC) is buffered by U3A
  • U4A creates a current source across R6 based on the voltage output from U3A
  • Tthe same current flows thru R7
  • U4B creates the 0 to 20 mA thru R8 based on the voltage across R7 created by the current flow from U4A.
  • The output mA flows thru the  LD3 LED and the brightness of the LED is a simple signal strength indicator.

The outputs are very easily defined as follows:

Reference Vref = 3.3VDC. The mA circuit is optimized to give 20 mA at a 3VDC output from the DAC. Therefore, 20 mA = 3/3.3 * 4096 DA Counts = 3723 DA Counts.

Here is a very simple test routine written in C:


 * pispi_2ao.c

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <math.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>

// Define Pins

#define PIN_EN_DA  22
// Prototypes    
void Initialize_Pi_Hardware(void);
void Update_Analog_Output(unsigned int dac1, unsigned int dac2);
// Variables
unsigned int DAC1_Counts;
unsigned int DAC2_Counts;

// main
int main(void) {
      digitalWrite(PIN_EN_DA, HIGH);
        DAC1_Counts = 3723;  // 3VDC/3.3Vref * 4096 = 3723 = 20 mA    
        DAC2_Counts = 745;    // 745 = 4 mA    
        printf("DAC1 AD Counts Output  = %d \n", DAC1_Counts);    
        printf("DAC2 AD Counts Output  = %d \n\n", DAC2_Counts);    

        Update_Analog_Output(DAC1_Counts, DAC2_Counts);        

    return 0;

void Update_Analog_Output(unsigned int dac1, unsigned int dac2) {

    unsigned int  output;
    unsigned char buf[2];
    wiringPiSPISetup(1, 100000);
    // Output DAC 1
    output = 0x3000;                          // Address for DAC Channel 1
    output |= dac1;                             // OR in the DA COunts
    buf[0] = (output >> 8) & 0xff;          // Set the first data byte to transmit
    buf[1] = output & 0xff;                   // Set the second data byte to transmit
    digitalWrite(PIN_EN_DA, LOW);    // Start the SPI communication by Setting CS LOW
    wiringPiSPIDataRW(1,buf,2);         // Send the data bytes
    digitalWrite(PIN_EN_DA, HIGH);    // Stop the SPI comminication by Setting CS High
    // Output DAC 2
    output = 0xb000;                          // Address for DAC Channel 2
    output |= dac2;
    buf[0] = (output >> 8) & 0xff;
    buf[1] = output & 0xff;
    digitalWrite(PIN_EN_DA, LOW);
    digitalWrite(PIN_EN_DA, HIGH);

void Initialize_Pi_Hardware(void) {
    // SPI CS Enable Lines
    pinMode(PIN_EN_DA, OUTPUT);



Share this post

← Older Post Newer Post →

Leave a comment

Please note, comments must be approved before they are published.