Skip to content

Will this work with RTC? #29

Open
Open
@hsnprojects

Description

DS3231 in the following repository is using a different strategy to initialize i2c bus.
https://github.com/nopnop2002/esp-idf-ds3231

We can't initialize i2c bus twice, am I right?
Do we need to configure anything differently to use the OLED display along with RTC?

Thank you for these libraries that saved me a ton of time!

Activity

nopnop2002

nopnop2002 commented on Sep 6, 2024

@nopnop2002
Owner

We can't initialize i2c bus twice, am I right?

xtensa's ESP32 has two i2c buses.
It is necessary to initialize each i2c bus.

	i2c_config_t i2c_config_0 = {
		.mode = I2C_MODE_MASTER,
		.sda_io_num = GPIO4,
		.scl_io_num = GPIO5,
		.sda_pullup_en = GPIO_PULLUP_ENABLE,
		.scl_pullup_en = GPIO_PULLUP_ENABLE,
		.master.clk_speed = 1000000
	};
	ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config_0));
	ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));

	i2c_config_t i2c_config_1 = {
		.mode = I2C_MODE_MASTER,
		.sda_io_num = GPIO21,
		.scl_io_num = GPIO22,
		.sda_pullup_en = GPIO_PULLUP_ENABLE,
		.scl_pullup_en = GPIO_PULLUP_ENABLE,
		.master.clk_speed = 4000000
	};
	ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_1, &i2c_config_1));
	ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_1, I2C_MODE_MASTER, 0, 0, 0));

esp-idf-ds3231 always uses I2C_NUM_0.

You can select either I2C_NUM_0/1 for this repository.
config-i2c-port

hsnprojects

hsnprojects commented on Sep 6, 2024

@hsnprojects
Author

Thanks for taking the time to reply to my message.

Do we still need to include i2cdev from DS3231? It has its own i2c_master_init() function, which conflicts with the one from SSD1306. I noticed that ESP-IDF itself has a different I2C bus initialization function (i2c_new_master_bus(&bus_config, &i2c_bus)).

Can all three of these co-exist?

nopnop2002

nopnop2002 commented on Sep 6, 2024

@nopnop2002
Owner

It has its own i2c_master_init() function, which conflicts with the one from SSD1306.

Yes, you are correct.

$ cd esp-idf-ssd1306

$ cp -r components/ $HOME/esp-idf-ds3231

$ cd $HOME/esp-idf-ds3231/components/ssd1306
$ vi ssd1306.h
#change from i2c_master_init to i2c_master_init_ssd1306

$ vi ssd1306_i2c_legacy.c
#change from i2c_master_init to i2c_master_init_ssd1306

$ vi ssd1306_i2c_new.c
#change from i2c_master_init to i2c_master_init_ssd1306

$ grep -rn i2c_master_init *
ssd1306.h:142:void i2c_master_init_ssd1306(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset);
ssd1306_i2c_legacy.c:24:void i2c_master_init_ssd1306(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset)
ssd1306_i2c_new.c:26:void i2c_master_init_ssd1306(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset)

$ cd ../..

$ cd main

$ vi main.c
# add this to end of code
    SSD1306_t dev;

#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);
    i2c_master_init_ssd1306(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE

    ssd1306_clear_screen(&dev, false);
    ssd1306_contrast(&dev, 0xff);
    ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
    vTaskDelay(3000 / portTICK_PERIOD_MS);

$ rm -r build

$ rm sdkconfig

$ idf.py menuconfig

config-0
config-1

change gpio and i2c bus using menuconfig

config-2

The build will now pass.

$ idf.py build


Project build complete. To flash, run:
 idf.py flash
or
 idf.py -p PORT flash
or
 python -m esptool --chip esp32 -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size 2MB --flash_freq 40m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/ds3231.bin
or from the "/home/nop/rtos/esp-idf-ds3231-test/build" directory
 python -m esptool --chip esp32 -b 460800 --before default_reset --after hard_reset write_flash "@flash_args"
hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

Fantastic! That resolved my original issue.

But I am still unable to include protocol_examples_common.h properly. I am very new to the CMake build system.

Following is what I have in my project root folder's CMakeLists.txt:
Could you take a look at this to see if you notice anything glaring?

cmake_minimum_required(VERSION 3.5)

set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ./components/ssd1306)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ds3231)

nopnop2002

nopnop2002 commented on Sep 7, 2024

@nopnop2002
Owner

This is my CMakeLists.txt

# 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)

# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ds3231)

The components directory is linked unconditionally.

hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

Here is the latest error:
E (558) i2c: CONFLICT! driver_ng is not allowed to be used with this old driver

But it looks like we are using ssd1306_i2c_new.c

hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

By the way, I have another similar board working with these components, but I am forcing it to use the legacy driver, and it works fine with esp-idf v5.3.

nopnop2002

nopnop2002 commented on Sep 7, 2024

@nopnop2002
Owner

I am forcing it to use the legacy driver

Yes.
Added forced legacy i2c driver mode to latest version of SSD1306.


$ cd $HOME

$ git clone https://github.com/nopnop2002/esp-idf-ssd1306

$ cd $HOME/esp-idf-ssd1306/components/ssd1306

$ cp CMakeLists.txt $HOME/esp-idf-ds3231/components/ssd1306/

$ cp Kconfig.projbuild $HOME/esp-idf-ds3231/components/ssd1306/

$ cd $HOME/esp-idf-ds3231

$ rm -r build

$ rm sdkconfig

$ idf.py menuconfig

config-i2c-driver


Please specify the GPIO number of SSD1306 directly.
CONFIG_SDA_GPIO and CONFIG_SCL_GPIO conflict on ds3231 and ssd1306

void ssd1306(void *pvParameters)
{
    SSD1306_t dev;

    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);
    //i2c_master_init_ssd1306(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
    i2c_master_init_ssd1306(&dev, 5, 4, -1);

#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);
    vTaskDelete(NULL);
}
hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

The following version works fine with the previous version of my program (originally in esp-idf 4.6).

void app_main()
{
i2c_dev_t devRTC;
memset(&devRTC, 0, sizeof(i2c_dev_t));

if (ds3231_init_desc(&devRTC, I2C_NUM_0, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO) != ESP_OK)
{
    halt("RTC failed.");
}

struct tm timeinfo = {
    .tm_year = 2024, .tm_mon = 7, .tm_mday = 15, .tm_hour = 17, .tm_min = 50, .tm_sec = 55};

printf("Setting RTC to: %04d-%02d-%02d %02d:%02d:%02d\n",
       timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday,
       timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

if (ds3231_set_time(&devRTC, &timeinfo) != ESP_OK)
{
    halt("Error RTC Write.");
}

if (ds3231_get_time(&devRTC, &timeinfo) != ESP_OK)
{
    printf("Error while reading RTC");
}

printf("Read back from RTC: %04d-%02d-%02d %02d:%02d:%02d\n",
       timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday,
       timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

SSD1306_t devOled;

devOled._address = I2C_ADDRESS; // 0x3C
ssd1306_init(&devOled, 128, 32);

ssd1306_clear_screen(&devOled, false);
ssd1306_display_text_x3(&devOled, 0, "Hello", 5, false);

while (1)
{
    vTaskDelay(1000);
}

}

nopnop2002

nopnop2002 commented on Sep 7, 2024

@nopnop2002
Owner

I am forcing it to use the legacy driver

Yes.
Added forced legacy i2c driver mode to latest version of SSD1306.


$ cd $HOME

$ git clone https://github.com/nopnop2002/esp-idf-ssd1306

$ cd $HOME/esp-idf-ssd1306/components/ssd1306

$ cp CMakeLists.txt $HOME/esp-idf-ds3231/components/ssd1306/

$ cp Kconfig.projbuild $HOME/esp-idf-ds3231/components/ssd1306/

$ cd $HOME/esp-idf-ds3231

$ rm -r build

$ rm sdkconfig

$ idf.py menuconfig

config-i2c-driver


Please specify the GPIO number of SSD1306 directly.
CONFIG_SDA_GPIO and CONFIG_SCL_GPIO conflict on ds3231 and ssd1306

void app_main()
{
i2c_dev_t devRTC;
memset(&devRTC, 0, sizeof(i2c_dev_t));

if (ds3231_init_desc(&devRTC, I2C_NUM_0, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO) != ESP_OK)
{
    halt("RTC failed.");
}

struct tm timeinfo = {
    .tm_year = 2024, .tm_mon = 7, .tm_mday = 15, .tm_hour = 17, .tm_min = 50, .tm_sec = 55};

printf("Setting RTC to: %04d-%02d-%02d %02d:%02d:%02d\n",
       timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday,
       timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

if (ds3231_set_time(&devRTC, &timeinfo) != ESP_OK)
{
    halt("Error RTC Write.");
}

if (ds3231_get_time(&devRTC, &timeinfo) != ESP_OK)
{
    printf("Error while reading RTC");
}

printf("Read back from RTC: %04d-%02d-%02d %02d:%02d:%02d\n",
       timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday,
       timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

SSD1306_t devOled;

devOled._address = I2C_ADDRESS; // 0x3C

i2c_master_init_ssd1306(&devOled, 5, 4, -1);

ssd1306_init(&devOled, 128, 32);

ssd1306_clear_screen(&devOled, false);
ssd1306_display_text_x3(&devOled, 0, "Hello", 5, false);

while (1)
{
    vTaskDelay(1000);
}
hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

The reason I tried to upgrade was due to a warning I saw while building the program, which recommended upgrading the I2C driver. However, I don't see that warning now, which is strange.

nopnop2002

nopnop2002 commented on Sep 7, 2024

@nopnop2002
Owner

Let's organize some information.

Is your ESP-IDF version 4.6?

Is the clone of ssd1306 the latest?

hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author
  1. I have upgraded my ESP-IDF to 5.3. I may still have 4.6 on another machine, though.

  2. The version that works fine now even on 5.3 is an old clone of your repo, but the sample that I am working on now is based on your source from earlier today.

When I try to initialize I2C for the OLED with the function call
i2c_master_init_ssd1306(&devOled, 13, 12, -1);

I get the following error:
E (345) i2c: i2c driver install error.

However, it works fine if I remove that line.

hsnprojects

hsnprojects commented on Sep 7, 2024

@hsnprojects
Author

I was hoping to use I2C in a manner similar to Arduino's Wire.begin(), where initializing the I2C bus would be separate from adding devices like the RTC or OLED to the bus.

nopnop2002

nopnop2002 commented on Sep 7, 2024

@nopnop2002
Owner

C++ is very limited in esp-idf.
In order to use the class like Arduino, it is necessary to change from main.c to main.cpp, but the driver provided by ESP-IDF does not support main.cpp.

15 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Will this work with RTC? · Issue #29 · nopnop2002/esp-idf-ssd1306