ESP32 с TM1637 4-разрядным 7-сегментным LED-дисплеем (Arduino IDE)
Это руководство по подключению 4-разрядного 7-сегментного LED-дисплея TM1637 к ESP32, программируемому в Arduino IDE. Вы узнаете, как подключить дисплей к ESP32 и как выводить на него символы. В качестве примера мы покажем, как создать цифровые часы и дисплей температуры.
В этом руководстве мы рассмотрим следующие темы:
Знакомство с TM1637 4-разрядным 7-сегментным LED-дисплеем
TM1637 4-разрядный 7-сегментный LED-дисплей — это модуль дисплея, который объединяет четыре 7-сегментных цифры на одном дисплее, управляемом через драйвер TM1637. Конкретный модуль, который мы используем здесь, имеет четыре цифры, разделённые двоеточием между второй и третьей цифрами.
Существуют аналогичные модули с точками между цифрами.
Также существуют аналогичные модули с шестью 7-сегментными цифрами. Для них требуется другая библиотека, отличная от той, которую мы будем использовать в этом руководстве.
Примечание: Я попытался использовать свой 6-разрядный модуль дисплея, но, похоже, многие из этих дисплеев поставляются с дефектами по умолчанию. Мне не удалось заставить свой работать. Поэтому это руководство будет только о модуле с четырьмя цифрами и двоеточием посередине.
Где купить?
Вы можете проверить нашу страницу Maker Advisor Tools, чтобы сравнить цены на модуль TM1637 4-разрядного 7-сегментного дисплея в разных магазинах:
Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все детали для ваших проектов по лучшей цене!
Подключение TM1637 4-разрядного 7-сегментного дисплея к ESP32
Подключение дисплея к ESP32 довольно просто, так как требуется всего два цифровых пина: CLK и DI/O.
TM1637 Display |
ESP32 |
|---|---|
CLK |
Любой цифровой пин (например: GPIO 19)* |
DIO |
Любой цифровой пин (например: GPIO 18)* |
VCC |
VIN |
GND |
GND |
* вы можете использовать любые другие подходящие GPIO. Проверьте руководство по распиновке ESP32:
Мы подключим пин CLK к GPIO 19, а пин DIO к GPIO 18, но вы можете использовать другую комбинацию пинов.
Установка библиотеки TM1637
Существует несколько библиотек для работы с дисплеем TM1637 на ESP32. Мы будем использовать библиотеку TM1637.h от avishorp (хотя она не обновлялась несколько лет, она всё ещё хорошо работает и очень проста в использовании).
Вы можете установить библиотеку через менеджер библиотек Arduino IDE. Найдите TM1637 и установите библиотеку от avishorp.
Тестирование дисплея TM1637 (базовые функции)
Следующий код предоставляется библиотекой для тестирования дисплея. Вы определите, правильно ли работает ваш дисплей, и увидите, как реализовать базовые функции для инициализации, управления дисплеем и записи символов.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
Based on the TM1637Display library example: https://github.com/avishorp/TM1637/blob/master/examples/TM1637Test/TM1637Test.ino
*/
#include <Arduino.h>
#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 19
#define DIO 18
// The amount of time (in milliseconds) between tests
#define TEST_DELAY 2000
const uint8_t SEG_DONE[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};
TM1637Display display(CLK, DIO);
void setup()
{
}
void loop()
{
int k;
uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };
uint8_t blank[] = { 0x00, 0x00, 0x00, 0x00 };
display.setBrightness(0x0f);
// All segments on
display.setSegments(data);
delay(TEST_DELAY);
display.showNumberDecEx(1230, 0b01000000);
delay(10000);
// Selectively set different digits
data[0] = display.encodeDigit(7);
data[1] = display.encodeDigit(6);
data[2] = display.encodeDigit(5);
data[3] = display.encodeDigit(9);
display.setSegments(data);
delay(TEST_DELAY);
/*
for(k = 3; k >= 0; k--) {
display.setSegments(data, 1, k);
delay(TEST_DELAY);
}
*/
display.clear();
display.setSegments(data+2, 2, 2);
delay(TEST_DELAY);
display.clear();
display.setSegments(data+2, 2, 1);
delay(TEST_DELAY);
display.clear();
display.setSegments(data+1, 3, 1);
delay(TEST_DELAY);
// Show decimal numbers with/without leading zeros
display.showNumberDec(0, false); // Expect: ___0
delay(TEST_DELAY);
display.showNumberDec(0, true); // Expect: 0000
delay(TEST_DELAY);
display.showNumberDec(1, false); // Expect: ___1
delay(TEST_DELAY);
display.showNumberDec(1, true); // Expect: 0001
delay(TEST_DELAY);
display.showNumberDec(301, false); // Expect: _301
delay(TEST_DELAY);
display.showNumberDec(301, true); // Expect: 0301
delay(TEST_DELAY);
display.clear();
display.showNumberDec(14, false, 2, 1); // Expect: _14_
delay(TEST_DELAY);
display.clear();
display.showNumberDec(4, true, 2, 2); // Expect: 04__
delay(TEST_DELAY);
display.showNumberDec(-1, false); // Expect: __-1
delay(TEST_DELAY);
display.showNumberDec(-12); // Expect: _-12
delay(TEST_DELAY);
display.showNumberDec(-999); // Expect: -999
delay(TEST_DELAY);
display.clear();
display.showNumberDec(-5, false, 3, 0); // Expect: _-5_
delay(TEST_DELAY);
display.showNumberHexEx(0xf1af); // Expect: f1Af
delay(TEST_DELAY);
display.showNumberHexEx(0x2c); // Expect: __2C
delay(TEST_DELAY);
display.showNumberHexEx(0xd1, 0, true); // Expect: 00d1
delay(TEST_DELAY);
display.clear();
display.showNumberHexEx(0xd1, 0, true, 2); // Expect: d1__
delay(TEST_DELAY);
// Run through all the dots
for(k=0; k <= 4; k++) {
display.showNumberDecEx(0, (0x80 >> k), true);
delay(TEST_DELAY);
}
// Brightness Test
for(k = 0; k < 4; k++)
data[k] = 0xff;
for(k = 0; k < 7; k++) {
display.setBrightness(k);
display.setSegments(data);
delay(TEST_DELAY);
}
// On/Off test
for(k = 0; k < 4; k++) {
display.setBrightness(7, false); // Turn off
display.setSegments(data);
delay(TEST_DELAY);
display.setBrightness(7, true); // Turn on
display.setSegments(data);
delay(TEST_DELAY);
}
// Done!
display.setSegments(SEG_DONE);
while(1);
}
Давайте рассмотрим некоторые из важных функций, используемых в этом примере.
Инициализация дисплея
Для инициализации дисплея вам нужно просто создать экземпляр TM1637Display с пинами, которые вы используете для подключения модуля к ESP32.
TM1637Display display(CLK, DIO);
Установка яркости дисплея
Для установки яркости дисплея вы можете использовать метод setBrightness() объекта display. Вы можете передать один или два аргумента в эту функцию.
void setBrightness(uint8_t brightness, bool on = true);
Первый — число от 0 (минимальная яркость) до 7 (максимальная яркость), а второй аргумент включает (true) или выключает (false) дисплей.
В коде эта функция тестируется в следующем фрагменте.
// Brightness Test
for(k = 0; k < 4; k++)
data[k] = 0xff;
for(k = 0; k < 7; k++) {
display.setBrightness(k);
display.setSegments(data);
delay(TEST_DELAY);
}
// On/Off test
for(k = 0; k < 4; k++) {
display.setBrightness(7, false); // Turn off
display.setSegments(data);
delay(TEST_DELAY);
display.setBrightness(7, true); // Turn on
display.setSegments(data);
delay(TEST_DELAY);
}
Управление сегментами
Дисплей TM1637 поставляется с четырьмя 7-сегментными цифрами. Вы можете вручную управлять отдельными сегментами каждой цифры с помощью функции setSegments(), используя массив байтов.
void setSegments(const uint8_t segments[], uint8_t length = 4, uint8_t pos = 0);
segments: массив байтов, определяющий, какие сегменты включены для цифры. Каждый бит в байте соответствует одному LED-сегменту;
length: сколько цифр обновлять (от 0 до 4) — этот параметр необязательный;
pos: начальная позиция (0 — крайняя левая, 3 — крайняя правая) — по умолчанию 0. Этот параметр также необязательный.
Как кодируются сегменты
Каждый сегмент соответствует биту в байте. Посмотрите на следующую таблицу:
Сегмент |
Бит |
|---|---|
A |
0 |
B |
1 |
C |
2 |
D |
3 |
E |
4 |
F |
5 |
G |
6 |
Бит 1 включает сегмент, а бит 0 выключает его.
Например, чтобы включить сегменты A, B и C, вам понадобится байт вроде 0b0000111.
Байт начинается с G и заканчивается A. Например:
0b0000110 включает сегменты C и B.
Отображение определённых цифр или символов
Чтобы отобразить определённое число, вам нужно использовать правильную комбинацию сегментов:
0: a, b, c, d, e, f
1: b, c
2: a, b, g, e, d
3: a, b, g, c, d
4: f, g, b, c
5: a, f, g, c, d
6: a, f, g, e, d, c
7: a, b, c
8: a, b, c, d, e, f, g
9: a, b, c, d, f, g
С этим вы также можете отображать другие символы, не только числа.
Например, чтобы вручную закодировать 0123 на дисплее, вам понадобится массив байтов следующего вида:
uint8_t segments[] = {
0b0111111, // 0 — all segments except G
0b0000110, // 1 — segments B and C
0b1011011, // 2
0b1001111 // 3
};
Например, чтобы протестировать эту функцию, вы можете использовать следующий код:
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <Arduino.h>
#include <TM1637Display.h>
#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);
void setup() {
display.setBrightness(7);
// Custom segments (one byte per digit)
uint8_t segments[] = {
0b0111111, // 0 — all segments except G
0b0000110, // 1 — segments B and C
0b1011011, // 2
0b1001111 // 3
};
display.setSegments(segments);
}
void loop() {
}
Отображение десятичного числа
Для отображения десятичного числа вы можете использовать функцию showNumberDec() объекта display.
void showNumberDec(int num, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
Эта функция принимает следующие параметры:
num: отображаемое число
leading_zero: когда true, отображаются ведущие нули. В противном случае ненужные цифры остаются пустыми.
length: количество отображаемых цифр. Пользователь должен убедиться, что отображаемое число помещается в запрашиваемое количество цифр (например, если нужно отобразить две цифры, число должно быть от 0 до 99)
pos: позиция старшей цифры (0 — крайняя левая, 3 — крайняя правая)
В коде есть несколько примеров использования этой функции. Комментарии показывают, что каждая команда отобразит.
display.showNumberDec(0, false); // Expect: ___0
delay(TEST_DELAY);
display.showNumberDec(0, true); // Expect: 0000
delay(TEST_DELAY);
display.showNumberDec(1, false); // Expect: ___1
delay(TEST_DELAY);
display.showNumberDec(1, true); // Expect: 0001
delay(TEST_DELAY);
display.showNumberDec(301, false); // Expect: _301
delay(TEST_DELAY);
display.showNumberDec(301, true); // Expect: 0301
delay(TEST_DELAY);
display.clear();
display.showNumberDec(14, false, 2, 1); // Expect: _14_
delay(TEST_DELAY);
display.clear();
display.showNumberDec(4, true, 2, 2); // Expect: 04__
delay(TEST_DELAY);
display.showNumberDec(-1, false); // Expect: __-1
delay(TEST_DELAY);
display.showNumberDec(-12); // Expect: _-12
delay(TEST_DELAY);
display.showNumberDec(-999); // Expect: -999
delay(TEST_DELAY);
display.clear();
display.showNumberDec(-5, false, 3, 0); // Expect: _-5_
delay(TEST_DELAY);
Отображение десятичного числа с двоеточием/точкой
Существует ещё одна функция, которая позволяет отображать десятичное число и управлять тем, включено ли двоеточие или точка (в зависимости от дисплея). Это функция showNumberDecEx(). Вот принимаемые параметры:
void showNumberDecEx(uint16_t num, uint8_t dots = 0, bool leading_zero = false, uint8_t length = 4, uint8_t pos = 0);
Она аналогична предыдущей функции showNumberDec(), но второй аргумент позволяет включать или выключать двоеточие/точку.
num: отображаемое число
dots: включение точки/двоеточия — смотрите ниже, как это работает
leading_zero: когда true, отображаются ведущие нули. В противном случае ненужные цифры остаются пустыми.
length: количество отображаемых цифр. Пользователь должен убедиться, что отображаемое число помещается в запрашиваемое количество цифр (например, если нужно отобразить две цифры, число должно быть от 0 до 99)
pos: позиция старшей цифры (0 — крайняя левая, 3 — крайняя правая)
Управление двоеточием/точкой
Второй аргумент функции showNumberDecEx() — это битовая маска, где каждый бит соответствует точке между цифрами (или знаку двоеточия, в зависимости от реализации каждого модуля).
Например, для дисплеев с точками между каждой цифрой:
0.000 > (0b10000000)
00.00 > (0b01000000)
000.0 > (0b00100000)
0.0.0.0 > (0b11100000)
В нашем случае это дисплей только с двоеточием. Поэтому для отображения двоеточия мы можем передать следующее двоичное значение в качестве второго аргумента:
00:00 > (0b01000000)
Наконец, вот пример для дисплеев с точками и двоеточием:
0.0:0.0 > (0b11100000)
Например, чтобы отобразить 12:30, вы бы вызвали:
display.showNumberDecEx(1230, 0b01000000);
В коде функция используется здесь:
// Run through all the dots
for(k=0; k <= 4; k++) {
display.showNumberDecEx(0, (0x80 >> k), true);
delay(TEST_DELAY);
}
Демонстрация
Загрузите код на плату. На дисплее будет отображаться серия цифр, символов и сегментов для тестирования функций библиотеки.
Если пример не работает, перепроверьте подключение и источник питания.
Практические примеры с дисплеем TM1637
Теперь, когда вы знаете базовые функции управления дисплеем, мы покажем вам два практических примера, которые вы можете протестировать с дисплеем TM1637 и ESP32:
Цифровые часы ESP32 с дисплеем TM1637 (с настройкой часового пояса и DST)
Отображение температуры на ESP32 (TM1637) — с температурой от WeatherAPI
Эти два проекта требуют только ESP32 и дисплей. Дополнительное оборудование не нужно, так как вся информация будет запрашиваться из интернета с помощью :doc:`Wi-Fi возможностей ESP32 <../esp32-useful-wi-fi-functions-arduino/index>`_.
Цифровые часы ESP32 с дисплеем TM1637 (с настройкой часового пояса и DST)
Компоновка 4-разрядного 7-сегментного дисплея TM1637 с двоеточием между вторым и третьим символами идеально подходит для создания цифровых часов, с часами на одной стороне двоеточия и минутами на другой.
Мы получим время для вашего часового пояса, используя NTP (network time protocol) с учётом перехода на летнее время.
Чтобы узнать больше о получении времени с ESP32 для вашего часового пояса с учётом перехода на летнее время (если это актуально), вы можете прочитать следующее подробное руководство:
Обзор проекта
Вот краткий обзор шагов для создания этого проекта:
Инициализация дисплея;
Инициализация Wi-Fi и подключение ESP32 к вашей локальной сети, чтобы он мог получать данные из интернета;
Инициализация времени для указанного часового пояса (учитывает переход на летнее время);
Отображение времени на дисплее (мигание двоеточия между цифрами каждую секунду).
Код – Цифровые часы TM1637
Вы можете загрузить следующий код на вашу плату ESP32. Вам нужно:
Вставить ваш SSID и пароль;
Вставить строку вашего часового пояса. Список можно найти на GitHub nayarsystems.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include "time.h"
#include <TM1637Display.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// TM1637 pins
#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);
// Timezone (Lisbon / Portugal)
// Change if needed - See list of timezones strings: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
const char* TZ_INFO = "WET0WEST,M3.5.0/1,M10.5.0";
// Init Wifi
void initWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
}
// Initialize Time with the specified timezone
void initTime() {
configTime(0, 0, "pool.ntp.org");
setenv("TZ", TZ_INFO, 1);
tzset();
}
// display the time on the screen
void displayTime() {
// blinking colon
static bool colon = false;
colon = !colon;
// get the current time
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return;
}
int hours = timeinfo.tm_hour; // get hours (0–23)
int minutes = timeinfo.tm_min; // get minutes (0–59)
// move hours to the left two digits
int hourPart = hours * 100;
// combine hours and minutes into HHMM
int value = hourPart + minutes;
// control the colon (for blinking colon)
uint8_t colonMask;
if (colon == true) {
colonMask = 0b01000000; // turn colon ON
} else {
colonMask = 0; // turn colon OFF
}
display.showNumberDecEx(
value,
colonMask, // blink colon
true // leading zeros
);
}
void setup() {
Serial.begin(115200);
display.setBrightness(7);
display.clear();
initWiFi();
initTime();
}
void loop() {
displayTime();
delay(1000);
}
Как работает код?
Давайте быстро рассмотрим код, чтобы понять, как он работает.
Подключение библиотек
Начните с подключения необходимых библиотек.
#include <WiFi.h>
#include "time.h"
#include <TM1637Display.h>
Сетевые учётные данные
Вставьте ваши сетевые учётные данные в следующие строки.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Инициализация дисплея
Установите пины TM1637 и создайте экземпляр дисплея с именем display.
// TM1637 pins
#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);
Часовой пояс
Вставьте строку вашего часового пояса в следующую строку. Вы можете найти список строк часовых поясов здесь. В моём случае мой часовой пояс — Лиссабон/Португалия, поэтому это будет выглядеть так:
const char* TZ_INFO = "WET0WEST,M3.5.0/1,M10.5.0";
Инициализация Wi-Fi
Следующая функция инициализирует Wi-Fi и подключает ESP32 к вашей локальной сети. Она будет вызвана позже в setup().
// Init Wifi
void initWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
}
Вы можете узнать больше о Wi-Fi функциях ESP32 в следующем руководстве:
Инициализация времени
Функция initTime() инициализирует NTP-время и настраивает его на ваш часовой пояс — обратите внимание на функции setenv() и tzset().
// Initialize Time with the specified timezone
void initTime() {
configTime(0, 0, "pool.ntp.org");
setenv("TZ", TZ_INFO, 1);
tzset();
}
Чтобы узнать больше о получении даты и времени с настройкой часового пояса, ознакомьтесь с этим руководством:
Функция displayTime() будет отображать дату и время на экране.
void displayTime() {
У нас есть булева переменная colon, которая определяет, отображается ли двоеточие или нет (для создания эффекта мигания).
// blinking colon
static bool colon = false;
colon = !colon;
Мы получаем текущее время и сохраняем его в структуре timeinfo.
// get the current time
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return;
}
Затем мы можем получить часы и минуты следующим образом:
int hours = timeinfo.tm_hour; // get hours (0–23)
int minutes = timeinfo.tm_min; // get minutes (0–59)
Теперь, чтобы отобразить числа на экране, нам нужно объединить дату и время в одно четырёхзначное число, которое будет разделено посередине двоеточием.
Мы можем сделать это, умножив часы на 100 и затем добавив минуты.
// move hours to the left two digits
int hourPart = hours * 100;
// combine hours and minutes into HHMM
int value = hourPart + minutes;
Например, представьте, что час — 12, а минуты — 30. Мы хотим получить 12:30. Поэтому нам нужно получить число 1230 и отобразить двоеточие посередине.
12*100+30 даст желаемое 1230. Это число сохраняется в переменной value.
Наконец, мы настраиваем битовую маску для отображения двоеточия в зависимости от того, пора ли его показывать.
// control the colon (for blinking colon)
uint8_t colonMask;
if (colon == true) {
colonMask = 0b01000000; // turn colon ON
} else {
colonMask = 0; // turn colon OFF
}
Мы можем использовать showNumberDecEx() для отображения времени на экране. Передайте в качестве аргумента значение, битовую маску для двоеточия и наличие ведущих нулей.
display.showNumberDecEx(
value,
colonMask, // blink colon
true // leading zeros
);
Теперь, когда все основные функции объявлены, легко настроить наш код.
setup()
В setup() инициализируйте Serial Monitor, установите яркость дисплея, инициализируйте Wi-Fi и время.
void setup() {
Serial.begin(115200);
display.setBrightness(7);
display.clear();
initWiFi();
initTime();
}
loop()
Наконец, в loop() вам нужно просто вызвать функцию displayTime() для отображения времени на 4-разрядном 7-сегментном дисплее.
void loop() {
displayTime();
delay(1000);
}
Демонстрация
После ввода ваших сетевых учётных данных и информации о часовом поясе вы можете загрузить код на ESP32.
Он должен начать отображать текущее время для вашего часового пояса.
Двоеточие должно мигать каждую секунду, имитируя старые цифровые часы.
Отображение температуры на ESP32 (TM1637) из Weather API
В этом проекте мы будем отображать текущую температуру для вашего города на дисплее. Мы получим температуру из Weather API.
Этот API бесплатный и предоставляет полезную информацию о погоде практически в любом месте мира.
Мы получим температуру для вашего местоположения и отобразим её на 7-сегментном дисплее.
Получение API-ключа
Перейдите на сайт Weather API: weatherapi.com/
Зарегистрируйтесь для создания аккаунта.
После подтверждения аккаунта войдите в него.
На вашей панели управления на weatherapi.com/my/ вы найдёте ваш API-ключ (несмотря на то, что указано, что пробная версия закончится, вы можете продолжать использовать ваш API-ключ бесплатно).
Скопируйте API-ключ в безопасное место, потому что он понадобится вам позже.
Чтобы получить информацию о погоде в выбранном вами местоположении, введите следующий URL в веб-браузер, но вставьте ваше местоположение и API-ключ в нужные места:
https://api.weatherapi.com/v1/current.json?q=YOUR_LOCATION+&key=YOUR_API_KEY'
Например, в моём случае:
https://api.weatherapi.com/v1/current.json?q=Oporto+&key=d1578a064b07453c917164350240106'
Скопируйте ваш URL и вставьте его в браузер, и API вернёт информацию, соответствующую вашей местной погоде. Например:
{
"location": {
"name": "Oporto",
"region": "Porto",
"country": "Portugal",
"lat": 41.15,
"lon": -8.62,
"tz_id": "Europe/Lisbon",
"localtime_epoch": 1719843562,
"localtime": "2024-07-01 15:19"
},
"current": {
"last_updated_epoch": 1719843300,
"last_updated": "2024-07-01 15:15",
"temp_c": 22.3,
"temp_f": 72.1,
"is_day": 1,
"condition": {
"text": "Sunny",
"icon": "//cdn.weatherapi.com/weather/64x64/day/113.png",
"code": 1000
},
"wind_mph": 10.5,
"wind_kph": 16.9,
"wind_degree": 310,
"wind_dir": "NW",
"pressure_mb": 1021,
"pressure_in": 30.15,
"precip_mm": 0,
"precip_in": 0,
"humidity": 69,
"cloud": 0,
"feelslike_c": 24.7,
"feelslike_f": 76.4,
"windchill_c": 21.9,
"windchill_f": 71.5,
"heatindex_c": 24.6,
"heatindex_f": 76.2,
"dewpoint_c": 15,
"dewpoint_f": 58.9,
"vis_km": 10,
"vis_miles": 6,
"uv": 6,
"gust_mph": 15.4,
"gust_kph": 24.7
}
}
Из этого JSON мы можем легко получить температуру для вашего местоположения, как в Цельсиях, так и в Фаренгейтах: temp_c и temp_f.
Установка библиотек
Для этого примера вам нужно установить библиотеку ArduinoJSON от bblanchon.
Код – Дисплей температуры TM1637
Вы можете загрузить следующий код на вашу плату. Вам нужно:
вставить ваш SSID и пароль;
вставить ваш API-ключ WeatherAPI;
вставить город, для которого вы хотите получить температуру.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TM1637Display.h>
// Wi-Fi credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* api_key = "REPLACE_WITH_YOUR_WeatherAPI_API_Key";
const char* location = "Oporto"; // "q" Parameter documentation for location: https://www.weatherapi.com/docs/#intro-request
// Request URL
String url = "https://api.weatherapi.com/v1/current.json?q=" + String(location) + "&key=" + String(api_key);
// TM1637 pins
#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);
// Create the °C Symbol
const uint8_t Celsius[] = {
SEG_A | SEG_B | SEG_F | SEG_G, // Circle
SEG_A | SEG_D | SEG_E | SEG_F // C
};
// Create the °F Symbol
const uint8_t Fahrenheit[] = {
SEG_A | SEG_B | SEG_F | SEG_G, // Circle
SEG_F | SEG_E | SEG_A | SEG_G // F
};
// Global variables for temperatures and timers
float currentTempC = 9999; // Initial error value
float currentTempF = 9999; // Initial error value
unsigned long lastFetchTime = 0;
const unsigned long fetchInterval = 3600000UL; // 1 hour in milliseconds
// Init Wifi
void initWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connection successful");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
bool updateTemperatures() {
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) { // Check for 200 specifically
String payload = http.getString();
Serial.print(payload);
// Parse JSON
StaticJsonDocument<1024> doc; // Adjust size if needed based on response
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print("JSON parsing failed: ");
Serial.println(error.c_str());
http.end();
return false;
}
// Get both temperatures
currentTempC = doc["current"]["temp_c"];
currentTempF = doc["current"]["temp_f"];
http.end();
return true;
} else {
Serial.print("Error during request: ");
Serial.println(httpCode);
http.end();
return false;
}
}
void setup() {
Serial.begin(115200);
delay(1000); // Give time for Serial to initialize
// Connect to Wi-Fi
initWiFi();
display.setBrightness(7); // Set the display brightness (0-7)
// Initial fetch
if (updateTemperatures()) {
lastFetchTime = millis();
}
}
void loop() {
// Check if it's time to fetch new data
if (millis() - lastFetchTime >= fetchInterval) {
if (updateTemperatures()) {
lastFetchTime = millis();
} else {
// If failed, try again next loop
Serial.println("Fetch failed, keeping old values.");
}
}
// Show Celsius
Serial.print("Temperature in Celsius: ");
Serial.println(currentTempC, 2);
int roundedTempC = round(currentTempC);
display.showNumberDec(roundedTempC, false, 2, 0);
display.setSegments(Celsius, 2, 2);
delay(5000);
// Show Fahrenheit
Serial.print("Temperature in Fahrenheit: ");
Serial.println(currentTempF, 2);
int roundedTempF = round(currentTempF);
display.showNumberDec(roundedTempF, false, 2, 0);
display.setSegments(Fahrenheit, 2, 2);
delay(5000);
}
Как работает код?
Давайте быстро рассмотрим основные части кода для этого руководства.
Подключение библиотек
Мы начинаем с подключения необходимых библиотек.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TM1637Display.h>
Сетевые учётные данные
Вставьте ваши сетевые учётные данные в следующие строки.
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Weather API
Вставьте ваш ключ WeatherAPI и местоположение, для которого вы хотите получить данные.
const char* api_key = "REPLACE_WITH_YOUR_API_KEY";
const char* location = "REPLACE_WITH_YOUR_LOCATION";
Это URL запроса, который вернёт данные о погоде.
String url = "https://api.weatherapi.com/v1/current.json?q=" + String(location) + "&key=" + String(api_key);
Дисплей TM1637
Установите пины, управляющие дисплеем, и создайте экземпляр дисплея с именем display.
// TM1637 pins
#define CLK 19
#define DIO 18
TM1637Display display(CLK, DIO);
Создайте массив с необходимыми сегментами для создания символов градусов Цельсия и Фаренгейта.
// Create the °C Symbol
const uint8_t Celsius[] = {
SEG_A | SEG_B | SEG_F | SEG_G, // Circle
SEG_A | SEG_D | SEG_E | SEG_F // C
};
// Create the °F Symbol
const uint8_t Fahrenheit[] = {
SEG_A | SEG_B | SEG_F | SEG_G, // Circle
SEG_F | SEG_E | SEG_A | SEG_G // F
};
SEG_A, SEG_B и так далее — это ссылки на их конкретные байты (они определены в .h файле библиотеки).
Глобальные переменные
Создайте глобальные переменные для хранения температуры в Цельсиях и Фаренгейтах.
float currentTempC = 9999; // Initial error value
float currentTempF = 9999; // Initial error value
И вспомогательные переменные для подсчёта времени, чтобы делать запрос к API каждый час.
unsigned long lastFetchTime = 0;
const unsigned long fetchInterval = 3600000UL; // 1 hour in milliseconds
Инициализация Wi-Fi
Функция initWiFi() инициализирует Wi-Fi и подключится к вашей сети с использованием введённых учётных данных.
// Init Wifi
void initWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connection successful");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
Получение/обновление температуры
Функция updateTemperatures() делает запрос к URL WeatherAPI.
Запрос возвращает множество данных о погоде, как мы видели ранее. Мы выводим все данные в Serial Monitor.
bool updateTemperatures() {
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) { // Check for 200 specifically
String payload = http.getString();
Serial.print(payload);
Затем мы сохраняем только те данные, которые нас интересуют. В данном случае — температуру в Цельсиях и Фаренгейтах. Мы сохраняем их в переменных currentTempC и currentTempF.
currentTempC = doc["current"]["temp_c"];
currentTempF = doc["current"]["temp_f"];
Если всё прошло хорошо с запросом, функция возвращает true. В противном случае — false.
setup()
В setup() мы инициализируем Serial Monitor, подключаемся к Wi-Fi и устанавливаем яркость дисплея.
void setup() {
Serial.begin(115200);
delay(1000); // Give time for Serial to initialize
// Connect to Wi-Fi
initWiFi();
display.setBrightness(7); // Set the display brightness (0-7)
Затем мы делаем наш первый запрос к API для получения текущих температур при первом запуске кода. С этого момента мы также начинаем отсчёт времени, чтобы проверить позже в loop(), пора ли делать ещё один запрос.
// Initial fetch
if (updateTemperatures()) {
lastFetchTime = millis();
}
loop()
В loop() мы постоянно проверяем, когда пора получить новые значения.
// Check if it's time to fetch new data
if (millis() - lastFetchTime >= fetchInterval) {
if (updateTemperatures()) {
lastFetchTime = millis();
} else {
// If failed, try again next loop
Serial.println("Fetch failed, keeping old values.");
}
}
Затем на дисплее мы чередуем отображение температуры в Цельсиях и Фаренгейтах каждые пять секунд.
// Show Celsius
Serial.print("Temperature in Celsius: ");
Serial.println(currentTempC, 2);
int roundedTempC = round(currentTempC);
display.showNumberDec(roundedTempC, false, 2, 0);
display.setSegments(Celsius, 2, 2);
delay(5000);
// Show Fahrenheit
Serial.print("Temperature in Fahrenheit: ");
Serial.println(currentTempF, 2);
int roundedTempF = round(currentTempF);
display.showNumberDec(roundedTempF, false, 2, 0);
display.setSegments(Fahrenheit, 2, 2);
delay(5000);
Поскольку значения температуры приходят как переменные float, нам нужно преобразовать их в целые числа. Для этого мы используем функцию round() для округления числа. Например:
int roundedTempC = round(currentTempC);
Затем мы просто вызываем функцию showNumberDec() для отображения значений.
display.showNumberDec(roundedTempC, false, 2, 0);
Затем вызываем функцию setSegments() для отображения единиц измерения градусов Цельсия и Фаренгейта.
display.setSegments(Celsius, 2, 2);
Демонстрация
Загрузите код на вашу плату ESP32. Не забудьте вставить ваш SSID и пароль в код, а также API-ключ и ваше местоположение.
Вы должны получить сообщение об успехе в Serial Monitor.
И температура в градусах Цельсия и Фаренгейта будет поочерёдно отображаться на дисплее.
Заключение
Это было исчерпывающее руководство по подключению 4-разрядного 7-сегментного дисплея TM1637 к ESP32. Он может быть весьма полезен для отображения температуры, времени или другой информации.
Конкретный формат дисплея, который мы используем, с двоеточием посередине, может быть особенно полезен для создания цифровых часов или отображения таймера.
Мы надеемся, что это руководство оказалось полезным. У нас есть руководства для других дисплеев, которые могут быть полезны:
:doc:`ESP32 OLED Display with Arduino IDE <../esp32-ssd1306-oled-display-arduino-ide/index>`_
:doc:`How to Use I2C LCD with ESP32 on Arduino IDE <../esp32-esp8266-i2c-lcd-arduino-ide/index>`_
Getting Started with ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R)
ESP32: TFT LCD Touchscreen Display – 2.8 inch ILI9341 240x320 (Arduino IDE)
Чтобы узнать больше об ESP32, обязательно ознакомьтесь с нашими ресурсами:
Источник: Random Nerd Tutorials – Rui Santos & Sara Santos https://randomnerdtutorials.com/esp32-tm1637-4-digit-7-segment-display-arduino/