Arduino PCF8591 Digital to Analog Tutorial

Output a Voltage from an Arduino

PCF8591 Arduino DAC TutorialOne of the things that your Arduino cannot do is provide a programmable voltage output.  For that,  you may want to use a digital to analog converter.  The PCF8591 is an easy to use device that includes (it does other things too) digital to analog converter.

It has what is known as an 8 bit digital to analog converter and can supply a voltage in value that equals the chips supply voltage.

In this tutorial,  we will use the Arduino to instruct the PCF8591 to supply a specific voltage and we will measure the output from the PCF8591 using an Arduino analog input pin.

How to Get One

Its available at any of the following locations…

eBay     Amazon      Deal Extreme      Bang Good     IC Station

 

PCF8591 Pinouts

In this tutorial,  you will create changing voltage output from AOUT.

PCF8591 Pin Outs

PCF8591 Arduino Voltage Output Tutorial

This tutorial will involve one set up,  but will include two sketches.

The first sketch will get you operating.

The second sketch will provide a simple means of improving the accuracy of your output.

Connect the PCF8591 to your Arduino

PCF8591 Tutorial 2 hook up

Copy, Paste and Load the Tutorial Sketch

// Henry's Bench
// PCF8591 Simple DAC
// Controlling voltage output with your Arduino

#include "Wire.h"
#define PCF8591 (0x90 >> 1) 

int Ain = 0;

int RawValue0 = 0;
int DACout = 0;
float DACoutVolt = 0.0;
float Voltage = 0.0;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}
void loop()
{
  for (int i = 0; i < 256; i++)
  {
    Wire.beginTransmission(PCF8591); 
    Wire.write(0x40); // sets the PCF8591 into a DA mode
    Wire.write(i); // sets the outputn
    Wire.endTransmission();     
    
    delay(500);    
    
    DACout = i;
    RawValue0 = analogRead(Ain);
    Voltage = (RawValue0 * 5.0 ) / 1024.0;
    DACoutVolt = (DACout * 5.0)/256.0;
    Serial.print("DAC Out = ");
    Serial.print(DACout);
    Serial.print("\tDAC Target Voltage = ");
    Serial.print(DACoutVolt, 3);
    Serial.print("\tRaw ADC Value = ");
    Serial.print(RawValue0);
    Serial.print("\tVoltage = ");
    Serial.println(Voltage, 3);
  }
}

Verify Your Tutorial Output

Open your Serial Monitor.  Your Output should look something like you see below.

PCF8591 Tutorial 2 Output

As you review the output, you will notice that the targeted DAC output voltage doesn’t quite match the actual voltage measured my your Arduino.

In the case of mine,  I was always measuring 30 to 40 millivolts lower than what I expect to see.

That should be expected.  The datasheet for the PCF8591 shows several sources of potential error in the analog output.  Among them is an offset error that be as much as 50 mV.

Copy, Paste and Upload the Sketch with Calibration

In the following sketch,  we find an offset in setup().  To do this we set the output of the DA to mid scale,  measure with it with the Arduino and record the difference.   With loop();  we apply this offset to what we predict the DAC output will be.

// Henry's Bench
// PCF8591 Simple DAC with Calibration
// Controlling voltage output with your Arduino

#include "Wire.h"
#define PCF8591 (0x90 >> 1)

int Ain = 0;

int RawValue0 = 0;
int DACout = 0;
float DACoutVolt = 0.0;
float Voltage = 0.0;
float Offset = 0.0;

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  //***** Calibrate
  Wire.beginTransmission(PCF8591);
  Wire.write(0x40); // sets the PCF8591 into a DA mode
  Wire.write(128); // sets the output to mid scale
  Wire.endTransmission();
  delay(10);
  DACoutVolt = (128.0 * 5.0) / 256.0;
  RawValue0 = analogRead(Ain);
  Voltage = (RawValue0 * 5.0 ) / 1024.0;
  Offset = DACoutVolt - Voltage;

}
void loop()
{
  for (int i = 0; i < 256; i++)
  {
    Wire.beginTransmission(PCF8591);
    Wire.write(0x40); // sets the PCF8591 into a DA mode
    Wire.write(i); // sets the outputn
    Wire.endTransmission();

    delay(500);

    DACout = i;
    RawValue0 = analogRead(Ain);
    Voltage = (RawValue0 * 5.0 ) / 1024.0;
    DACoutVolt = ((DACout * 5.0) / 256.0) - Offset;
    
    // Because the math could give us something less than zero
    // we need to set it to zero if it is.
    
    if( DACoutVolt < 0.0){
      DACoutVolt = 0.0;
    }   
    
    Serial.print("DAC Out = ");
    Serial.print(DACout);
    Serial.print("\tDAC Target Voltage = ");
    Serial.print(DACoutVolt, 3);
    Serial.print("\tRaw ADC Value = ");
    Serial.print(RawValue0);
    Serial.print("\tVoltage = ");
    Serial.println(Voltage, 3);


  }
}

Verify Your Calibrated Sketch Output

You should see a vast improvement as shown below:   It won’t be perfect as there are other sources of error adding to this offset error, including within the Arduino itself.  That said, you should be able to see that it is possible to make the DAC output of the PCF8591 far more predictable and thus more usable.

 

PCF8591 Tutorial 2b Output