Skip to main content

pcf8591

8-bit ADC and DAC converter with 4 analog inputs and 1 analog output via I2C.

Overview

The pcf8591 node reads analog values from the PCF8591 8-bit ADC/DAC converter via I2C. This versatile chip provides 4 analog inputs and 1 analog output in a single package, making it an affordable solution for basic analog sensing. It supports single-ended and differential input modes, with configurable I2C addresses allowing up to 8 devices on the same bus. The built-in DAC can output a variable voltage for controlling analog circuits.

8-bit
Resolution (256)
4 In
Analog Inputs
1 Out
DAC Output
I2C
Interface

Properties

Property Type Default Description
i2cBus select /dev/i2c-1 I2C bus device
address select 0x48 I2C address. Options: 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f (set by A0-A2 pins)
channel select 0 ADC channel to read. Options: 0, 1, 2, 3
inputMode select single Input mode. Options: single (single-ended), differential, single_diff (mixed), two_diff (two differential pairs)
autoIncrement boolean false Auto-increment channel after each read (cycle through all channels)
vref number 3.3 Reference voltage for voltage calculation

Output

{
  "raw": 178,
  "voltage": 2.30,
  "channel": 0,
  "mode": "single",
  "vref": 3.3,
  "timestamp": 1640000000000
}

Wiring (I2C)

Connection

VCC → 3.3V (Pin 1)

GND → GND (Pin 6)

SDA → GPIO 2 (Pin 3)

SCL → GPIO 3 (Pin 5)

AIN0-3 → Analog inputs (0-3.3V)

AOUT → DAC output (0-3.3V)

Address pins A0-A2: tie to GND for 0x48, VCC for higher addresses

ASCII Wiring Diagram

  PCF8591           Raspberry Pi
  -------           ------------
  VCC  ──────────── 3.3V (Pin 1)
  GND  ──────────── GND  (Pin 6)
  SDA  ──────────── SDA  (Pin 3 / GPIO 2)
  SCL  ──────────── SCL  (Pin 5 / GPIO 3)
  A0   ──────────── GND  (address bit 0)
  A1   ──────────── GND  (address bit 1)
  A2   ──────────── GND  (address bit 2)

  AIN0 ── sensor/pot  (analog in ch0)
  AIN1 ── sensor/pot  (analog in ch1)
  AIN2 ── sensor/pot  (analog in ch2)
  AIN3 ── sensor/pot  (analog in ch3)
  AOUT ── load        (analog output)

Example: Multi-Channel Sensor Dashboard

Read all 4 analog channels to monitor different sensors and convert raw readings to meaningful values.

pcf8591 function dashboard
// Function node: Parse 4-channel analog data
// CH0: LDR (light sensor)
// CH1: NTC thermistor
// CH2: Potentiometer (user dial)
// CH3: Soil moisture sensor

var voltage = msg.voltage;
var channel = msg.channel;
var vref = msg.vref;
var result = flow.get('sensorData') || {};

switch(channel) {
    case 0: // LDR: lower voltage = brighter
        result.light = ((vref - voltage) / vref * 100).toFixed(1);
        break;
    case 1: // NTC: Steinhart-Hart approximation
        var resistance = voltage / (vref - voltage) * 10000;
        var tempK = 1 / (1/298.15 + Math.log(resistance/10000)/3950);
        result.temperature = (tempK - 273.15).toFixed(1);
        break;
    case 2: // Potentiometer: 0-100%
        result.dial = (voltage / vref * 100).toFixed(0);
        break;
    case 3: // Moisture: higher voltage = drier
        result.moisture = (100 - (voltage / vref * 100)).toFixed(0);
        break;
}

flow.set('sensorData', result);
msg.payload = result;
return msg;

Example: LED Brightness with DAC Output

Use the DAC output to control LED brightness based on ambient light readings from the ADC input.

// Function node: Auto-brightness LED control
var lightVoltage = msg.voltage;
var vref = msg.vref;

// Light level: 0 (dark) to 100 (bright)
var lightLevel = ((vref - lightVoltage) / vref * 100);

// Invert: darker ambient = brighter LED
var ledBrightness = 100 - lightLevel;
ledBrightness = Math.max(5, Math.min(100, ledBrightness));

// Convert to DAC value (0-255 for 8-bit)
var dacValue = Math.round(ledBrightness / 100 * 255);
var dacVoltage = (dacValue / 255 * vref);

msg.payload = {
    ambientLight: lightLevel.toFixed(1),
    ledBrightness: ledBrightness.toFixed(0),
    dacRaw: dacValue,
    dacVoltage: dacVoltage.toFixed(2)
};

// Send dacValue to pcf8591 DAC output
msg.dacOutput = dacValue;
return msg;

Example: Differential Voltage Measurement

Use differential mode to measure the voltage difference between two points, useful for bridge sensors and current sensing.

// Function node: Differential pressure sensor
// Using differential mode: AIN0 - AIN3
var raw = msg.raw;      // 0-255, centered at 128
var vref = msg.vref;

// Convert differential reading
// 128 = 0V difference, 255 = +Vref, 0 = -Vref
var diffVoltage = ((raw - 128) / 128) * vref;

// Convert to pressure (example: MPXV7002 sensor)
// Sensitivity: 1V per kPa, offset at 2.5V (= 0 kPa)
var pressure_kPa = diffVoltage * 1.0;

// Convert to other units
var pressure_psi = pressure_kPa * 0.14504;
var pressure_mbar = pressure_kPa * 10;

msg.payload = {
    raw: raw,
    diffVoltage: diffVoltage.toFixed(3),
    pressure_kPa: pressure_kPa.toFixed(3),
    pressure_psi: pressure_psi.toFixed(4),
    pressure_mbar: pressure_mbar.toFixed(1)
};

return msg;

Common Use Cases

Multi-Sensor Monitoring

Read up to 4 analog sensors (LDR, thermistor, moisture, gas) on a single I2C chip

Analog Output Control

Use DAC output to control LED brightness, motor speed, or analog actuators

Bridge Sensors

Differential mode for load cells, strain gauges, and Wheatstone bridge sensors

Knob/Slider Input

Read potentiometers for user controls, panel knobs, and slider inputs

Related Nodes