Smart Home Automation Forum
[ESP-IDF code examples for A32 Pro]-02 Read digital input ports state - Printable Version

+- Smart Home Automation Forum (https://www.kincony.com/forum)
+-- Forum: Technical Support (https://www.kincony.com/forum/forumdisplay.php?fid=20)
+--- Forum: KC868-A32/A32 Pro (https://www.kincony.com/forum/forumdisplay.php?fid=27)
+--- Thread: [ESP-IDF code examples for A32 Pro]-02 Read digital input ports state (/showthread.php?tid=6692)



[ESP-IDF code examples for A32 Pro]-02 Read digital input ports state - admin - 09-14-2024

Code:
/*
* Made by KinCony IoT: https://www.kincony.com
*
* This program reads inputs from two XL9535 I/O expander chips (I2C addresses 0x24 and 0x25)
* and one PCF8574 I/O expander (I2C address 0x23) via I2C using an ESP32-S3.
* The state of all inputs is printed in binary format to the serial monitor every second.
*
* - The XL9535 chips read inputs from channels 1-32.
* - The PCF8574 chip reads inputs from channels 33-40.
*
* I2C is initialized on GPIO 11 (SDA) and GPIO 10 (SCL) with a frequency of 40kHz.
*/

#include <stdio.h>
#include "driver/i2c.h"
#include "esp_log.h"

// I2C communication settings
#define I2C_MASTER_SCL_IO           10    // GPIO number for I2C clock line (SCL)
#define I2C_MASTER_SDA_IO           11    // GPIO number for I2C data line (SDA)
#define I2C_MASTER_FREQ_HZ          40000  // I2C frequency set to 40kHz
#define I2C_MASTER_PORT             I2C_NUM_0  // I2C port number used in this program

// I2C addresses for XL9535 chips and PCF8574
#define XL9535_ADDR_1               0x24  // Address for XL9535 (channels 1-16)
#define XL9535_ADDR_2               0x25  // Address for XL9535 (channels 17-32)
#define PCF8574_ADDR                0x23  // Address for PCF8574 (channels 33-40)

// XL9535 registers for input ports
#define XL9535_INPUT_PORT_0         0x00  // Input register for port 0 (channels 1-8)
#define XL9535_INPUT_PORT_1         0x01  // Input register for port 1 (channels 9-16)

// Function prototypes
esp_err_t i2c_master_init();
esp_err_t xl9535_read_inputs(uint8_t device_addr, uint8_t *data);
esp_err_t pcf8574_read_inputs(uint8_t *data);
void read_and_print_inputs();

void app_main() {
    // Initialize I2C master
    ESP_ERROR_CHECK(i2c_master_init());

    // Main loop to read and print input states every second
    while (1) {
        read_and_print_inputs();
        vTaskDelay(1000 / portTICK_PERIOD_MS);  // Wait for 1 second
    }
}

// Initialize I2C master interface
esp_err_t i2c_master_init() {
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,  // Set I2C mode to master
        .sda_io_num = I2C_MASTER_SDA_IO,  // SDA GPIO pin
        .scl_io_num = I2C_MASTER_SCL_IO,  // SCL GPIO pin
        .sda_pullup_en = GPIO_PULLUP_ENABLE,  // Enable internal pull-up for SDA line
        .scl_pullup_en = GPIO_PULLUP_ENABLE,  // Enable internal pull-up for SCL line
        .master.clk_speed = I2C_MASTER_FREQ_HZ,  // Set I2C clock frequency to 40kHz
    };
    i2c_param_config(I2C_MASTER_PORT, &conf);
    return i2c_driver_install(I2C_MASTER_PORT, conf.mode, 0, 0, 0);
}

// Read inputs from XL9535 I/O expander
esp_err_t xl9535_read_inputs(uint8_t device_addr, uint8_t *data) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(cmd, XL9535_INPUT_PORT_0, true);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (device_addr << 1) | I2C_MASTER_READ, true);
    i2c_master_read_byte(cmd, &data[0], I2C_MASTER_ACK);  // Read port 0 (channels 1-8 or 17-24)
    i2c_master_read_byte(cmd, &data[1], I2C_MASTER_NACK); // Read port 1 (channels 9-16 or 25-32)
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_PORT, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

// Read inputs from PCF8574 I/O expander
esp_err_t pcf8574_read_inputs(uint8_t *data) {
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (PCF8574_ADDR << 1) | I2C_MASTER_READ, true);
    i2c_master_read_byte(cmd, data, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_PORT, cmd, 1000 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

// Function to read and print the state of inputs from XL9535 and PCF8574 chips
void read_and_print_inputs() {
    uint8_t xl9535_data_1[2];  // Data buffer for XL9535 (channels 1-16)
    uint8_t xl9535_data_2[2];  // Data buffer for XL9535 (channels 17-32)
    uint8_t pcf8574_data;      // Data buffer for PCF8574 (channels 33-40)

    // Read inputs from the first XL9535 (channels 1-16)
    if (xl9535_read_inputs(XL9535_ADDR_1, xl9535_data_1) == ESP_OK) {
        printf("1-16 input states: %02X%02X\n", xl9535_data_1[1], xl9535_data_1[0]);  // Print in binary
    } else {
        printf("Error reading from XL9535 (channels 1-16)\n");
    }

    // Read inputs from the second XL9535 (channels 17-32)
    if (xl9535_read_inputs(XL9535_ADDR_2, xl9535_data_2) == ESP_OK) {
        printf("17-32 input states: %02X%02X\n", xl9535_data_2[1], xl9535_data_2[0]);  // Print in binary
    } else {
        printf("Error reading from XL9535 (channels 17-32)\n");
    }

    // Read inputs from the PCF8574 (channels 33-40)
    if (pcf8574_read_inputs(&pcf8574_data) == ESP_OK) {
        printf("33-40 input states: %02X\n", pcf8574_data);  // Print in binary
    } else {
        printf("Error reading from PCF8574 (channels 33-40)\n");
    }
}