//cpu - node mcu lolin (esp32)
#include <Arduino.h>
#include <EEPROM.h>
// Название контакта Номер пина
// D0 16
// D1 5
// D2 4
// D3 0
// Кнопки
// Кнопки
#define UP_BTN 34
#define DOWN_BTN 35
#define SET_BTN 32
#define LED 16
// Разряды (аноды/катоды)
const uint8_t digitPins[3] = {12, 14, 27};
// Сегменты 7-сегментного индикатора (a-g)
const uint8_t segPins[7] = {19, 21, 26, 25, 33, 22, 23};
// Таблица сегментов для цифр 0-9 (abcdefg)
const uint8_t segTable[10] = {
0b0000001, // 0
0b1001111, // 1
0b0010010, // 2
0b0000110, // 3
0b1001100, // 4
0b0100100, // 5
0b0100000, // 6
0b0001111, // 7
0b0000000, // 8
0b0000100 // 9
};
// PWM
#define PWM_PIN 4
#define ADDRESS 0
uint8_t duty = 0;
uint32_t lastDisplayUpdate = 0;
uint8_t currentDigit = 0;
bool showSavMessage = false; // Флаг отображения сообщения SAV
unsigned long savStartTime = 0; // Время начала отображения SAV
unsigned long lastPrintTime = 0; // Последний вывод на Serial
// Функция для отображения цифры на 7-сегментном индикаторе
void displayDigit(uint8_t digit) {
uint8_t segs = segTable[digit];
for (uint8_t i = 0; i < 7; i++) {
digitalWrite(segPins[i], (segs >> (6 - i)) & 0x01);
}
}
// Функция для отображения значения duty на 3-х разрядах
void displayDuty(uint8_t value, uint8_t digit) {
// Выключение всех разрядов
for (uint8_t i = 0; i < 3; i++) {
digitalWrite(digitPins[i], LOW);
}
// Получаем цифры для каждого разряда
uint8_t digits[3] = {
value / 100,
(value / 10) % 10,
value % 10
};
// Не показываем ведущий ноль, если duty меньше 100
if (digit == 0 && digits[0] == 0) {
for (uint8_t i = 0; i < 7; i++) {
digitalWrite(segPins[i], LOW);
}
} else {
displayDigit(digits[digit]);
}
// Активируем текущий разряд
digitalWrite(digitPins[digit], HIGH);
}
// Функция для отображения сообщения "SAV"
void displaySavMessage(uint8_t step) {
const uint8_t savPatterns[3][7] = {
{LOW, HIGH, HIGH, LOW, LOW, LOW, HIGH}, // S
{LOW, LOW, LOW, LOW, LOW, LOW, HIGH}, // A
{HIGH, LOW, LOW, HIGH, LOW, LOW, LOW} // V
};
// Выключаем все разряды
for (uint8_t i = 0; i < 3; i++) {
digitalWrite(digitPins[i], LOW);
}
// Устанавливаем сегменты для текущей буквы
for (uint8_t i = 0; i < 7; i++) {
digitalWrite(segPins[i], savPatterns[step][i]);
}
// Включаем соответствующий разряд
digitalWrite(digitPins[step], HIGH);
}
void setup() {
// Инициализация ввода-вывода
pinMode(UP_BTN, INPUT_PULLUP);
pinMode(DOWN_BTN, INPUT_PULLUP);
pinMode(SET_BTN, INPUT_PULLUP);
pinMode(PWM_PIN, OUTPUT);
pinMode(LED, OUTPUT);
// Настройка выходов для 7-сегментника
for (uint8_t i = 0; i < 7; i++) pinMode(segPins[i], OUTPUT);
for (uint8_t i = 0; i < 3; i++) pinMode(digitPins[i], OUTPUT);
// Загрузка duty из flash памяти
// Инициализируем модуль EEPROM с размером блока в байтах
EEPROM.begin(512); // Размер должен соответствовать размеру области, выделенной приложением
// Чтение сохраненного значения из EEPROM
duty = EEPROM.read(ADDRESS);
// Если прочитанное значение некорректное, сбрасываем его
if (duty > 100 || duty < 0) {
duty = 0;
}
analogWrite(PWM_PIN, map(duty, 0, 100, 0, 255)); // Применяем начальное значение
Serial.begin(115200);
Serial.println("Hello esp32!");
}
void loop() {
// Обработка нажатий кнопок
if (digitalRead(UP_BTN) == LOW && duty < 100) {
duty++;
analogWrite(PWM_PIN, map(duty, 0, 100, 0, 255));
delay(100); }
if (digitalRead(DOWN_BTN) == LOW && duty > 0) {
duty--;
analogWrite(PWM_PIN, map(duty, 0, 100, 0, 255));
delay(100); }
if (digitalRead(SET_BTN) == LOW) {
EEPROM.write(ADDRESS, duty); // Пишем новое значение
EEPROM.commit(); // Обязательно применяем изменения!
showSavMessage = true;
savStartTime = millis();
delay(100); }
// Отображение сообщения "SAV"
if (showSavMessage) {digitalWrite(LED, HIGH); // Зажечь светодиод
unsigned long now = millis();
uint8_t step = (now - savStartTime) / 50 % 3;
displaySavMessage(step);
if (now - savStartTime > 3000) {
showSavMessage = false;
digitalWrite(LED, LOW); // Погасить светодиод
}
} else {
// Обычный режим отображения duty
if (millis() - lastDisplayUpdate > 2) {
displayDuty(duty, currentDigit);
currentDigit = (currentDigit + 1) % 3;
lastDisplayUpdate = millis();
}
}
// Вывод на Serial каждые 3 секунды
if (millis() - lastPrintTime >= 3000) {
Serial.print("PWM Duty Cycle: ");
Serial.println(duty);
lastPrintTime = millis();
}
}