PCF8591 I2C Analog I/O Expander Library



A simple and efficient library to use the PCF8591 I2C 8-bit A/D and D/A converter with Arduino, ESP8266, ESP32, and other platforms. It provides 4 analog inputs and 1 analog output.
Author: Renzo Mischianti
Website: www.mischianti.org
GitHub: xreef/PCF8591_library
📚 Documentation & Articles
Complete documentation, tutorials, and examples are available on mischianti.org.
📋 Table of Contents
✨ Features
- 4 Analog Inputs: Read up to 4 analog channels over I2C.
- 1 Analog Output: Provides a true analog voltage output.
- 8-Bit Resolution: Both ADC and DAC operate at 8-bit resolution (0-255).
- Multiple Input Modes: Supports four single-ended inputs, three differential inputs, and combined modes.
- Efficient Reading: Read all 4 input channels in a single I2C transaction with
analogReadAll().
- Voltage Conversion: Built-in functions (
voltageRead, voltageWrite) to work directly with voltage levels.
- Flexible I2C Configuration: Custom I2C pins (SDA, SCL) can be specified for platforms like ESP8266/ESP32.
| Platform |
Support |
Notes |
| ESP32 |
✅ |
Full support |
| ESP8266 |
✅ |
Full support |
| Raspberry Pi Pico (RP2040) |
✅ |
Full support |
| Arduino (AVR, Uno, Mega, UNO R4) |
✅ |
Full support |
| Arduino SAMD (Nano 33 IoT, etc.) |
✅ |
Full support |
| STM32 |
✅ |
Full support |
📦 Installation
Arduino IDE (Library Manager)
- Open Arduino IDE.
- Go to
Sketch > Include Library > Manage Libraries....
- Search for “PCF8591_library” by Renzo Mischianti.
- Click
Install.
Add the library to your platformio.ini file:
lib_deps = xreef/PCF8591 library
Manual Installation
- Download the latest release from GitHub.
- Unzip the folder and rename it to
PCF8591_library.
- Move it to your Arduino
libraries folder.
- Restart the Arduino IDE.
🔌 Hardware Setup
Here is a typical wiring diagram for the PCF8591 module.

And here is the pinout of the IC:

🚀 API Overview
Constructor
// Basic constructor with I2C address
PCF8591(uint8_t address);
// For ESP8266/ESP32 with custom SDA/SCL pins
PCF8591(uint8_t address, uint8_t sda, uint8_t scl);
Core Functions
// Initialize the library (must be called in setup())
bool begin();
// Read all 4 analog inputs at once
PCF8591::AnalogInput analogReadAll();
// Read a single analog input channel
int analogRead(uint8_t channel, uint8_t mode = FOUR_SINGLE_ENDED);
// Write a value (0-255) to the analog output
void analogWrite(uint8_t value);
// Read the voltage from a specified analog pin
float voltageRead(uint8_t analogPin, bool microcontrollerReferenceVoltage = true, float referenceVoltage = 5.0);
// Write a voltage level to the analog output
void voltageWrite(float value, bool microcontrollerReferenceVoltage = true, float referenceVoltage = 5.0);
💡 Basic Usage
Here is a simple example of how to read an analog input and write to the analog output.
#include <Wire.h>
#include <PCF8591.h>
// Set I2C address (e.g., 0x48)
PCF8591 pcf8591(0x48);
void setup() {
Serial.begin(115200);
// Initialize the PCF8591
if (!pcf8591.begin()) {
Serial.println("Couldn't find PCF8591");
while (1);
}
Serial.println("PCF8591 initialized!");
}
void loop() {
// Write a value (e.g., 128) to the analog output
pcf8591.analogWrite(128);
// Read a single analog input (AIN0)
int analogValue = pcf8591.analogRead(AIN0);
Serial.print("Value from AIN0: ");
Serial.println(analogValue);
// Read all analog inputs at once
PCF8591::AnalogInput allValues = pcf8591.analogReadAll();
Serial.print("AIN0: "); Serial.print(allValues.ain0);
Serial.print(" | AIN1: "); Serial.print(allValues.ain1);
Serial.print(" | AIN2: "); Serial.print(allValues.ain2);
Serial.print(" | AIN3: "); Serial.println(allValues.ain3);
delay(500);
}
🔬 Advanced Reading Modes
The PCF8591 supports different analog input configurations, which can be selected using the analogRead function.

// Example: Read the differential value between AIN0 and AIN1
int differentialValue = pcf8591.analogRead(CHANNEL0, THREE_DIFFERENTIAL_INPUT);
// Example: Read AIN0 as single-ended and AIN1, AIN2 as differential
int value = pcf8591.analogRead(CHANNEL0, AIN0_SINGLE_AIN1_AIN2_DIFFERENTIAL);
⚡ Voltage Functions
The library provides helper functions to work directly with voltage values, abstracting the 8-bit conversion.
void setup() {
// ... setup code ...
pcf8591.begin();
}
void loop() {
// Set the analog output to 2.7 Volts
// Assumes the microcontroller VCC is the reference voltage.
pcf8591.voltageWrite(2.7);
delay(1000);
// Read the voltage from analog input AIN0
float inputVoltage = pcf8591.voltageRead(AIN0);
Serial.print("Voltage at AIN0: ");
Serial.print(inputVoltage);
Serial.println(" V");
delay(1000);
}
📝 Changelog
- 31/10/2025: v1.1.3 Minor change and README update
- 01/02/2024: v1.1.2 Add the possibility to insert address at begin() function
- 10/07/2023: v1.1.1 Add support for Arduino UNO R4
- 16/02/2023: v1.1.0 Fix STM32 support, add support for RP2040, and add custom SERCOM for SAMD.
- 06/04/2022: v1.0.2 Fix package size
📄 License
This library is released under the MIT License. See the LICENSE file for more details.
Copyright © 2019-2025 Renzo Mischianti
🤝 Contributing
Contributions are welcome! Please fork the repository, create a feature branch, and submit a pull request.
⭐ If this library helped your project, please give it a star on GitHub!
评论