From ed645576627e9344e72be91c2fbe0ddd28c2aa90 Mon Sep 17 00:00:00 2001 From: Alexey Zholtikov Date: Sat, 16 May 2026 11:05:53 +0300 Subject: [PATCH] feat: added print int and float values --- README.md | 24 +++++-- include/zh_tm1637.h | 67 +++++++++++++++++-- version.txt | 2 +- zh_tm1637.c | 152 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 227 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 793b98f..acc02d3 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,7 @@ ## Features 1. Support up to 4 led drives on one device (depends on the used ESP32 chip). - -## Note - -1. Just simple driver without any additives. +2. Print raw symbols, int and float values. ## Attention @@ -44,7 +41,7 @@ In the application, add the component: ## Examples -One 4 segment led drive on device: +One 6 segment led drive on device: ```c // Numerical symbols without dot (with dot). @@ -76,8 +73,21 @@ void app_main(void) zh_tm1637_set_brightness(&tm1637_handle, 7); // Set brightness. zh_tm1637_clear(&tm1637_handle); vTaskDelay(1000 / portTICK_PERIOD_MS); - zh_tm1637_print(&tm1637_handle, 0, 0x4F); // 3 on C0H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C0H, 0x3F); // 0 on C0H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C1H, 0x06); // 1 on C1H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C2H, 0x5B); // 2 on C2H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C3H, 0x4F); // 3 on C3H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C4H, 0x66); // 4 on C4H address. + zh_tm1637_print(&tm1637_handle, ZH_TM1637_C5H, 0x6D); // 5 on C5H address. + vTaskDelay(1000 / portTICK_PERIOD_MS); + // If the display of numbers on the screen does not correspond to the order, it is necessary to establish physical correspondence. + // For example you sees 210543. The physical correspondence should be established as follows: + zh_tm1637_set(&tm1637_handle, ZH_TM1637_C2H, ZH_TM1637_C1H, ZH_TM1637_C0H, ZH_TM1637_C5H, ZH_TM1637_C4H, ZH_TM1637_C3H); + zh_tm1637_clear(&tm1637_handle); + zh_tm1637_print_int(&tm1637_handle, 0, 123456); + vTaskDelay(1000 / portTICK_PERIOD_MS); + zh_tm1637_clear(&tm1637_handle); + zh_tm1637_print_float(&tm1637_handle, 0, -156.255, 2); vTaskDelay(1000 / portTICK_PERIOD_MS); - zh_tm1637_print(&tm1637_handle, 4, 0x87); // 7. on C4H address. } ``` diff --git a/include/zh_tm1637.h b/include/zh_tm1637.h index 97d67c9..7047e9e 100644 --- a/include/zh_tm1637.h +++ b/include/zh_tm1637.h @@ -22,6 +22,20 @@ extern "C" { #endif + /** + * @brief Enumeration of TM1637 adresses. + */ + typedef enum + { + ZH_TM1637_C0H = 0x00, + ZH_TM1637_C1H, + ZH_TM1637_C2H, + ZH_TM1637_C3H, + ZH_TM1637_C4H, + ZH_TM1637_C5H, + ZH_TM1637_MAX + } zh_tm1637_address_t; + /** * @brief Structure for initial initialization of TM1637 led drive. */ @@ -36,11 +50,12 @@ extern "C" */ typedef struct { - bool is_initialized; /*!< Led drive initialization flag. */ - int8_t brightness; /*!< Led drive brightness. */ - rmt_sync_manager_handle_t synchro; /*!< Unique RMT TX device sync manager handle. */ - rmt_channel_handle_t tx_channel[2]; /*!< Unique RMT TX device handles. */ - rmt_encoder_handle_t copy_encoder; /*!< Unique copy encoder handle. */ + bool is_initialized; /*!< Led drive initialization flag. */ + int8_t brightness; /*!< Led drive brightness. */ + zh_tm1637_address_t digit_positions[6]; /*!< The physical relationship of the arrangement of digits on the display in relation to addresses. */ + rmt_sync_manager_handle_t synchro; /*!< Unique RMT TX device sync manager handle. */ + rmt_channel_handle_t tx_channel[2]; /*!< Unique RMT TX device handles. */ + rmt_encoder_handle_t copy_encoder; /*!< Unique copy encoder handle. */ } zh_tm1637_handle_t; /** @@ -85,7 +100,7 @@ extern "C" * * @return ESP_OK if success or an error code otherwise. */ - esp_err_t zh_tm1637_print(zh_tm1637_handle_t *handle, uint8_t address, uint8_t symbol); + esp_err_t zh_tm1637_print(zh_tm1637_handle_t *handle, zh_tm1637_address_t address, uint8_t symbol); /** * @brief Set brightness of the LED. @@ -109,7 +124,7 @@ extern "C" */ void zh_tm1637_reset_stats(void); - /** + /** * @brief Clear the LEDs. * * @param[in] handle Pointer to unique TM1637 handle. @@ -118,6 +133,44 @@ extern "C" */ esp_err_t zh_tm1637_clear(zh_tm1637_handle_t *handle); + /** + * @brief Sets physical relationship of the arrangement of digits on the display in relation to addresses. + * + * @param[in] handle Pointer to unique TM1637 handle. + * @param[in] digit_0 Address of digit 0. + * @param[in] digit_1 Address of digit 1. + * @param[in] digit_2 Address of digit 2. + * @param[in] digit_3 Address of digit 3. + * @param[in] digit_4 Address of digit 4. + * @param[in] digit_5 Address of digit 5. + * + * @return ESP_OK if success or an error code otherwise. + */ + esp_err_t zh_tm1637_set(zh_tm1637_handle_t *handle, zh_tm1637_address_t digit_0, zh_tm1637_address_t digit_1, zh_tm1637_address_t digit_2, zh_tm1637_address_t digit_3, zh_tm1637_address_t digit_4, zh_tm1637_address_t digit_5); + + /** + * @brief Prints an int value to the LED. + * + * @param[in] handle Pointer to unique TM1637 handle. + * @param[in] position Start position for print. + * @param[in] value Int value. + * + * @return ESP_OK if success or an error code otherwise. + */ + esp_err_t zh_tm1637_print_int(zh_tm1637_handle_t *handle, uint8_t position, int value); + + /** + * @brief Prints a float value to the LED. + * + * @param[in] handle Pointer to unique TM1637 handle. + * @param[in] position Start position for print. + * @param[in] value Float value. + * @param[in] precision The number of decimal places to display. + * + * @return ESP_OK if success or an error code otherwise. + */ + esp_err_t zh_tm1637_print_float(zh_tm1637_handle_t *handle, uint8_t position, float value, uint8_t precision); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/version.txt b/version.txt index 50aea0e..e3a4f19 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.0 \ No newline at end of file +2.2.0 \ No newline at end of file diff --git a/zh_tm1637.c b/zh_tm1637.c index abd781e..74b0396 100644 --- a/zh_tm1637.c +++ b/zh_tm1637.c @@ -30,6 +30,10 @@ esp_err_t zh_tm1637_init(const zh_tm1637_init_config_t *config, zh_tm1637_handle ZH_ERROR_CHECK(handle->is_initialized == false, ESP_ERR_INVALID_STATE, NULL, "Led drive initialization failed. Led drive is already initialized."); ZH_ERROR_CHECK(_zh_tm1637_validate_config(config, handle) == ESP_OK, ESP_FAIL, NULL, "Led drive initialization failed. Initial configuration check failed."); ZH_ERROR_CHECK(_zh_tm1637_rmt_init(config, handle) == ESP_OK, ESP_FAIL, , "Led drive initialization failed. RMT initialization failed."); + for (uint8_t i = 0; i < 6; ++i) + { + handle->digit_positions[i] = i; + } handle->brightness = 7; handle->is_initialized = true; ZH_LOGI("Led drive initialization completed successfully."); @@ -50,7 +54,7 @@ esp_err_t zh_tm1637_deinit(zh_tm1637_handle_t *handle) // -V2008 return ESP_OK; } -esp_err_t zh_tm1637_print(zh_tm1637_handle_t *handle, uint8_t address, uint8_t symbol) // -V2008 +esp_err_t zh_tm1637_print(zh_tm1637_handle_t *handle, zh_tm1637_address_t address, uint8_t symbol) // -V2008 { ZH_LOGI("Led drive printing started."); ZH_ERROR_CHECK(handle != NULL && address <= 5, ESP_ERR_INVALID_ARG, NULL, "Led drive printing failed. Invalid argument."); @@ -96,12 +100,154 @@ esp_err_t zh_tm1637_clear(zh_tm1637_handle_t *handle) ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Led drive clear failed. Led drive not initialized."); for (uint8_t i = 0; i < 6; ++i) { - ZH_ERROR_CHECK(zh_tm1637_print(handle, i, 0x00) == ESP_OK, ESP_FAIL, NULL, "Led drive clear failed. RMT driver error."); - }; + ZH_ERROR_CHECK(zh_tm1637_print(handle, (zh_tm1637_address_t)i, 0x00) == ESP_OK, ESP_FAIL, NULL, "Led drive clear failed. RMT driver error."); + } ZH_LOGI("Led drive clear completed successfully."); return ESP_OK; } +esp_err_t zh_tm1637_set(zh_tm1637_handle_t *handle, zh_tm1637_address_t digit_0, zh_tm1637_address_t digit_1, zh_tm1637_address_t digit_2, zh_tm1637_address_t digit_3, zh_tm1637_address_t digit_4, zh_tm1637_address_t digit_5) // -V2008 +{ + ZH_LOGI("Led drive set physical correspondence started."); + ZH_ERROR_CHECK(handle != NULL, ESP_ERR_INVALID_ARG, NULL, "Led drive set physical correspondence failed. Invalid argument."); + ZH_ERROR_CHECK(digit_0 < ZH_TM1637_MAX && digit_1 < ZH_TM1637_MAX && digit_2 < ZH_TM1637_MAX && digit_3 < ZH_TM1637_MAX && digit_4 < ZH_TM1637_MAX && digit_5 < ZH_TM1637_MAX, ESP_ERR_INVALID_ARG, NULL, "Led drive set physical correspondence failed. Invalid address."); + ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Led drive set physical correspondence failed. Led drive not initialized."); + uint8_t matrix[] = {digit_0, digit_1, digit_2, digit_3, digit_4, digit_5}; + for (uint8_t i = 0; i < sizeof(matrix); ++i) + { + for (uint8_t j = i + 1; j < sizeof(matrix); ++j) + { + ZH_ERROR_CHECK(matrix[i] != matrix[j], ESP_ERR_INVALID_ARG, NULL, "Led drive set physical correspondence failed. Addresses are repeated."); + } + } + handle->digit_positions[0] = digit_0; + handle->digit_positions[1] = digit_1; + handle->digit_positions[2] = digit_2; + handle->digit_positions[3] = digit_3; + handle->digit_positions[4] = digit_4; + handle->digit_positions[5] = digit_5; + ZH_LOGI("Led drive set physical correspondence completed successfully."); + return ESP_OK; +} + +esp_err_t zh_tm1637_print_int(zh_tm1637_handle_t *handle, uint8_t position, int value) // -V2008 +{ + ZH_LOGI("Led drive print int started."); + ZH_ERROR_CHECK(handle != NULL && position <= 5, ESP_ERR_INVALID_ARG, NULL, "Led drive print int failed. Invalid argument."); + ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Led drive print int failed. Led drive not initialized."); + char char_buffer[6] = {0}; + sprintf(char_buffer, "%d", value); + for (uint8_t i = 0; i < sizeof(char_buffer) - position; ++i) + { + uint8_t int_symbol = 0x00; + switch (char_buffer[i]) + { + case '-': + int_symbol = 0x40; + break; + case '0': + int_symbol = 0x3F; + break; + case '1': + int_symbol = 0x06; + break; + case '2': + int_symbol = 0x5B; + break; + case '3': + int_symbol = 0x4F; + break; + case '4': + int_symbol = 0x66; + break; + case '5': + int_symbol = 0x6D; + break; + case '6': + int_symbol = 0x7D; + break; + case '7': + int_symbol = 0x07; + break; + case '8': + int_symbol = 0x7F; + break; + case '9': + int_symbol = 0x6F; + break; + default: + break; + } + if (int_symbol != 0x00) + { + ZH_ERROR_CHECK(zh_tm1637_print(handle, handle->digit_positions[i + position], int_symbol) == ESP_OK, ESP_FAIL, NULL, "Led drive print int failed. RMT driver error."); + } + } + ZH_LOGI("Led drive print int completed successfully."); + return ESP_OK; +} + +esp_err_t zh_tm1637_print_float(zh_tm1637_handle_t *handle, uint8_t position, float value, uint8_t precision) // -V2008 +{ + ZH_LOGI("Led drive print float started."); + ZH_ERROR_CHECK(handle != NULL && position <= 5, ESP_ERR_INVALID_ARG, NULL, "Led drive print float failed. Invalid argument."); + ZH_ERROR_CHECK(handle->is_initialized == true, ESP_FAIL, NULL, "Led drive print float failed. Led drive not initialized."); + char char_buffer[7] = {0}; + uint8_t dot_offset = 0; + sprintf(char_buffer, "%.*f", precision, value); // -V512 + for (uint8_t i = 0; i < sizeof(char_buffer) - position; ++i) + { + uint8_t int_symbol = 0x00; + switch (char_buffer[i]) + { + case '.': + dot_offset = 1; + break; + case '-': + int_symbol = 0x40; + break; + case '0': + int_symbol = (char_buffer[i + 1] == '.') ? 0xBF : 0x3F; + break; + case '1': + int_symbol = (char_buffer[i + 1] == '.') ? 0x86 : 0x06; + break; + case '2': + int_symbol = (char_buffer[i + 1] == '.') ? 0xDB : 0x5B; + break; + case '3': + int_symbol = (char_buffer[i + 1] == '.') ? 0xCF : 0x4F; + break; + case '4': + int_symbol = (char_buffer[i + 1] == '.') ? 0xE6 : 0x66; + break; + case '5': + int_symbol = (char_buffer[i + 1] == '.') ? 0xED : 0x6D; + break; + case '6': + int_symbol = (char_buffer[i + 1] == '.') ? 0xFD : 0x7D; + break; + case '7': + int_symbol = (char_buffer[i + 1] == '.') ? 0x87 : 0x07; + break; + case '8': + int_symbol = (char_buffer[i + 1] == '.') ? 0xFF : 0x7F; + break; + case '9': + int_symbol = (char_buffer[i + 1] == '.') ? 0xEF : 0x6F; + break; + default: + break; + } + if (int_symbol != 0x00 && (i + position - dot_offset) != 6) + { + ZH_ERROR_CHECK(zh_tm1637_print(handle, handle->digit_positions[i + position - dot_offset], int_symbol) == ESP_OK, ESP_FAIL, NULL, "Led drive print float failed. RMT driver error."); + } + } + ZH_LOGI("Led drive print float completed successfully."); + return ESP_OK; +} + static esp_err_t _zh_tm1637_validate_config(const zh_tm1637_init_config_t *config, zh_tm1637_handle_t *handle) { ZH_ERROR_CHECK(config->clk_gpio < GPIO_NUM_MAX && config->dio_gpio < GPIO_NUM_MAX, ESP_ERR_INVALID_ARG, NULL, "Invalid GPIO number.")