PCF8591 ADC and DAC (YL-40)

The NXP PCF8591 on the YL-40 module: four 8-bit analog inputs and one analog output on I2C.

Aliases: YL-40, PCF8591 module, AD/DA converter. It is the analog board of the Freenove and SunFounder kits, and the way a Raspberry Pi, which has no analog inputs, reads a sensor.

Pins

Pin What it does
AOUT The DAC's output, while it is enabled.
AIN0 to AIN3 The four analog inputs, 0 V to the supply.
SCL, SDA The I2C bus; the module has its pull-ups. Address 0x48.
GND, VCC Ground and the supply, 2.5 to 6 V.

Properties

jumpers: on (as shipped) puts the board's own sensors on three inputs, the light-dependent resistor on AIN0, the thermistor on AIN1 and the blue trimmer on AIN3. Off, every input is yours.

While it runs

The three sliders are the light on the LDR, the temperature at the thermistor and the trimmer's position. The LED beside AOUT lights with the DAC's voltage.

Reading it on an Arduino

With the Adafruit library, which Mokxi ships as Adafruit_PCF8591.h:

#include <Wire.h>
#include <Adafruit_PCF8591.h>

Adafruit_PCF8591 pcf = Adafruit_PCF8591();

void setup() {
  Serial.begin(9600);
  pcf.begin();          // 0x48
  pcf.enableDAC(true);
}

void loop() {
  Serial.println(pcf.analogRead(3));   // the trimmer, 0 to 255
  pcf.analogWrite(200);                // about 3.9 V on AOUT
  delay(250);
}

With Wire.h alone: write the control byte (bit 6 the DAC enable, the low two bits the channel), then read two bytes and keep the second.

What the model gets right

From the NXP datasheet:

The read is one conversion behind. Each read starts a conversion and sends the result of the one before; the first byte after power-on is 0x80. A sketch that switches channel and reads one byte gets the old channel's value, which is why every tutorial reads twice.

All four input modes. Four single-ended inputs; three differential (each against AIN3); two single-ended and one differential; or two differential. Differential results are two's complement, -128 to 127.

Auto-increment walks the channels after each conversion, wrapping at the mode's channel count.

The DAC puts VCC x value / 256 on AOUT while it is enabled and leaves the pin high impedance when it is not.

The board's dividers. The LDR and the thermistor each sit under a 10 k pull-up, so more light and more heat both read lower; the trimmer is across the supply. Each drives its input as the divider it is, so a wire you add to the same input fights it as it would on the real board.

What it does not model

The converter's offset and gain errors (a few counts on a real chip), the oscillator and its output, the external reference (the YL-40 ties it to the supply, as here), and the load of the LED on AOUT. The DAC buffer's source resistance is an assumed 50 ohm.

Common mistakes

Reading one byte after changing channel, and getting the previous channel.

Expecting the LDR to read higher in more light: on this board it reads lower.

Leaving the jumpers on and wiring your own sensor to AIN0, AIN1 or AIN3: the board's sensor fights it. Take the jumper off.

See it in action

Analog board reads all three sensors and drives the DAC from the trimmer. Open it at /templates.