### PlatformIO Installation Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Add this library to your platformio.ini file for project dependency management. ```ini lib_deps = xreef/PCF8574 library ``` -------------------------------- ### Basic Usage Example Source: https://github.com/xreef/pcf8574_library/blob/master/README.md A simple Arduino sketch demonstrating how to initialize the PCF8574 library, set pin modes, and control an LED based on button input. ```APIDOC ## Basic Usage Here is a simple example of how to use the library to control an LED and read a button. ```cpp #include #include // Set I2C address (e.g., 0x20) PCF8574 pcf8574(0x20); const uint8_t LED_PIN = P0; const uint8_t BUTTON_PIN = P1; void setup() { Serial.begin(115200); // Initialize the PCF8574 if (!pcf8574.begin()) { Serial.println("Couldn't find PCF8574"); while (1); } // Set pin modes pcf8574.pinMode(LED_PIN, OUTPUT); pcf8574.pinMode(BUTTON_PIN, INPUT); Serial.println("PCF8574 initialized!"); } void loop() { // Read the button state uint8_t buttonState = pcf8574.digitalRead(BUTTON_PIN); // If button is pressed (assuming active-low), turn on the LED if (buttonState == LOW) { pcf8574.digitalWrite(LED_PIN, HIGH); } else { pcf8574.digitalWrite(LED_PIN, LOW); } delay(100); } ``` **Important Note on Initialization Order:** Always configure PCF8574 pins with `pinMode()` (and set initial output levels with `digitalWrite()` if needed) *before* calling `begin()`. Some platforms or usage patterns rely on the initial pin configuration, and calling `begin()` before `pinMode()` can lead to unexpected behavior. Example: ```cpp pcf.pinMode(P0, OUTPUT); pcf.pinMode(P1, INPUT); // optional: pcf.digitalWrite(P0, LOW); if (!pcf.begin()) { Serial.println(F("ERROR: Could not initialize PCF8574! Check wiring, I2C address, SDA/SCL and power.")); while (1) delay(100); } ``` ``` -------------------------------- ### Initialization Methods Source: https://context7.com/xreef/pcf8574_library/llms.txt Methods to initialize the PCF8574 device and start I2C communication. ```APIDOC ## begin() / beginResult() ### Description Initializes the PCF8574 and starts I2C communication. Must be called after pinMode() configurations. ### Parameters - **None** ### Response - **begin()** (bool) - Returns true on success, false on failure. - **beginResult()** (enum) - Returns detailed error codes (OK, I2C_ERROR, NO_PINS_CONFIGURED, INVALID_ADDRESS). ``` -------------------------------- ### Initialize PCF8574 with begin() and beginResult() Source: https://context7.com/xreef/pcf8574_library/llms.txt Initializes the device and starts I2C communication. Must be called after configuring pin modes; beginResult() provides detailed error codes. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x20); void setup() { Serial.begin(115200); // IMPORTANT: Configure pins BEFORE calling begin() pcf8574.pinMode(P0, OUTPUT); pcf8574.pinMode(P1, INPUT); pcf8574.digitalWrite(P0, LOW); // Optional: set initial output state // Method 1: Simple boolean check if (pcf8574.begin()) { Serial.println("OK"); } else { Serial.println("Failed - check wiring, I2C address, SDA/SCL, and power"); } // Method 2: Using beginResult() for detailed error information // Requires #define PCF8574_BEGIN_ENUM_RESULT (enabled by default) BeginResult result = pcf8574.beginResult(); switch (result) { case BeginResult::OK: Serial.println("Initialization successful"); break; case BeginResult::I2C_ERROR: Serial.println("I2C error - no ACK from device"); break; case BeginResult::NO_PINS_CONFIGURED: Serial.println("Warning: No pins configured before begin()"); break; case BeginResult::INVALID_ADDRESS: Serial.println("Invalid I2C address"); break; } // Method 3: Using convenience wrapper with diagnostics if (pcf8574.beginWithResultPrint(true)) { Serial.println("Ready to use"); } } void loop() {} ``` -------------------------------- ### PCF8574 Constructor with Second I2C Bus (ESP32) Source: https://context7.com/xreef/pcf8574_library/llms.txt Initializes a PCF8574 instance using an alternate I2C bus on ESP32, enabling multiple independent I2C interfaces. This example configures the second I2C bus with custom pins and a specific clock frequency. ```cpp #include "Arduino.h" #include "PCF8574.h" // Create second I2C interface TwoWire I2Ctwo = TwoWire(1); // Initialize PCF8574 with second I2C bus PCF8574 pcf8574(&I2Ctwo, 0x20); void setup() { Serial.begin(115200); // Initialize second I2C with custom pins (SDA=21, SCL=22) at 400kHz I2Ctwo.begin(21, 22, 400000U); delay(1000); // Set all pins as outputs for (int i = 0; i < 8; i++) { pcf8574.pinMode(i, OUTPUT); } if (pcf8574.begin()) { Serial.println("PCF8574 on second I2C bus initialized"); } else { Serial.println("Initialization failed"); } } void loop() { static int pin = 0; pcf8574.digitalWrite(pin, HIGH); delay(400); pcf8574.digitalWrite(pin, LOW); delay(400); pin = (pin + 1) % 8; } ``` -------------------------------- ### Configure polling interval for distance measurement Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Example of calling the polling method with a specific interval to balance I2C traffic and precision. ```cpp ping_cm_poll(trigPin, echoPin, 400, 100) ``` -------------------------------- ### Basic PCF8574 LED and Button Control Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Demonstrates initializing the PCF8574, setting pin modes for an LED and a button, and reading the button state to control the LED. Ensure I2C is initialized and the PCF8574 is found before proceeding. ```cpp #include #include // Set I2C address (e.g., 0x20) PCF8574 pcf8574(0x20); const uint8_t LED_PIN = P0; const uint8_t BUTTON_PIN = P1; void setup() { Serial.begin(115200); // Initialize the PCF8574 if (!pcf8574.begin()) { Serial.println("Couldn't find PCF8574"); while (1); } // Set pin modes pcf8574.pinMode(LED_PIN, OUTPUT); pcf8574.pinMode(BUTTON_PIN, INPUT); Serial.println("PCF8574 initialized!"); } void loop() { // Read the button state uint8_t buttonState = pcf8574.digitalRead(BUTTON_PIN); // If button is pressed (assuming active-low), turn on the LED if (buttonState == LOW) { pcf8574.digitalWrite(LED_PIN, HIGH); } else { pcf8574.digitalWrite(LED_PIN, LOW); } delay(100); } ``` -------------------------------- ### Configure pins with pinMode() Source: https://context7.com/xreef/pcf8574_library/llms.txt Sets pin modes to INPUT, INPUT_PULLUP, or OUTPUT. OUTPUT mode supports an optional initial state parameter. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x20); void setup() { Serial.begin(115200); // Configure pin as OUTPUT (default initial state is HIGH) pcf8574.pinMode(P0, OUTPUT); // Configure pin as OUTPUT with initial LOW state pcf8574.pinMode(P1, OUTPUT, LOW); // Configure pin as OUTPUT with initial HIGH state pcf8574.pinMode(P2, OUTPUT, HIGH); // Configure pin as INPUT (pull-down, reads external signal) pcf8574.pinMode(P3, INPUT); // Configure pin as INPUT_PULLUP (internal pull-up enabled) pcf8574.pinMode(P4, INPUT_PULLUP); // Configure all pins in a loop for (int i = 5; i <= 7; i++) { pcf8574.pinMode(i, OUTPUT); } if (pcf8574.begin()) { Serial.println("PCF8574 ready"); } } void loop() {} ``` -------------------------------- ### PCF8574 Constructor (Basic) Source: https://context7.com/xreef/pcf8574_library/llms.txt Initializes a PCF8574 instance with a specified I2C address. Ensure correct wiring and address for successful initialization. ```cpp #include "Arduino.h" #include "PCF8574.h" // PCF8574 with A0, A1, A2 all connected to GND = address 0x20 PCF8574 pcf8574(0x20); // PCF8574A with A0 connected to VCC = address 0x39 PCF8574 pcf8574a(0x39); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, OUTPUT); pcf8574.pinMode(P1, INPUT); if (pcf8574.begin()) { Serial.println("PCF8574 initialized successfully"); } else { Serial.println("PCF8574 initialization failed - check wiring and address"); } } void loop() { // Use the expander... } ``` -------------------------------- ### PCF8574 Pin Mode and Initialization Order Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Emphasizes the critical order of operations: configure pin modes using `pinMode()` before calling `begin()`. Incorrect order can lead to unexpected behavior on some platforms. ```cpp pcf.pinMode(P0, OUTPUT); pcf.pinMode(P1, INPUT); // optional: pcf.digitalWrite(P0, LOW); if (!pcf.begin()) { Serial.println(F("ERROR: Could not initialize PCF8574! Check wiring, I2C address, SDA/SCL and power.")); while (1) delay(100); } ``` -------------------------------- ### PCF8574 Library Methods Source: https://github.com/xreef/pcf8574_library/blob/master/keywords.txt A collection of methods for controlling the PCF8574 device, including initialization, pin configuration, and data reading/writing. ```APIDOC ## PCF8574 Library Methods ### Description Methods for initializing the device, setting pin modes, and performing digital I/O operations. ### Methods - **begin()**: Initializes the PCF8574 device. - **pinMode(pin, mode)**: Sets the mode of a specific pin. - **digitalRead(pin)**: Reads the state of a specific pin. - **digitalReadAll()**: Reads the state of all pins. - **digitalWrite(pin, value)**: Writes a value to a specific pin. - **digitalWriteAll(value)**: Writes a value to all pins. - **readBuffer()**: Reads the internal buffer of the device. ``` ```APIDOC ## Interrupt and Encoder Methods ### Description Methods for managing hardware interrupts and reading encoder values. ### Methods - **attachInterrupt(pin, callback, mode)**: Attaches an interrupt to a pin. - **detachInterrupt(pin)**: Detaches an interrupt from a pin. - **encoder(pinA, pinB)**: Configures encoder pins. - **readEncoderValue()**: Returns the current encoder count. - **getLatency()**: Gets the current latency setting. - **setLatency(value)**: Sets the latency for the device. ``` ```APIDOC ## Ultrasonic Sensor Methods ### Description Methods for interfacing with ultrasonic sensors using the PCF8574. ### Methods - **ping() / pingPoll()**: Triggers a ping. - **ping_cm() / ping_cm_poll()**: Triggers a ping and returns distance in cm. - **ping_in() / ping_in_poll()**: Triggers a ping and returns distance in inches. - **ping_median() / ping_median_poll()**: Performs a median ping operation. - **pulseIn() / pulseInPoll()**: Measures pulse duration. - **microsecondsToDistance_cm(duration)**: Converts microseconds to cm. - **microsecondsToDistance_in(duration)**: Converts microseconds to inches. ``` -------------------------------- ### Basic PCF8574 Constructor Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Instantiate the PCF8574 object with its I2C address. ```cpp PCF8574(uint8_t address); ``` -------------------------------- ### Initialize Rotary Encoder Support Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Requires enabling PCF8574_ENCODER_SUPPORT or PCF8574_ENCODER_SUPPORT_OPTIMIZED in PCF8574.h before use. ```cpp // In PCF8574.h, uncomment one of these: // #define PCF8574_ENCODER_SUPPORT // #define PCF8574_ENCODER_SUPPORT_OPTIMIZED #include #include PCF8574 pcf8574(0x20); // Define encoder pins const uint8_t ENCODER_A = P0; const uint8_t ENCODER_B = P1; volatile long encoderValue = 0; void setup() { Serial.begin(115200); pcf8574.begin(); // Initialize the encoder pcf8574.encoder(ENCODER_A, ENCODER_B); pcf8574.setEncoderValue(0); } void loop() { long newEncoderValue = pcf8574.getEncoderValue(); if (newEncoderValue != encoderValue) { Serial.print("Encoder value: "); Serial.println(newEncoderValue); encoderValue = newEncoderValue; } delay(10); } ``` -------------------------------- ### Measure distance with HC-SR04 via PCF8574 Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Demonstrates initializing the PCF8574 pins and performing a distance measurement using the ping_cm_poll method. ```cpp #include #include PCF8574 pcf(0x20); const uint8_t trigPinPCF = P1; // TRIG on PCF8574 P1 const uint8_t echoPinPCF = P0; // ECHO on PCF8574 P0 const unsigned long MAX_DISTANCE = 400; // Maximum distance in cm void setup() { Serial.begin(115200); // Configure PCF8574 pins BEFORE calling begin() pcf.pinMode(trigPinPCF, OUTPUT); pcf.pinMode(echoPinPCF, INPUT); pcf.digitalWrite(trigPinPCF, LOW); // Initialize PCF8574 after pins are configured if (!pcf.begin()) { Serial.println(F("ERROR: Could not initialize PCF8574! Check wiring, I2C address, SDA/SCL and power.")); while (1) delay(100); } } void loop() { // Simple distance measurement in cm (with polling for efficiency) unsigned long distance = pcf.ping_cm_poll(trigPinPCF, echoPinPCF, MAX_DISTANCE, 100); Serial.print("Distance: "); Serial.print(distance); Serial.println(" cm"); delay(500); } ``` -------------------------------- ### PCF8574 Constructor with Interrupt Support Source: https://context7.com/xreef/pcf8574_library/llms.txt Initializes a PCF8574 instance with hardware interrupt support. The specified callback function is triggered when any input pin changes state. Ensure the interrupt pin is correctly configured. ```cpp #include "Arduino.h" #include "PCF8574.h" #define INTERRUPT_PIN 2 // Arduino Uno: pins 2 or 3 are interrupt-capable void keyPressedOnPCF8574(); // Forward declaration // Initialize with address, interrupt pin, and ISR function PCF8574 pcf8574(0x39, INTERRUPT_PIN, keyPressedOnPCF8574); volatile bool keyPressed = false; void setup() { Serial.begin(115200); pcf8574.pinMode(P0, OUTPUT); pcf8574.pinMode(P1, INPUT); if (pcf8574.begin()) { Serial.println("PCF8574 with interrupt initialized"); } else { Serial.println("Initialization failed"); } } void loop() { if (keyPressed) { uint8_t val = pcf8574.digitalRead(P1); Serial.print("Button state: "); Serial.println(val); keyPressed = false; } } // Interrupt Service Routine - keep it short and fast void keyPressedOnPCF8574() { keyPressed = true; } ``` -------------------------------- ### PCF8574 Constructor for ESP32/ESP8266 Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Instantiate the PCF8574 object with custom SDA and SCL pins for platforms like ESP8266 and ESP32. ```cpp PCF8574(uint8_t address, uint8_t sda, uint8_t scl); ``` -------------------------------- ### isOnline() Source: https://context7.com/xreef/pcf8574_library/llms.txt Probes the I2C bus to check if the PCF8574 device is responding. ```APIDOC ## isOnline() ### Description Probes the I2C bus to check if the PCF8574 device is responding. Useful for detecting connection issues at runtime. ### Response - **status** (bool) - Returns true if the device is online, false otherwise. ``` -------------------------------- ### Core Functions Source: https://github.com/xreef/pcf8574_library/blob/master/README.md This section details the fundamental functions available in the PCF8574 library for controlling I/O pins and reading sensor data. ```APIDOC ## Core Functions ### `begin(uint8_t defaultVal = 0xFF)` * **Description**: Initializes the PCF8574 library. Must be called in `setup()`. * **Parameters**: * `defaultVal` (uint8_t) - Optional - The default value to set for all pins upon initialization. Defaults to `0xFF` (all high). * **Returns**: `bool` - `true` if initialization was successful, `false` otherwise. ### `pinMode(uint8_t pin, uint8_t mode)` * **Description**: Sets the mode of a specific pin to either `INPUT` or `OUTPUT`. * **Parameters**: * `pin` (uint8_t) - The pin number (e.g., `P0`, `P1`, etc.). * `mode` (uint8_t) - The pin mode (`INPUT` or `OUTPUT`). ### `digitalWrite(uint8_t pin, uint8_t value)` * **Description**: Writes a `HIGH` or `LOW` value to a digital pin. * **Parameters**: * `pin` (uint8_t) - The pin number. * `value` (uint8_t) - The value to write (`HIGH` or `LOW`). ### `digitalRead(uint8_t pin)` * **Description**: Reads the state of a digital pin. * **Parameters**: * `pin` (uint8_t) - The pin number. * **Returns**: `uint8_t` - The state of the pin (`HIGH` or `LOW`). ### `digitalReadAll()` * **Description**: Reads the state of all 8 pins at once. * **Returns**: `PCF8574::DigitalInput` - A structure containing the state of all pins. ### `pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)` * **Description**: Measures the duration (in microseconds) of a pulse on a pin. This is a low-level function. * **Parameters**: * `pin` (uint8_t) - The pin number. * `state` (uint8_t) - The state to wait for (`HIGH` or `LOW`). * `timeout` (unsigned long) - The maximum time to wait for the pulse in microseconds. * **Returns**: `unsigned long` - The duration of the pulse in microseconds, or `0` if the timeout occurred. ### `pulseInPoll(uint8_t pin, uint8_t state, unsigned long timeout, unsigned int pollIntervalMicros)` * **Description**: Similar to `pulseIn`, but allows specifying a polling interval for more controlled timing. * **Parameters**: * `pin` (uint8_t) - The pin number. * `state` (uint8_t) - The state to wait for (`HIGH` or `LOW`). * `timeout` (unsigned long) - The maximum time to wait for the pulse in microseconds. * `pollIntervalMicros` (unsigned int) - The interval in microseconds between polls. * **Returns**: `unsigned long` - The duration of the pulse in microseconds, or `0` if the timeout occurred. ### Ultrasonic Sensor Methods (HC-SR04 compatible, NewPing-style) * **`ping(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500)`**: Sends a ping and returns the distance in centimeters. Uses default timeout. * **`pingPoll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100)`**: Similar to `ping` but with a configurable poll interval. * **`ping_cm(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500)`**: Returns the distance in centimeters. Uses default timeout. * **`ping_cm_poll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100)`**: Similar to `ping_cm` but with a configurable poll interval. * **`ping_in(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500)`**: Returns the distance in inches. Uses default timeout. * **`ping_in_poll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100)`**: Similar to `ping_in` but with a configurable poll interval. * **`ping_median(uint8_t trigPin, uint8_t echoPin, uint8_t iterations = 5, unsigned long maxDistance_cm = 500)`**: Calculates the median distance over multiple iterations for more stable readings. * **`ping_median_poll(uint8_t trigPin, uint8_t echoPin, uint8_t iterations = 5, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100)`**: Similar to `ping_median` but with a configurable poll interval. * **`microsecondsToDistance_cm(unsigned long microseconds)`**: Static method to convert microseconds to centimeters. * **`microsecondsToDistance_in(unsigned long microseconds)`**: Static method to convert microseconds to inches. * **Parameters for ping methods**: * `trigPin` (uint8_t) - The trigger pin for the ultrasonic sensor. * `echoPin` (uint8_t) - The echo pin for the ultrasonic sensor. * `maxDistance_cm` (unsigned long) - The maximum distance to measure in centimeters. * `iterations` (uint8_t) - The number of iterations for median calculation. * `pollIntervalMicros` (unsigned int) - The interval in microseconds between polls. * **Returns**: `unsigned long` - The calculated distance in the specified unit (cm or inches). ``` -------------------------------- ### PCF8574 Constructor with Interrupt Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Instantiate the PCF8574 object with an interrupt pin and a callback function for interrupt handling. ```cpp PCF8574(uint8_t address, uint8_t interruptPin, void (*interruptFunction)()); ``` -------------------------------- ### PCF8574 Constructor Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Initializes the PCF8574 object with the specified I2C address, optional custom I2C pins, or interrupt configuration. ```APIDOC ## Constructor ### Description Initializes the PCF8574 instance. Multiple overloads are available depending on the hardware configuration. ### Parameters - **address** (uint8_t) - Required - The I2C address of the PCF8574 (0x20-0x27 or 0x38-0x3F). - **sda** (uint8_t) - Optional - Custom SDA pin for ESP8266/ESP32. - **scl** (uint8_t) - Optional - Custom SCL pin for ESP8266/ESP32. - **interruptPin** (uint8_t) - Optional - The pin connected to the PCF8574 INT output. - **interruptFunction** (void (*)()) - Optional - The callback function to execute on interrupt. ### Request Example // Basic constructor PCF8574 pcf(0x20); // Constructor with custom I2C pins PCF8574 pcf(0x20, 21, 22); // Constructor with interrupt PCF8574 pcf(0x20, 2, myInterruptHandler); ``` -------------------------------- ### PCF8574 Core Functions Overview Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Lists the primary functions available in the PCF8574 library for I2C I/O expansion. These include initialization, pin configuration, digital read/write, and pulse measurement. ```cpp // Initialize the library (must be called in setup()) bool begin(uint8_t defaultVal = 0xFF); // Set a pin as INPUT or OUTPUT void pinMode(uint8_t pin, uint8_t mode); // Write a value (HIGH/LOW) to a pin void digitalWrite(uint8_t pin, uint8_t value); // Read a value (HIGH/LOW) from a pin uint8_t digitalRead(uint8_t pin); // Read all 8 pins at once PCF8574::DigitalInput digitalReadAll(); // Pulse measurement (low-level) unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); unsigned long pulseInPoll(uint8_t pin, uint8_t state, unsigned long timeout, unsigned int pollIntervalMicros); // Ultrasonic sensor methods (HC-SR04 compatible, NewPing-style) unsigned long ping(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500); unsigned long pingPoll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100); unsigned long ping_cm(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500); unsigned long ping_cm_poll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100); unsigned long ping_in(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500); unsigned long ping_in_poll(uint8_t trigPin, uint8_t echoPin, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100); unsigned long ping_median(uint8_t trigPin, uint8_t echoPin, uint8_t iterations = 5, unsigned long maxDistance_cm = 500); unsigned long ping_median_poll(uint8_t trigPin, uint8_t echoPin, uint8_t iterations = 5, unsigned long maxDistance_cm = 500, unsigned int pollIntervalMicros = 100); static unsigned long microsecondsToDistance_cm(unsigned long microseconds); static unsigned long microsecondsToDistance_in(unsigned long microseconds); ``` -------------------------------- ### digitalReadAll() Source: https://context7.com/xreef/pcf8574_library/llms.txt Reads all 8 pins in a single I2C transaction. ```APIDOC ## digitalReadAll() ### Description Reads all 8 pins in a single I2C transaction for improved efficiency. ### Response - **DigitalInput** (struct) - Returns a struct containing the state of all pins (p0 through p7). ``` -------------------------------- ### digitalWrite() Source: https://context7.com/xreef/pcf8574_library/llms.txt Writes a logic level to an output pin. ```APIDOC ## digitalWrite() ### Description Writes a HIGH or LOW value to an output pin. ### Parameters - **pin** (uint8_t) - Required - The pin number (P0-P7). - **value** (uint8_t) - Required - The value to write (HIGH or LOW). ### Response - **success** (bool) - Returns true if the I2C transmission was successful. ``` -------------------------------- ### pinMode() Source: https://context7.com/xreef/pcf8574_library/llms.txt Configures the mode of a specific pin on the PCF8574. ```APIDOC ## pinMode() ### Description Configures a pin as INPUT, INPUT_PULLUP, or OUTPUT. For OUTPUT mode, an optional third parameter sets the initial state. ### Parameters - **pin** (uint8_t) - Required - The pin number (P0-P7). - **mode** (uint8_t) - Required - The mode (INPUT, INPUT_PULLUP, OUTPUT). - **initialState** (uint8_t) - Optional - Initial state for OUTPUT mode (HIGH or LOW). ``` -------------------------------- ### Interrupt Handling Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Demonstrates how to use interrupts with the PCF8574 library to detect input changes without constant polling. This involves connecting the PCF8574's INT pin to an interrupt-capable pin on the microcontroller. ```APIDOC ## Interrupts You can use an interrupt to detect input changes without constantly polling the device. 1. Connect the `INT` pin of the PCF8574 to an interrupt-capable pin on your microcontroller. 2. Define an interrupt handler function (ISR). 3. Initialize the library with the interrupt pin and handler. ```cpp // Global flag to be set by the ISR volatile bool keyPressed = false; // Interrupt Service Routine (ISR) // NOTE: Keep this function as short and fast as possible. void ICACHE_RAM_ATTR keyPressedOnPCF8574() { keyPressed = true; } // Initialize with interrupt pin and ISR // Example assumes PCF8574 is at address 0x20 and interrupt is connected to digital pin D3 PCF8574 pcf8574(0x20, D3, keyPressedOnPCF8574); // Address, Interrupt Pin, ISR void setup() { Serial.begin(115200); // ... other setup code ... // Initialize PCF8574 with interrupt if (!pcf8574.begin()) { Serial.println("Couldn't find PCF8574"); while (1); } Serial.println("PCF8574 initialized with interrupt!"); } void loop() { if (keyPressed) { // Reset the flag keyPressed = false; // An input on the PCF8574 has changed, read all values PCF8574::DigitalInput values = pcf8574.digitalReadAll(); Serial.print("Input change detected. P0 state: "); Serial.println(values.p0); // ... check other pins as needed ... } } ``` ``` -------------------------------- ### Control I2C Latency with getLatency() and setLatency() Source: https://context7.com/xreef/pcf8574_library/llms.txt Manage the delay between I2C reads to reduce bus traffic. Default latency is 10ms. Set to 0 to enable PCF8574_LOW_LATENCY for immediate reads. Higher latency can be used for slow-changing inputs. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x20); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, INPUT); // Get current latency setting int currentLatency = pcf8574.getLatency(); Serial.print("Default latency: "); Serial.print(currentLatency); Serial.println(" ms"); // Set custom latency (e.g., 50ms for slow-changing inputs) pcf8574.setLatency(50); Serial.println("Latency set to 50ms"); // For time-critical applications, set to 0 // pcf8574.setLatency(0); if (pcf8574.begin()) { Serial.println("Ready"); } } void loop() { // With higher latency, consecutive reads within the latency period // return buffered values without I2C communication uint8_t val1 = pcf8574.digitalRead(P0); uint8_t val2 = pcf8574.digitalRead(P0); // May return buffered value // Force immediate read regardless of latency uint8_t val3 = pcf8574.digitalRead(P0, true); // Always reads from device Serial.print("Values: "); Serial.print(val1); Serial.print(", "); Serial.print(val2); Serial.print(", "); Serial.println(val3); delay(100); } ``` -------------------------------- ### Read all pins with digitalReadAll() Source: https://context7.com/xreef/pcf8574_library/llms.txt Reads all 8 pins in a single I2C transaction, returning a DigitalInput struct for efficient access. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x38); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, INPUT); pcf8574.pinMode(P1, INPUT_PULLUP); pcf8574.pinMode(P2, INPUT); pcf8574.pinMode(P3, INPUT); pcf8574.pinMode(P4, OUTPUT); pcf8574.pinMode(P5, OUTPUT); pcf8574.pinMode(P6, OUTPUT); pcf8574.pinMode(P7, OUTPUT); if (pcf8574.begin()) { Serial.println("OK"); } } void loop() { // Read all 8 pins at once PCF8574::DigitalInput values = pcf8574.digitalReadAll(); Serial.print("P0: "); Serial.print(values.p0); Serial.print(" P1: "); Serial.print(values.p1); Serial.print(" P2: "); Serial.print(values.p2); Serial.print(" P3: "); Serial.println(values.p3); // Access individual pin values from the struct if (values.p0 == HIGH) { Serial.println("P0 is HIGH"); } delay(500); } ``` -------------------------------- ### Write to All Pins at Once with digitalWriteAll() Source: https://context7.com/xreef/pcf8574_library/llms.txt Efficiently writes to all 8 pins of the PCF8574 in a single I2C transaction. Ensure pins are configured as OUTPUT before use. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x38); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, INPUT); pcf8574.pinMode(P1, INPUT); pcf8574.pinMode(P2, INPUT); pcf8574.pinMode(P3, INPUT); pcf8574.pinMode(P4, OUTPUT); pcf8574.pinMode(P5, OUTPUT); pcf8574.pinMode(P6, OUTPUT); pcf8574.pinMode(P7, OUTPUT); if (pcf8574.begin()) { Serial.println("OK"); } } void loop() { // Create struct with desired output values PCF8574::DigitalInput outputs; outputs.p4 = HIGH; outputs.p5 = LOW; outputs.p6 = HIGH; outputs.p7 = LOW; // Write all values at once bool success = pcf8574.digitalWriteAll(outputs); if (success) { Serial.println("All pins written successfully"); } delay(1000); // Toggle pattern outputs.p4 = LOW; outputs.p5 = HIGH; outputs.p6 = LOW; outputs.p7 = HIGH; pcf8574.digitalWriteAll(outputs); delay(1000); } ``` -------------------------------- ### digitalRead() Source: https://context7.com/xreef/pcf8574_library/llms.txt Reads the state of an input pin. ```APIDOC ## digitalRead() ### Description Reads the current state of an input pin. Supports an optional parameter to bypass the internal buffer. ### Parameters - **pin** (uint8_t) - Required - The pin number (P0-P7). - **forceRead** (bool) - Optional - If true, forces an immediate I2C read bypassing the internal buffer. ### Response - **value** (uint8_t) - Returns HIGH or LOW. ``` -------------------------------- ### Ping Measurement Methods Source: https://context7.com/xreef/pcf8574_library/llms.txt Methods to trigger an HC-SR04 sensor and measure the echo response duration. ```APIDOC ## ping() / pingPoll() ### Description Sends a trigger pulse and measures the echo response duration in microseconds. The poll variant reduces I2C traffic by polling the echo pin at defined intervals. ### Parameters - **trigPin** (uint8_t) - Required - The PCF8574 pin connected to the sensor trigger. - **echoPin** (uint8_t) - Required - The PCF8574 pin connected to the sensor echo. - **maxDistance** (unsigned long) - Required - Maximum distance to measure in cm. - **pollInterval** (unsigned long) - Required (for Poll variant) - Interval in microseconds between I2C reads. ``` -------------------------------- ### Enable Low Memory Mode with PCF8574_LOW_MEMORY Source: https://context7.com/xreef/pcf8574_library/llms.txt When PCF8574_LOW_MEMORY is defined in PCF8574.h, digitalReadAll() returns a single byte instead of a struct, conserving approximately 7 bytes of RAM. This is beneficial for memory-constrained devices. ```cpp // In PCF8574.h, uncomment: #define PCF8574_LOW_MEMORY #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x20); void setup() { Serial.begin(115200); for (int i = 0; i < 8; i++) { pcf8574.pinMode(i, INPUT); } if (pcf8574.begin()) { Serial.println("Low memory mode active"); } } void loop() { // In low memory mode, digitalReadAll returns a byte byte pinValues = pcf8574.digitalReadAll(); // Extract individual pin values using bitwise operations bool p0 = (pinValues & bit(0)) > 0; bool p1 = (pinValues & bit(1)) > 0; bool p2 = (pinValues & bit(2)) > 0; bool p3 = (pinValues & bit(3)) > 0; bool p4 = (pinValues & bit(4)) > 0; bool p5 = (pinValues & bit(5)) > 0; bool p6 = (pinValues & bit(6)) > 0; bool p7 = (pinValues & bit(7)) > 0; Serial.print("Raw byte: 0b"); Serial.println(pinValues, BIN); Serial.print("P0="); Serial.print(p0); Serial.print(" P1="); Serial.print(p1); Serial.print(" P2="); Serial.print(p2); Serial.print(" P3="); Serial.println(p3); delay(500); } ``` -------------------------------- ### Configure Rotary Encoder with encoder() Source: https://context7.com/xreef/pcf8574_library/llms.txt Configures two pins for rotary encoder input using INPUT_PULLUP mode. This function is used in conjunction with readEncoderValue() to read encoder rotations. ```cpp #include "Arduino.h" #include "PCF8574.h" #define INTERRUPTED_PIN D7 void ICACHE_RAM_ATTR updateEncoder(); PCF8574 pcf8574(0x38, INTERRUPTED_PIN, updateEncoder); int encoderPinA = P0; int encoderPinB = P1; volatile long encoderValue = 0; bool changed = false; void setup() { Serial.begin(9600); // Initialize encoder pins (sets both as INPUT_PULLUP internally) pcf8574.encoder(encoderPinA, encoderPinB); // Button on encoder (optional) pcf8574.pinMode(P2, INPUT); if (pcf8574.begin()) { Serial.println("Encoder initialized"); } } void loop() { if (changed) { Serial.print("Encoder value: "); Serial.println(encoderValue); changed = false; } } void updateEncoder() { // Read encoder and update value if (pcf8574.readEncoderValue(encoderPinA, encoderPinB, &encoderValue)) { changed = true; } } ``` -------------------------------- ### Read Pins in Low Memory Mode Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Requires enabling PCF8574_LOW_MEMORY in PCF8574.h. digitalReadAll returns a byte instead of a struct, requiring bitwise operations to extract pin states. ```cpp // In your sketch, after enabling low memory mode: byte pinValues = pcf8574.digitalReadAll(); bool p0 = (pinValues & bit(0)) > 0; bool p1 = (pinValues & bit(1)) > 0; // ... and so on for all 8 pins ``` -------------------------------- ### Check I2C Transmission Status with isLastTransmissionSuccess() Source: https://context7.com/xreef/pcf8574_library/llms.txt Verify if the most recent I2C transmission was successful. Use getTransmissionStatusCode() to retrieve the specific I2C error code, where 0 indicates success. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x20); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, OUTPUT); pcf8574.begin(); } void loop() { // Perform a write operation pcf8574.digitalWrite(P0, HIGH); // Check if transmission was successful if (pcf8574.isLastTransmissionSuccess()) { Serial.println("Write successful"); } else { Serial.print("Write failed! Error code: "); Serial.println(pcf8574.getTransmissionStatusCode()); // Error codes: // 0 = success // 1 = data too long for transmit buffer // 2 = received NACK on transmit of address // 3 = received NACK on transmit of data // 4 = other error } delay(1000); pcf8574.digitalWrite(P0, LOW); uint8_t status = pcf8574.getTransmissionStatusCode(); Serial.print("Transmission status code: "); Serial.println(status); delay(1000); } ``` -------------------------------- ### ping_median() / ping_median_poll() Source: https://context7.com/xreef/pcf8574_library/llms.txt Takes multiple distance measurements and returns the median value for more stable readings. ```APIDOC ## ping_median() / ping_median_poll() ### Description Takes multiple distance measurements and returns the median value for more stable readings. Useful for filtering out erratic measurements from ultrasonic sensors. ### Parameters - **trigPinPCF** (uint8_t) - Required - The pin connected to the sensor trigger. - **echoPinPCF** (uint8_t) - Required - The pin connected to the sensor echo. - **samples** (int) - Required - Number of samples to take. - **MAX_DISTANCE** (unsigned long) - Required - The maximum distance to measure. - **poll_interval** (unsigned long) - Required (poll only) - The interval for polling the I2C bus. ### Response - **distance** (unsigned long) - The median distance in centimeters. ``` -------------------------------- ### Measure Distance with HC-SR04 Source: https://github.com/xreef/pcf8574_library/blob/master/README.md Demonstrates basic distance measurement using the PCF8574 to read the echo pulse. Ensure pin modes are configured before calling pcf.begin(). ```cpp #include #include PCF8574 pcf(0x20); const int trigPin = 9; // A standard digital pin on your Arduino/ESP const uint8_t echoPinPCF = P0; // A pin on the PCF8574 void setup() { Serial.begin(115200); // Configure pin modes BEFORE initializing the PCF8574 pcf.pinMode(echoPinPCF, INPUT); pinMode(trigPin, OUTPUT); // Initialize the PCF8574 (after pinMode) if (!pcf.begin()) { Serial.println("Couldn't find PCF8574"); while (1); } } void loop() { // Trigger the sensor digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Measure the echo pulse duration on the PCF8574 pin // Timeout is 30000 microseconds (30ms) unsigned long duration = pcf.pulseIn(echoPinPCF, HIGH, 30000UL); // Calculate distance unsigned long distanceCm = duration / 29 / 2; Serial.print("Distance: "); Serial.print(distanceCm); Serial.println(" cm"); delay(500); } ``` -------------------------------- ### Read from pins with digitalRead() Source: https://context7.com/xreef/pcf8574_library/llms.txt Reads the state of an input pin. An optional parameter forces an immediate I2C read, bypassing the internal buffer. ```cpp #include "Arduino.h" #include "PCF8574.h" PCF8574 pcf8574(0x39); void setup() { Serial.begin(115200); pcf8574.pinMode(P0, OUTPUT); pcf8574.pinMode(P1, INPUT); if (pcf8574.begin()) { Serial.println("OK"); } } void loop() { // Standard read (uses internal buffer with latency optimization) uint8_t val = pcf8574.digitalRead(P1); // Force immediate read (bypasses buffer, always reads from device) uint8_t valImmediate = pcf8574.digitalRead(P1, true); if (val == HIGH) { Serial.println("Button pressed (HIGH)"); } else { Serial.println("Button released (LOW)"); } delay(50); // Debounce delay } ```