diff --git a/README.md b/README.md index 9812cff..a04d362 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # ESP32 ESP-IDF component for liquid crystal display module 1602(4)A via I2C connection (PCF8574(A)) +## Wiki + +[EN](WIKI_EN.md) | [RU](WIKI_RU.md) + ## Tested on 1. [ESP32 ESP-IDF v6.0.0](https://docs.espressif.com/projects/esp-idf/en/v6.0/esp32/index.html) @@ -36,8 +40,7 @@ CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM ## Dependencies -1. [zh_vector](https://github.com/aZholtikov/zh_vector) -2. [zh_pcf8574](https://github.com/aZholtikov/zh_pcf8574) +1. [zh_pcf8574](https://github.com/aZholtikov/zh_pcf8574) ## Using @@ -46,8 +49,6 @@ In an existing project, run the following command to install the components: ```text cd ../your_project/components git clone https://github.com/aZholtikov/zh_160x_i2c -git clone https://github.com/aZholtikov/zh_pcf8574 -git clone https://github.com/aZholtikov/zh_vector ``` In the application, add the component: diff --git a/WIKI_EN.md b/WIKI_EN.md new file mode 100644 index 0000000..0560f0a --- /dev/null +++ b/WIKI_EN.md @@ -0,0 +1,500 @@ +# zh_160x_i2c - ESP32 ESP-IDF Component for LCD 1602A/1604A via I2C (PCF8574) + +## Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [Installation](#installation) +- [API Reference](#api-reference) +- [Usage Examples](#usage-examples) +- [Technical Specifications](#technical-specifications) +- [Error Codes](#error-codes) +- [Connection](#connection) +- [Contributing](#contributing) +- [License](#license) + +--- + +## Overview + +`zh_160x_i2c` is a lightweight ESP-IDF component for controlling LCD 1602A and 1604A displays via I2C interface using PCF8574(A) I/O expanders. This component simplifies the process of displaying text, numbers, and progress bars on character LCD modules by providing a simple and intuitive API. + +The component is designed specifically for ESP32 microcontrollers and uses ESP-IDF's I2C master driver and FreeRTOS for optimal performance in embedded systems. + +--- + +## Features + +1. **Simple API**: Easy-to-use functions for common LCD operations +2. **I2C Interface**: Uses only 2 GPIO pins (SCL and SDA) via PCF8574 expander +3. **Support for 1602A and 1604A**: Supports both 16x2 and 16x4 LCD modules +4. **Multiple LCD Support**: Up to 8 LCD modules on one I2C bus (PCF8574) or 4 (PCF8574A) +5. **Text Display**: Print strings, integers, and floating-point numbers +6. **Cursor Control**: Enable/disable cursor with optional blink +7. **Progress Bar**: Display progress bars on LCD +8. **Row Operations**: Clear specific rows +9. **ESP-IDF Optimized**: Uses ESP-IDF's I2C master driver and FreeRTOS + +--- + +## Installation + +1. Navigate to your project's components directory: + +```bash +cd ../your_project/components +``` + +2. Clone the repository: + +```bash +git clone https://github.com/aZholtikov/zh_160x_i2c +``` + +3. In your application, include the header: + +```c +#include "zh_160x_i2c.h" +``` + +4. The component will be automatically built with your project. + +### Required menuconfig Settings + +For correct operation, enable the following settings in menuconfig: + +```text +CONFIG_FREERTOS_HZ=1000 +CONFIG_I2C_ISR_IRAM_SAFE +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM +``` + +--- + +## API Reference + +### Configuration Constants + +```c +#define ZH_LCD_16X2 1 // LCD size 16x2 +#define ZH_LCD_16X4 0 // LCD size 16x4 +``` + +--- + +### zh_160x_init() + +Initializes the LCD 160X module. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle (must be already initialized) +- `size` - LCD size (ZH_LCD_16X2 or ZH_LCD_16X4) + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or handle not initialized) +- `ESP_FAIL` - Initialization failed + +**Example:** + +```c +zh_pcf8574_handle_t lcd_handle = {0}; +// Initialize PCF8574 first +zh_pcf8574_init(&config, &lcd_handle); +// Then initialize LCD +zh_160x_init(&lcd_handle, ZH_LCD_16X2); +``` + +--- + +### zh_160x_lcd_clear() + +Clears the entire LCD screen. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_set_cursor() + +Sets the cursor to a specific position on the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `row` - Row number (0-1 for 16x2, 0-3 for 16x4) +- `col` - Column number (0-15) + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, invalid row/col) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_print_char() + +Prints a string to the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `str` - Pointer to the null-terminated string to display + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or str) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_print_int() + +Prints an integer to the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `num` - Integer value to display + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_print_float() + +Prints a floating-point number to the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `num` - Floating-point value to display +- `precision` - Number of decimal places (0-9) + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_print_progress_bar() + +Displays a progress bar on a specific row of the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `row` - Row number (0-1 for 16x2, 0-3 for 16x4) +- `progress` - Progress percentage (0-100) + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, invalid row or progress) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_clear_row() + +Clears a specific row on the LCD. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `row` - Row number (0-1 for 16x2, 0-3 for 16x4) + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle, invalid row) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_on_cursor() + +Enables the cursor with optional blink mode. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle +- `blink` - If true, cursor blinks; if false, cursor is steady + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle) +- `ESP_FAIL` - Operation failed + +--- + +### zh_160x_off_cursor() + +Disables the cursor. + +**Parameters:** + +- `handle` - Pointer to unique PCF8574 handle + +**Returns:** + +- `ESP_OK` - Success +- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle) +- `ESP_FAIL` - Operation failed + +--- + +## Usage Examples + +### Basic Example: Single LCD Display + +```c +#include "zh_160x_i2c.h" + +#define I2C_PORT (I2C_NUM_MAX - 1) + +zh_pcf8574_handle_t lcd_160x_handle = {0}; + +void app_main(void) +{ + esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR); + esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR); + esp_log_level_set("zh_vector", ESP_LOG_ERROR); + i2c_master_bus_config_t i2c_bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = I2C_PORT, + .scl_io_num = GPIO_NUM_22, + .sda_io_num = GPIO_NUM_21, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + + i2c_master_bus_handle_t i2c_bus_handle = NULL; + i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle); + zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT(); + config.i2c_handle = i2c_bus_handle; + config.i2c_address = 0x27; + zh_pcf8574_init(&config, &lcd_160x_handle); + zh_160x_init(&lcd_160x_handle, ZH_LCD_16X2); + // Display text + zh_160x_set_cursor(&lcd_160x_handle, 0, 0); + zh_160x_print_char(&lcd_160x_handle, "LCD 160X"); + zh_160x_set_cursor(&lcd_160x_handle, 1, 0); + zh_160x_print_char(&lcd_160x_handle, "Hello World!"); +} +``` + +### Example: Progress Bar + +```c +#include "zh_160x_i2c.h" + +void app_main(void) +{ + zh_pcf8574_handle_t lcd_handle = {0}; + // ... initialization code ... + for (uint8_t i = 0; i <= 100; ++i) + { + zh_160x_set_cursor(&lcd_handle, 0, 10); + zh_160x_print_int(&lcd_handle, i); + zh_160x_print_char(&lcd_handle, "%"); + zh_160x_print_progress_bar(&lcd_handle, 1, i); + vTaskDelay(100 / portTICK_PERIOD_MS); + } +} +``` + +### Example: Displaying Various Data Types + +```c +#include "zh_160x_i2c.h" + +void app_main(void) +{ + zh_pcf8574_handle_t lcd_handle = {0}; + // ... initialization code ... + // Display string + zh_160x_set_cursor(&lcd_handle, 0, 0); + zh_160x_print_char(&lcd_handle, "String: "); + zh_160x_print_char(&lcd_handle, "Hello"); + // Display integer + zh_160x_set_cursor(&lcd_handle, 1, 0); + zh_160x_print_int(&lcd_handle, 42); + // Display floating-point number + zh_160x_set_cursor(&lcd_handle, 0, 0); + zh_160x_print_float(&lcd_handle, 3.14159, 2); // 3.14 + // Enable cursor + zh_160x_on_cursor(&lcd_handle, true); // Blinking cursor + vTaskDelay(2000 / portTICK_PERIOD_MS); + // Disable cursor + zh_160x_off_cursor(&lcd_handle); +} +``` + +### Example: Multiple LCDs on One Bus + +```c +#include "zh_160x_i2c.h" + +#define I2C_PORT (I2C_NUM_MAX - 1) + +zh_pcf8574_handle_t lcd1_handle = {0}; +zh_pcf8574_handle_t lcd2_handle = {0}; + +void app_main(void) +{ + esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR); + esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR); + esp_log_level_set("zh_vector", ESP_LOG_ERROR); + i2c_master_bus_config_t i2c_bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = I2C_PORT, + .scl_io_num = GPIO_NUM_22, + .sda_io_num = GPIO_NUM_21, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t i2c_bus_handle = NULL; + i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle); + // Initialize first LCD at address 0x27 + zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT(); + config.i2c_handle = i2c_bus_handle; + config.i2c_address = 0x27; + zh_pcf8574_init(&config, &lcd1_handle); + zh_160x_init(&lcd1_handle, ZH_LCD_16X2); + // Initialize second LCD at address 0x26 + config.i2c_address = 0x26; + zh_pcf8574_init(&config, &lcd2_handle); + zh_160x_init(&lcd2_handle, ZH_LCD_16X2); + // Display on first LCD + zh_160x_set_cursor(&lcd1_handle, 0, 0); + zh_160x_print_char(&lcd1_handle, "LCD 1"); + // Display on second LCD + zh_160x_set_cursor(&lcd2_handle, 0, 0); + zh_160x_print_char(&lcd2_handle, "LCD 2"); +} +``` + +--- + +## Technical Specifications + +| Parameter | Value | +|-----------|-------| +| **LCD Types** | 1602A (16x2), 1604A (16x4) | +| **Interface** | I2C via PCF8574(A) | +| **I2C Address Range** | 0x20-0x27 (PCF8574), 0x38-0x3F (PCF8574A) | +| **Max LCDs per Bus** | 16 | +| **GPIO Usage** | 2 (SCL, SDA) | +| **ESP-IDF Version** | >= 5.0| +| **Platform** | ESP32 family | +| **Language** | C (C99) | + +--- + +## Error Codes + +| Error Code | Description | +|------------|-------------| +| `ESP_OK` | Operation completed successfully | +| `ESP_ERR_INVALID_ARG` | Invalid argument (NULL pointer or invalid value) | +| `ESP_ERR_INVALID_STATE` | Handle not initialized | +| `ESP_FAIL` | General failure (I2C communication error) | + +--- + +## Connection + +### 1602A/1604A to PCF8574 Connection + +| LCD Pin | PCF8574 Pin | Description | +|---------|-------------|-------------| +| RS | P0 | Register select | +| E | P2 | Enable | +| D4 | P4 | Data bit 4 | +| D5 | P5 | Data bit 5 | +| D6 | P6 | Data bit 6 | +| D7 | P7 | Data bit 7 | + +### I2C Connection + +| LCD Module | PCF8574 | ESP32 | +|------------|---------|-------| +| VCC | VCC | 3.3V | +| GND | GND | GND | +| SDA | SDA | GPIO21 | +| SCL | SCL | GPIO22 | +| RW | GND | GND | + +**Note:** RW pin must be connected to GND for write-only operation. + +--- + +## Contributing + +Contributions are welcome! To contribute: + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/AmazingFeature`) +3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + +Please ensure your code follows the existing style and includes appropriate documentation. + +--- + +## License + +This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file for details. + +### Apache License, Version 2.0 + +Copyright (c) 2026 Alexey Zholtikov + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +--- + +## Additional Notes + +- **I2C Pull-up Resistors**: Use 4.7kΩ resistors on SDA and SCL lines for reliable communication +- **Power Supply**: Ensure stable 5V power for LCD module (PCF8574 is 5V tolerant) +- **Contrast Adjustment**: Use the built-in potentiometer to adjust LCD contrast for optimal visibility +- **Backlight**: LCD backlight is typically connected to VCC through a current-limiting resistor +- **Performance**: Operations are blocking and use FreeRTOS delays for proper timing +- **I2C_ISR_IRAM_SAFE**: For proper operation, enable `I2C_ISR_IRAM_SAFE` and `I2C_MASTER_ISR_HANDLER_IN_IRAM` in menuconfig +- **FreeRTOS**: For correct operation, configure `CONFIG_FREERTOS_HZ=1000` in menuconfig +- **Best Practices**: + - Always initialize PCF8574 before initializing LCD + - Check I2C address using a scanner if LCD does not respond + - Consider I2C bus speed limitations when using multiple devices diff --git a/WIKI_RU.md b/WIKI_RU.md new file mode 100644 index 0000000..b323a11 --- /dev/null +++ b/WIKI_RU.md @@ -0,0 +1,500 @@ +# zh_160x_i2c - Компонент ESP32 ESP-IDF для LCD 1602A/1604A через I2C (PCF8574) + +## Содержание + +- [Обзор](#обзор) +- [Возможности](#возможности) +- [Установка](#установка) +- [Справочник API](#справочник-api) +- [Примеры использования](#примеры-использования) +- [Технические характеристики](#технические-характеристики) +- [Коды ошибок](#коды-ошибок) +- [Подключение](#подключение) +- [Вклад в проект](#вклад-в-проект) +- [Лицензия](#лицензия) + +--- + +## Обзор + +`zh_160x_i2c` — это легковесный компонент ESP-IDF для управления LCD-дисплеями 1602A и 1604A через интерфейс I2C с использованием расширителей ввода-вывода PCF8574(A). Этот компонент упрощает процесс отображения текста, чисел и индикаторов прогресса на символьных LCD-модулях, предоставляя простой и интуитивно понятный API. + +Компонент разработан специально для микроконтроллеров ESP32 и использует драйвер I2C-мастера ESP-IDF и FreeRTOS для оптимальной производительности во встраиваемых системах. + +--- + +## Возможности + +1. **Простой API**: Удобные функции для распространенных операций с LCD +2. **Интерфейс I2C**: Использует только 2 GPIO-пина (SCL и SDA) через расширитель PCF8574 +3. **Поддержка 1602A и 1604A**: Поддерживает LCD-модули 16x2 и 16x4 +4. **Множественные LCD**: До 16 LCD-модулей на одной шине I2C +5. **Отображение текста**: Вывод строк, целых чисел и чисел с плавающей точкой +6. **Управление курсором**: Включение/выключение курсора с опциональным миганием +7. **Индикатор прогресса**: Отображение индикаторов прогресса на LCD +8. **Операции со строками**: Очистка конкретных строк +9. **Оптимизировано под ESP-IDF**: Использует драйвер I2C-мастера ESP-IDF и FreeRTOS + +--- + +## Установка + +1. Перейдите в каталог компонентов вашего проекта: + +```bash +cd ../ваш_проект/components +``` + +2. Клонируйте репозиторий: + +```bash +git clone https://github.com/aZholtikov/zh_160x_i2c +``` + +3. В вашем приложении подключите заголовочный файл: + +```c +#include "zh_160x_i2c.h" +``` + +4. Компонент будет автоматически собран вместе с вашим проектом. + +### Обязательные настройки в menuconfig + +Для корректной работы компонента включите следующие настройки в menuconfig: + +```text +CONFIG_FREERTOS_HZ=1000 +CONFIG_I2C_ISR_IRAM_SAFE +CONFIG_I2C_MASTER_ISR_HANDLER_IN_IRAM +``` + +--- + +## Справочник API + +### Константы конфигурации + +```c +#define ZH_LCD_16X2 1 // Размер LCD 16x2 +#define ZH_LCD_16X4 0 // Размер LCD 16x4 +``` + +--- + +### zh_160x_init() + +Инициализирует модуль LCD 160X. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 (должен быть уже инициализирован) +- `size` - Размер LCD (ZH_LCD_16X2 или ZH_LCD_16X4) + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или handle не инициализирован) +- `ESP_FAIL` - Ошибка инициализации + +**Пример:** + +```c +zh_pcf8574_handle_t lcd_handle = {0}; +// Сначала инициализируйте PCF8574 +zh_pcf8574_init(&config, &lcd_handle); +// Затем инициализируйте LCD +zh_160x_init(&lcd_handle, ZH_LCD_16X2); +``` + +--- + +### zh_160x_lcd_clear() + +Очищает весь экран LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_set_cursor() + +Устанавливает курсор в определенную позицию на LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4) +- `col` - Номер столбца (0-15) + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row/col) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_print_char() + +Выводит строку на LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `str` - Указатель на null-terminated строку для отображения + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или str) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_print_int() + +Выводит целое число на LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `num` - Целочисленное значение для отображения + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_print_float() + +Выводит число с плавающей точкой на LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `num` - Значение с плавающей точкой для отображения +- `precision` - Количество знаков после запятой (0-9) + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_print_progress_bar() + +Отображает индикатор прогресса в определенной строке LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4) +- `progress` - Процент прогресса (0-100) + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row или progress) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_clear_row() + +Очищает определенную строку на LCD. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `row` - Номер строки (0-1 для 16x2, 0-3 для 16x4) + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle, неверный row) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_on_cursor() + +Включает курсор с опциональным режимом мигания. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 +- `blink` - Если true, курсор мигает; если false, курсор статичный + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle) +- `ESP_FAIL` - Операция не удалась + +--- + +### zh_160x_off_cursor() + +Отключает курсор. + +**Параметры:** + +- `handle` - Указатель на уникальный дескриптор PCF8574 + +**Возвращает:** + +- `ESP_OK` - Успех +- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle) +- `ESP_FAIL` - Операция не удалась + +--- + +## Примеры использования + +### Базовый пример: Одиночный LCD-дисплей + +```c +#include "zh_160x_i2c.h" + +#define I2C_PORT (I2C_NUM_MAX - 1) + +zh_pcf8574_handle_t lcd_160x_handle = {0}; + +void app_main(void) +{ + esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR); + esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR); + esp_log_level_set("zh_vector", ESP_LOG_ERROR); + i2c_master_bus_config_t i2c_bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = I2C_PORT, + .scl_io_num = GPIO_NUM_22, + .sda_io_num = GPIO_NUM_21, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + + i2c_master_bus_handle_t i2c_bus_handle = NULL; + i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle); + zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT(); + config.i2c_handle = i2c_bus_handle; + config.i2c_address = 0x27; + zh_pcf8574_init(&config, &lcd_160x_handle); + zh_160x_init(&lcd_160x_handle, ZH_LCD_16X2); + // Отображение текста + zh_160x_set_cursor(&lcd_160x_handle, 0, 0); + zh_160x_print_char(&lcd_160x_handle, "LCD 160X"); + zh_160x_set_cursor(&lcd_160x_handle, 1, 0); + zh_160x_print_char(&lcd_160x_handle, "Привет Мир!"); +} +``` + +### Пример: Индикатор прогресса + +```c +#include "zh_160x_i2c.h" + +void app_main(void) +{ + zh_pcf8574_handle_t lcd_handle = {0}; + // ... код инициализации ... + for (uint8_t i = 0; i <= 100; ++i) + { + zh_160x_set_cursor(&lcd_handle, 0, 10); + zh_160x_print_int(&lcd_handle, i); + zh_160x_print_char(&lcd_handle, "%"); + zh_160x_print_progress_bar(&lcd_handle, 1, i); + vTaskDelay(100 / portTICK_PERIOD_MS); + } +} +``` + +### Пример: Отображение различных типов данных + +```c +#include "zh_160x_i2c.h" + +void app_main(void) +{ + zh_pcf8574_handle_t lcd_handle = {0}; + // ... код инициализации ... + // Отображение строки + zh_160x_set_cursor(&lcd_handle, 0, 0); + zh_160x_print_char(&lcd_handle, "Строка: "); + zh_160x_print_char(&lcd_handle, "Привет"); + // Отображение целого числа + zh_160x_set_cursor(&lcd_handle, 1, 0); + zh_160x_print_int(&lcd_handle, 42); + // Отображение числа с плавающей точкой + zh_160x_set_cursor(&lcd_handle, 0, 0); + zh_160x_print_float(&lcd_handle, 3.14159, 2); // 3.14 + // Включение курсора + zh_160x_on_cursor(&lcd_handle, true); // Мигающий курсор + vTaskDelay(2000 / portTICK_PERIOD_MS); + // Отключение курсора + zh_160x_off_cursor(&lcd_handle); +} +``` + +### Пример: Несколько LCD на одной шине + +```c +#include "zh_160x_i2c.h" + +#define I2C_PORT (I2C_NUM_MAX - 1) + +zh_pcf8574_handle_t lcd1_handle = {0}; +zh_pcf8574_handle_t lcd2_handle = {0}; + +void app_main(void) +{ + esp_log_level_set("zh_160x_i2c", ESP_LOG_ERROR); + esp_log_level_set("zh_pcf8574", ESP_LOG_ERROR); + esp_log_level_set("zh_vector", ESP_LOG_ERROR); + i2c_master_bus_config_t i2c_bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = I2C_PORT, + .scl_io_num = GPIO_NUM_22, + .sda_io_num = GPIO_NUM_21, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t i2c_bus_handle = NULL; + i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle); + // Инициализация первого LCD по адресу 0x27 + zh_pcf8574_init_config_t config = ZH_PCF8574_INIT_CONFIG_DEFAULT(); + config.i2c_handle = i2c_bus_handle; + config.i2c_address = 0x27; + zh_pcf8574_init(&config, &lcd1_handle); + zh_160x_init(&lcd1_handle, ZH_LCD_16X2); + // Инициализация второго LCD по адресу 0x26 + config.i2c_address = 0x26; + zh_pcf8574_init(&config, &lcd2_handle); + zh_160x_init(&lcd2_handle, ZH_LCD_16X2); + // Отображение на первом LCD + zh_160x_set_cursor(&lcd1_handle, 0, 0); + zh_160x_print_char(&lcd1_handle, "LCD 1"); + // Отображение на втором LCD + zh_160x_set_cursor(&lcd2_handle, 0, 0); + zh_160x_print_char(&lcd2_handle, "LCD 2"); +} +``` + +--- + +## Технические характеристики + +| Параметр | Значение | +|----------|----------| +| **Типы LCD** | 1602A (16x2), 1604A (16x4) | +| **Интерфейс** | I2C через PCF8574(A) | +| **Диапазон адресов I2C** | 0x20-0x27 (PCF8574), 0x38-0x3F (PCF8574A) | +| **Макс. LCD на шине** | 16 | +| **Использование GPIO** | 2 (SCL, SDA) | +| **Версия ESP-IDF** | >= 5.0 | +| **Платформа** | Семейство ESP32 | +| **Язык** | C (C99) | + +--- + +## Коды ошибок + +| Код ошибки | Описание | +|------------|----------| +| `ESP_OK` | Операция выполнена успешно | +| `ESP_ERR_INVALID_ARG` | Неверный аргумент (NULL указатель или неверное значение) | +| `ESP_ERR_INVALID_STATE` | Дескриптор не инициализирован | +| `ESP_FAIL` | Общий сбой (ошибка связи I2C) | + +--- + +## Подключение + +### Подключение 1602A/1604A к PCF8574 + +| Пин LCD | Пин PCF8574 | Описание | +|---------|-------------|----------| +| RS | P0 | Выбор регистра | +| E | P2 | Enable | +| D4 | P4 | Бит данных 4 | +| D5 | P5 | Бит данных 5 | +| D6 | P6 | Бит данных 6 | +| D7 | P7 | Бит данных 7 | + +### Подключение I2C + +| LCD-модуль | PCF8574 | ESP32 | +|------------|---------|-------| +| VCC | VCC | 3.3V | +| GND | GND | GND | +| SDA | SDA | GPIO21 | +| SCL | SCL | GPIO22 | +| RW | GND | GND | + +**Примечание:** Пин RW должен быть подключен к GND для операции только записи. + +--- + +## Вклад в проект + +Вклад приветствуется! Чтобы внести свой вклад: + +1. Сделайте форк репозитория +2. Создайте ветку функции (`git checkout -b feature/AmazingFeature`) +3. Закоммитьте ваши изменения (`git commit -m 'Add some AmazingFeature'`) +4. Отправьте в ветку (`git push origin feature/AmazingFeature`) +5. Откройте Pull Request + +Пожалуйста, убедитесь, что ваш код следует существующему стилю и включает соответствующую документацию. + +--- + +## Лицензия + +Этот проект лицензирован по лицензии Apache, версия 2.0 - см. файл [LICENSE](LICENSE) для подробной информации. + +### Apache License, Version 2.0 + +Авторское право (c) 2026 Алексей Жолтиков + +Лицензировано по лицензии Apache License, Version 2.0 (далее — "Лицензия"); +вы не можете использовать этот файл, кроме случаев, предусмотренных Лицензией. +Копию Лицензии можно получить по адресу: + + http://www.apache.org/licenses/LICENSE-2.0 + +Если иное не требуется действующим законодательством или не согласовано в письменном виде, +программное обеспечение, распространяемое по Лицензии, распространяется на условиях "КАК ЕСТЬ", +БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, явных или подразумеваемых, включая, но не ограничиваясь, гарантии +ТОВАРНОГО СОСТОЯНИЯ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. +Смотрите Лицензию для получения конкретных прав и ограничений. + +--- + +## Дополнительные заметки + +- **Подтягивающие резисторы I2C**: Используйте резисторы 4.7 кОм на линиях SDA и SCL для надежной связи +- **Питание**: Обеспечьте стабильное питание 5 В для LCD-модуля (PCF8574 совместим с 5 В) +- **Настройка контраста**: Используйте встроенный подстроечный резистор для настройки контраста LCD для оптимальной видимости +- **Подсветка**: Подсветка LCD обычно подключается к VCC через резистор ограничения тока +- **Производительность**: Операции блокирующие и используют задержки FreeRTOS для правильного тайминга +- **I2C_ISR_IRAM_SAFE**: Для правильной работы включите `I2C_ISR_IRAM_SAFE` и `I2C_MASTER_ISR_HANDLER_IN_IRAM` в menuconfig +- **FreeRTOS**: Для корректной работы настройте `CONFIG_FREERTOS_HZ=1000` в menuconfig +- **Лучшие практики**: + - Всегда инициализируйте PCF8574 перед инициализацией LCD + - Проверьте адрес I2C с помощью сканера, если LCD не отвечает + - Учитывайте ограничения скорости шины I2C при использовании нескольких устройств