From fa0a78a837e0333b585c74a4f9af94bc9f3a7953 Mon Sep 17 00:00:00 2001 From: nopnop2002 Date: Mon, 9 Sep 2024 11:17:01 +0900 Subject: [PATCH] added DeveiceAddDemo --- DeviceAddDemo/CMakeLists.txt | 8 + DeviceAddDemo/README.md | 253 ++++++++++++++++++++++++++++ DeviceAddDemo/main/CMakeLists.txt | 4 + DeviceAddDemo/main/component.mk | 8 + DeviceAddDemo/main/main.c | 268 ++++++++++++++++++++++++++++++ DeviceAddDemo/sdkconfig.defaults | 18 ++ 6 files changed, 559 insertions(+) create mode 100644 DeviceAddDemo/CMakeLists.txt create mode 100644 DeviceAddDemo/README.md create mode 100644 DeviceAddDemo/main/CMakeLists.txt create mode 100644 DeviceAddDemo/main/component.mk create mode 100644 DeviceAddDemo/main/main.c create mode 100644 DeviceAddDemo/sdkconfig.defaults diff --git a/DeviceAddDemo/CMakeLists.txt b/DeviceAddDemo/CMakeLists.txt new file mode 100644 index 0000000..2aa16fe --- /dev/null +++ b/DeviceAddDemo/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ../components/ssd1306) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ssd1306) diff --git a/DeviceAddDemo/README.md b/DeviceAddDemo/README.md new file mode 100644 index 0000000..52ec743 --- /dev/null +++ b/DeviceAddDemo/README.md @@ -0,0 +1,253 @@ +# DeviceAddDemo for SSD1306 + +I received a question about using an SSD1306 and other i2c/spi devices at the same time. +A new i2c driver is now available in ESP-IDF V5.2. +This complicated the use of other i2c devices at the same time as the SSD1306. + +I will record the survey results here. +If you want to use SSD1306 and other i2c/spi devices at the same time, please follow the guide below. + +# Using i2c interface + +### Case 1 +Use multiple i2c devices on one i2c bus. +SCL and SDA are shared by all devices. +``` +I2C_NUM_0 --+-- I2C SSD1306 + +---Any I2C Device +``` + +In the XTENSA series, you can use I2C_NUM_1 bus instead of I2C_NUM_0 bus. +``` +I2C_NUM_1 --+-- I2C SSD1306 + +---Any I2C Device +``` + +- Legacy driver + +We only need to run this code once. +There is no need to memorize any data. +SSD1306 and other device use the same frequency. +Please note that the maximum i2c clock frequency of SSD1306 is 400KHz. +Under ESP-IDF V5.2 or later, this project uses the new I2C driver, but there is an option to force the use of the legacy I2C driver. + +``` + i2c_config_t i2c_config = { + .mode = I2C_MODE_MASTER, + .sda_io_num = CONFIG_SDA_GPIO, + .scl_io_num = CONFIG_SCL_GPIO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = I2C_MASTER_FREQ_HZ + }; + ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config)); + ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0)); +``` + +This project uses the following functions to install the i2c driver. +``` +i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO); +``` + +This project allows you to use an initialization function that does not install the i2c driver. +``` +i2c_device_add(&dev, i2c_num, CONFIG_RESET_GPIO); +``` + +The i2c driver must be installed before using this initialization function. +``` + // install i2c master driver + i2c_config_t i2c_config = { + .mode = I2C_MODE_MASTER, + .sda_io_num = CONFIG_SDA_GPIO, + .scl_io_num = CONFIG_SCL_GPIO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 400000 + }; + ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config)); + ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0)); + + // add new device to i2c bus + i2c_device_add(&dev, I2C_NUM_0, CONFIG_RESET_GPIO); +``` + +- New i2c driver + +We need to run this code on the first i2c device. +``` + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .i2c_port = I2C_NUM_0, + .scl_io_num = scl, + .sda_io_num = sda, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t bus_handle; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = I2C_ADDRESS1, + .scl_speed_hz = I2C_MASTER_FREQ_HZ1, + }; + i2c_master_dev_handle_t dev_handle; + ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); +``` + +We need to run this code on the second device. +SSD1306 and other device can use different frequencies. + +``` + // We need to load bus_handle from somewhere. + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = I2C_ADDRESS2, + .scl_speed_hz = I2C_MASTER_FREQ_HZ2, + }; + i2c_master_dev_handle_t dev_handle; + ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle)); +``` + +This project uses the following functions to install the i2c driver. +``` +i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO); +``` + +This project allows you to use an initialization function that does not install the i2c driver. +``` +i2c_bus_add(&dev, bus_handle, i2c_num, CONFIG_RESET_GPIO); +``` + +The i2c driver must be installed before using this initialization function. +``` + // install i2c master driver + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .i2c_port = I2C_NUM_0, + .scl_io_num = CONFIG_SCL_GPIO, + .sda_io_num = CONFIG_SDA_GPIO, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t bus_handle; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + // add new device to i2c bus + i2c_bus_add(&dev, bus_handle, I2C_NUM_0, CONFIG_RESET_GPIO); +``` + + +--- + +### Case 2 +Use multiple i2c devices on two i2c bus. +SCL and SDA each use separate GPIOs. +Install the i2c master driver for each of I2C_NUM_0 and I2C_NUM_1. +The frequencies of I2C_NUM_0 and I2C_NUM_1 can be set completely independently. +``` +I2C_NUM_0 ----- I2C SSD1306 +I2C_NUM_1 ----- Any I2C Device +``` + +This is possible with both the new i2c driver or the legacy i2c driver, but **both buses must use the same driver.** +This is not acceptable. +``` +I2C_NUM_0 ----- I2C SSD1306 using new i2c driver +I2C_NUM_1 ----- Any I2C Device using legacy i2c driver +``` + +If other i2c devices use legacy i2c drivers, SSD1306 must also use legacy i2c drivers. +Under ESP-IDF V5.2 or later, this project uses the new I2C driver, but there is an option to force the use of the legacy I2C driver. +``` +I2C_NUM_0 ----- I2C SSD1306 using legacy i2c driver +I2C_NUM_1 ----- Any I2C Device using legacy i2c driver +``` + +If SSD1306 use new i2c drivers, other i2c devices must also use new i2c drivers. +``` +I2C_NUM_0 ----- I2C SSD1306 using new i2c driver +I2C_NUM_1 ----- Any I2C Device using new i2c driver +``` + +ESP32C series has only one i2c bus. +This is not available on the ESP32C series. +Can only be used with XTENSA series. + +--- + +# Using spi interface + +### Case 1 +Use multiple spi devices on one spi bus. +MOSI and SCLK are shared by all devices. +``` +SPI2_HOST --+-- SPI SSD1306 + +---Any SPI Device +``` + +In the XTENSA series, you can use SPI2_HOST bus instead of SPI3_HOST bus. +``` +SPI3_HOST --+-- SPI SSD1306 + +---Any SPI Device +``` + +We only need to run this code once. + +``` + spi_bus_config_t spi_bus_config = { + .mosi_io_num = CONFIG_MOSI_GPIO, + .miso_io_num = -1, + .sclk_io_num = CONFIG_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 0, + .flags = 0 + }; + + ESP_LOGI(tag, "SPI HOST_ID=%d", host_id); + esp_err_t ret = spi_bus_initialize( host_id, &spi_bus_config, SPI_DMA_CH_AUTO ); + ESP_LOGI(tag, "spi_bus_initialize=%d",ret); +``` + +This project uses the following functions to install the spi driver. +``` +spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO); +``` + +This project allows you to use an initialization function that does not install the spi driver. +``` +spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO); +``` + +The spi driver must be installed before using this initialization function. +``` + // install spi master driver + spi_bus_config_t spi_bus_config = { + .mosi_io_num = CONFIG_MOSI_GPIO, + .miso_io_num = -1, + .sclk_io_num = CONFIG_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 0, + .flags = 0 + }; + + esp_err_t ret = spi_bus_initialize( SPI2_HOST, &spi_bus_config, SPI_DMA_CH_AUTO ); + ESP_LOGI(tag, "spi_bus_initialize=%d",ret); + assert(ret==ESP_OK); + + // add new device to spi bus + spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO); +``` + +### Case 2 +Use multiple spi devices on two spi bus. +MOSI and SCLK each use separate GPIOs. +Install the spi master driver for each of SPI2_HOST and SPI3_HOST. +``` +SPI2_HOST ----- SPI SSD1306 +SPI3_HOST ----- Any SPI Device +``` diff --git a/DeviceAddDemo/main/CMakeLists.txt b/DeviceAddDemo/main/CMakeLists.txt new file mode 100644 index 0000000..647a294 --- /dev/null +++ b/DeviceAddDemo/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "main.c") +set(COMPONENT_ADD_INCLUDEDIRS "") + +register_component() diff --git a/DeviceAddDemo/main/component.mk b/DeviceAddDemo/main/component.mk new file mode 100644 index 0000000..61f8990 --- /dev/null +++ b/DeviceAddDemo/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/DeviceAddDemo/main/main.c b/DeviceAddDemo/main/main.c new file mode 100644 index 0000000..88914e7 --- /dev/null +++ b/DeviceAddDemo/main/main.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#if CONFIG_LEGACY_DRIVER +#include "driver/i2c.h" +#else +#include "driver/i2c_master.h" +#endif + +#include "ssd1306.h" +#include "font8x8_basic.h" + +/* + You have to set this config value with menuconfig + CONFIG_INTERFACE + + for i2c + CONFIG_MODEL + CONFIG_SDA_GPIO + CONFIG_SCL_GPIO + CONFIG_RESET_GPIO + + for SPI + CONFIG_CS_GPIO + CONFIG_DC_GPIO + CONFIG_RESET_GPIO +*/ + +#define tag "SSD1306" + +void app_main(void) +{ + SSD1306_t dev; + int center, top, bottom; + char lineChar[20]; + +#if CONFIG_I2C_INTERFACE + ESP_LOGI(tag, "INTERFACE is i2c"); + ESP_LOGI(tag, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO); + ESP_LOGI(tag, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO); + ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO); + +#if CONFIG_I2C_PORT_0 + i2c_port_t i2c_num = I2C_NUM_0; +#else + i2c_port_t i2c_num = I2C_NUM_1; +#endif + +#if CONFIG_LEGACY_DRIVER + ESP_LOGI(tag, "I2C_LEGACY_DRIVER"); + // install i2c master driver + i2c_config_t i2c_config = { + .mode = I2C_MODE_MASTER, + .sda_io_num = CONFIG_SDA_GPIO, + .scl_io_num = CONFIG_SCL_GPIO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 400000 + }; + ESP_ERROR_CHECK(i2c_param_config(i2c_num, &i2c_config)); + ESP_ERROR_CHECK(i2c_driver_install(i2c_num, I2C_MODE_MASTER, 0, 0, 0)); + + // add new device to i2c bus + i2c_device_add(&dev, i2c_num, CONFIG_RESET_GPIO); +#else + ESP_LOGI(tag, "I2C_NEW_DRIVER"); + // install i2c master driver + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .i2c_port = i2c_num, + .scl_io_num = CONFIG_SCL_GPIO, + .sda_io_num = CONFIG_SDA_GPIO, + .flags.enable_internal_pullup = true, + }; + i2c_master_bus_handle_t bus_handle; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + // add new device to i2c bus + i2c_bus_add(&dev, bus_handle, i2c_num, CONFIG_RESET_GPIO); +#endif + +#endif // CONFIG_I2C_INTERFACE + +#if CONFIG_SPI_INTERFACE + ESP_LOGI(tag, "INTERFACE is SPI"); + ESP_LOGI(tag, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO); + ESP_LOGI(tag, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO); + ESP_LOGI(tag, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO); + ESP_LOGI(tag, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO); + ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO); + + spi_bus_config_t spi_bus_config = { + .mosi_io_num = CONFIG_MOSI_GPIO, + .miso_io_num = -1, + .sclk_io_num = CONFIG_SCLK_GPIO, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 0, + .flags = 0 + }; + +#if CONFIG_SPI2_HOST + spi_host_device_t host_id = SPI2_HOST; +#else + spi_host_device_t host_id = SPI3_HOST; +#endif + + ESP_LOGI(tag, "SPI HOST_ID=%d", host_id); + esp_err_t ret = spi_bus_initialize( host_id, &spi_bus_config, SPI_DMA_CH_AUTO ); + ESP_LOGI(tag, "spi_bus_initialize=%d",ret); + assert(ret==ESP_OK); + + spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO); +#endif // CONFIG_SPI_INTERFACE + +#if CONFIG_FLIP + dev._flip = true; + ESP_LOGW(tag, "Flip upside down"); +#endif + +#if CONFIG_SSD1306_128x64 + ESP_LOGI(tag, "Panel is 128x64"); + ssd1306_init(&dev, 128, 64); +#endif // CONFIG_SSD1306_128x64 +#if CONFIG_SSD1306_128x32 + ESP_LOGI(tag, "Panel is 128x32"); + ssd1306_init(&dev, 128, 32); +#endif // CONFIG_SSD1306_128x32 + + ssd1306_clear_screen(&dev, false); + ssd1306_contrast(&dev, 0xff); + ssd1306_display_text_x3(&dev, 0, "Hello", 5, false); + vTaskDelay(3000 / portTICK_PERIOD_MS); + +#if CONFIG_SSD1306_128x64 + top = 2; + center = 3; + bottom = 8; + ssd1306_display_text(&dev, 0, "SSD1306 128x64", 14, false); + ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false); + ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false); + ssd1306_display_text(&dev, 3, "Hello World!!", 13, false); + //ssd1306_clear_line(&dev, 4, true); + //ssd1306_clear_line(&dev, 5, true); + //ssd1306_clear_line(&dev, 6, true); + //ssd1306_clear_line(&dev, 7, true); + ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true); + ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true); + ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true); + ssd1306_display_text(&dev, 7, "Hello World!!", 13, true); +#endif // CONFIG_SSD1306_128x64 + +#if CONFIG_SSD1306_128x32 + top = 1; + center = 1; + bottom = 4; + ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false); + ssd1306_display_text(&dev, 1, "Hello World!!", 13, false); + //ssd1306_clear_line(&dev, 2, true); + //ssd1306_clear_line(&dev, 3, true); + ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true); + ssd1306_display_text(&dev, 3, "Hello World!!", 13, true); +#endif // CONFIG_SSD1306_128x32 + vTaskDelay(3000 / portTICK_PERIOD_MS); + + // Display Count Down + uint8_t image[24]; + memset(image, 0, sizeof(image)); + ssd1306_display_image(&dev, top, (6*8-1), image, sizeof(image)); + ssd1306_display_image(&dev, top+1, (6*8-1), image, sizeof(image)); + ssd1306_display_image(&dev, top+2, (6*8-1), image, sizeof(image)); + for(int font=0x39;font>0x30;font--) { + memset(image, 0, sizeof(image)); + ssd1306_display_image(&dev, top+1, (7*8-1), image, 8); + memcpy(image, font8x8_basic_tr[font], 8); + if (dev._flip) ssd1306_flip(image, 8); + ssd1306_display_image(&dev, top+1, (7*8-1), image, 8); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + + // Scroll Up + ssd1306_clear_screen(&dev, false); + ssd1306_contrast(&dev, 0xff); + ssd1306_display_text(&dev, 0, "---Scroll UP---", 16, true); + //ssd1306_software_scroll(&dev, 7, 1); + ssd1306_software_scroll(&dev, (dev._pages - 1), 1); + for (int line=0;line0;contrast=contrast-0x20) { + ssd1306_contrast(&dev, contrast); + vTaskDelay(40); + } +#endif + + // Restart module + esp_restart(); +} diff --git a/DeviceAddDemo/sdkconfig.defaults b/DeviceAddDemo/sdkconfig.defaults new file mode 100644 index 0000000..27d6f75 --- /dev/null +++ b/DeviceAddDemo/sdkconfig.defaults @@ -0,0 +1,18 @@ +# +# ESP32-specific +# +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 + +# +# ESP32S2-specific +# +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=240 + +# +# ESP32S3-specific +# +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +