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.
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:
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) {
wiringPiSetupGpio();
Initialize_Pi_Hardware();
digitalWrite(PIN_EN_DA, HIGH);
while(1)
{
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);
delay(500);
}
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
delay(500);
// 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);
wiringPiSPIDataRW(1,buf,2);
digitalWrite(PIN_EN_DA, HIGH);
}
void Initialize_Pi_Hardware(void) {
// SPI CS Enable Lines
pinMode(PIN_EN_DA, OUTPUT);
}