diff --git a/firmware/dac1 b/firmware/dac1 new file mode 100644 index 0000000..6cf99d4 --- /dev/null +++ b/firmware/dac1 @@ -0,0 +1,520 @@ +// ============================================================ +// ИНТЕРАКТИВНЫЙ ТЕСТОВЫЙ СКЕТЧ ДЛЯ XL4015 + ESP32 DAC +// ============================================================ +// Управление через Serial Monitor (115200 baud) +// ============================================================ + +#define DAC_PIN 25 // GPIO25 = DAC1 + +// Текущие значения +uint8_t current_dac = 0; +float current_voltage = 0.0; + +// Калибровочные значения (будут обновляться) +uint8_t cal_1s = 246; // Для 4.2V +uint8_t cal_2s = 195; // Для 8.4V +uint8_t cal_3s = 145; // Для 12.6V +uint8_t cal_4s = 0; // Для 16.8V + +// Настройка времени калибровки (в секундах) +int calibration_delay = 10; // По умолчанию 10 секунд + +void setup() { + Serial.begin(115200); + delay(1000); + + // Устанавливаем начальное значение DAC + dacWrite(DAC_PIN, 0); + current_dac = 0; + + printWelcome(); + printMenu(); +} + +void loop() { + // Проверяем, есть ли данные в Serial + if (Serial.available() > 0) { + String command = Serial.readStringUntil('\n'); + command.trim(); // Убираем пробелы + + processCommand(command); + } +} + +// ============================================================ +// ОБРАБОТКА КОМАНД +// ============================================================ + +void processCommand(String cmd) { + cmd.toLowerCase(); // Приводим к нижнему регистру + + Serial.println(); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + Serial.print("📨 Команда: "); + Serial.println(cmd); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + + // ========== ПРЯМОЕ УПРАВЛЕНИЕ DAC ========== + if (cmd.startsWith("d") || cmd.startsWith("dac")) { + // Команды: d100, dac100, d 100, dac 100 + int value = extractNumber(cmd); + if (value >= 0 && value <= 255) { + setDAC(value); + } else { + Serial.println("❌ Ошибка: значение должно быть 0-255"); + Serial.println(" Пример: d100 или dac150"); + } + } + + // ========== УПРАВЛЕНИЕ ПО БАНКАМ ========== + else if (cmd == "1s") { + setVoltageForCells(1); + } + else if (cmd == "2s") { + setVoltageForCells(2); + } + else if (cmd == "3s") { + setVoltageForCells(3); + } + else if (cmd == "4s") { + setVoltageForCells(4); + } + + // ========== КАЛИБРОВКА ========== + else if (cmd == "cal" || cmd == "calibrate") { + runCalibration(); + } + else if (cmd == "quickcal") { + runQuickCalibration(); + } + + // ========== НАСТРОЙКА ВРЕМЕНИ КАЛИБРОВКИ ========== + else if (cmd.startsWith("delay")) { + int value = extractNumber(cmd); + if (value >= 1 && value <= 30) { + calibration_delay = value; + Serial.print("✅ Задержка калибровки установлена: "); + Serial.print(value); + Serial.println(" секунд"); + } else { + Serial.println("❌ Ошибка: значение должно быть 1-30 секунд"); + Serial.println(" Пример: delay5 или delay10"); + } + } + + // ========== СОХРАНЕНИЕ КАЛИБРОВКИ ========== + else if (cmd.startsWith("save1s")) { + int value = extractNumber(cmd); + if (value >= 0 && value <= 255) { + cal_1s = value; + Serial.print("✅ Сохранено: 1S = DAC "); + Serial.println(value); + } + } + else if (cmd.startsWith("save2s")) { + int value = extractNumber(cmd); + if (value >= 0 && value <= 255) { + cal_2s = value; + Serial.print("✅ Сохранено: 2S = DAC "); + Serial.println(value); + } + } + else if (cmd.startsWith("save3s")) { + int value = extractNumber(cmd); + if (value >= 0 && value <= 255) { + cal_3s = value; + Serial.print("✅ Сохранено: 3S = DAC "); + Serial.println(value); + } + } + else if (cmd.startsWith("save4s")) { + int value = extractNumber(cmd); + if (value >= 0 && value <= 255) { + cal_4s = value; + Serial.print("✅ Сохранено: 4S = DAC "); + Serial.println(value); + } + } + + // ========== ИНФОРМАЦИЯ ========== + else if (cmd == "info" || cmd == "status") { + printStatus(); + } + else if (cmd == "cal_values" || cmd == "cv") { + printCalibrationValues(); + } + + // ========== БЫСТРЫЕ КОМАНДЫ ========== + else if (cmd == "min") { + setDAC(255); + Serial.println("⬇️ Установлено минимальное напряжение (DAC=255)"); + } + else if (cmd == "max") { + setDAC(0); + Serial.println("⬆️ Установлено максимальное напряжение (DAC=0)"); + } + else if (cmd == "mid") { + setDAC(128); + Serial.println("➡️ Установлено среднее значение (DAC=128)"); + } + + // ========== ПОШАГОВОЕ ИЗМЕНЕНИЕ ========== + else if (cmd == "+" || cmd == "up") { + if (current_dac < 255) { + setDAC(current_dac + 1); + Serial.println("⬆️ DAC +1"); + } + } + else if (cmd == "-" || cmd == "down") { + if (current_dac > 0) { + setDAC(current_dac - 1); + Serial.println("⬇️ DAC -1"); + } + } + else if (cmd == "++" || cmd == "up10") { + if (current_dac <= 245) { + setDAC(current_dac + 10); + Serial.println("⬆️ DAC +10"); + } + } + else if (cmd == "--" || cmd == "down10") { + if (current_dac >= 10) { + setDAC(current_dac - 10); + Serial.println("⬇️ DAC -10"); + } + } + + // ========== ПОМОЩЬ ========== + else if (cmd == "help" || cmd == "?" || cmd == "menu") { + printMenu(); + } + + // ========== НЕИЗВЕСТНАЯ КОМАНДА ========== + else { + Serial.println("❌ Неизвестная команда!"); + Serial.println(" Введи 'help' для списка команд"); + } + + Serial.println(); +} + +// ============================================================ +// ФУНКЦИИ УПРАВЛЕНИЯ +// ============================================================ + +void setDAC(uint8_t value) { + dacWrite(DAC_PIN, value); + current_dac = value; + + Serial.println(); + Serial.println("╔═══════════════════════════════════╗"); + Serial.print ("║ DAC установлен: "); + Serial.print(value); + Serial.print(" ("); + Serial.print((value * 100.0) / 255.0, 1); + Serial.println("%) ║"); + Serial.println("╚═══════════════════════════════════╝"); + Serial.println(); + Serial.println("📊 СЕЙЧАС ИЗМЕРЬ НАПРЯЖЕНИЕ НА VOUT-1!"); + Serial.println(" И запиши результат."); +} + +void setVoltageForCells(uint8_t cells) { + uint8_t dac_value; + float target_voltage; + + switch(cells) { + case 1: + dac_value = cal_1s; + target_voltage = 4.2; + break; + case 2: + dac_value = cal_2s; + target_voltage = 8.4; + break; + case 3: + dac_value = cal_3s; + target_voltage = 12.6; + break; + case 4: + dac_value = cal_4s; + target_voltage = 16.8; + break; + default: + Serial.println("❌ Ошибка: недопустимое количество банок!"); + return; + } + + dacWrite(DAC_PIN, dac_value); + current_dac = dac_value; + + Serial.println(); + Serial.println("╔═══════════════════════════════════╗"); + Serial.print ("║ Установлено для "); + Serial.print(cells); + Serial.println("S батареи ║"); + Serial.print ("║ Целевое: "); + Serial.print(target_voltage, 1); + Serial.println("V ║"); + Serial.print ("║ DAC: "); + Serial.print(dac_value); + Serial.println(" ║"); + Serial.println("╚═══════════════════════════════════╝"); + Serial.println(); + Serial.println("📊 Проверь напряжение вольтметром!"); + Serial.print(" Должно быть около "); + Serial.print(target_voltage); + Serial.println("V"); +} + +// ============================================================ +// КАЛИБРОВКА +// ============================================================ + +void runCalibration() { + Serial.println(); + Serial.println("╔═══════════════════════════════════════════╗"); + Serial.println("║ РЕЖИМ ПОЛНОЙ КАЛИБРОВКИ ║"); + Serial.println("╚═══════════════════════════════════════════╝"); + Serial.println(); + Serial.println("⚠️ ПОДГОТОВКА:"); + Serial.println(" 1. Подключи вольтметр к VOUT-1"); + Serial.println(" 2. НЕ подключай нагрузку!"); + Serial.println(" 3. Приготовь ручку и бумагу"); + Serial.println(); + Serial.print("⏱️ Задержка на измерение: "); + Serial.print(calibration_delay); + Serial.println(" секунд"); + Serial.println(" (Изменить: delay5, delay10, delay15 и т.д.)"); + Serial.println(); + Serial.println("📋 Для каждого значения DAC:"); + Serial.print(" - Жди "); + Serial.print(calibration_delay); + Serial.println(" секунд стабилизации"); + Serial.println(" - Измерь напряжение"); + Serial.println(" - Запиши в таблицу"); + Serial.println(); + Serial.println("Нажми ENTER для начала..."); + + // Ждём нажатия Enter + while(Serial.available() == 0) { + delay(100); + } + Serial.readString(); // Очищаем буфер + + Serial.println(); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + Serial.println(" НАЧАЛО КАЛИБРОВКИ"); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + + // Проходим по значениям DAC с шагом 25 + for (int dac_value = 0; dac_value <= 255; dac_value += 25) { + dacWrite(DAC_PIN, dac_value); + + Serial.println(); + Serial.print("┌─ DAC = "); + Serial.print(dac_value); + Serial.println(" ─────────────────────"); + Serial.println("│"); + Serial.print("│ Ожидание "); + Serial.print(calibration_delay); + Serial.print(" сек"); + + // Ждём стабилизации с анимацией + int steps = calibration_delay * 2; // Каждые 0.5 секунды точка + for (int i = 0; i < steps; i++) { + delay(500); + Serial.print("."); + } + + Serial.println(); + Serial.println("│"); + Serial.println("│ 🔔 ЗВУКОВОЙ СИГНАЛ - ИЗМЕРЯЙ СЕЙЧАС!"); + Serial.println("│"); + Serial.println("│ 📊 ИЗМЕРЬ НАПРЯЖЕНИЕ НА VOUT-1!"); + Serial.print("│ Запиши: DAC "); + Serial.print(dac_value); + Serial.println(" = _____ V"); + Serial.println("│"); + + // Дополнительная пауза для записи (3 секунды) + Serial.println("│ (3 сек на запись"); + for (int i = 0; i < 6; i++) { + delay(500); + Serial.print("."); + } + Serial.println(")"); + + Serial.println("└─────────────────────────────────"); + } + + Serial.println(); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + Serial.println("✅ КАЛИБРОВКА ЗАВЕРШЕНА!"); + Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); + Serial.println(); + Serial.println("📋 Теперь найди в таблице значения DAC для:"); + Serial.println(" - 4.2V (1S) → введи: save1s [значение]"); + Serial.println(" - 8.4V (2S) → введи: save2s [значение]"); + Serial.println(" - 12.6V (3S) → введи: save3s [значение]"); + Serial.println(" - 16.8V (4S) → введи: save4s [значение]"); + Serial.println(); + Serial.println("Пример: save1s 150"); + + // Возвращаемся к DAC=0 + dacWrite(DAC_PIN, 0); +} + +void runQuickCalibration() { + Serial.println(); + Serial.println("╔═══════════════════════════════════════════╗"); + Serial.println("║ РЕЖИМ БЫСТРОЙ КАЛИБРОВКИ ║"); + Serial.println("╚═══════════════════════════════════════════╝"); + Serial.println(); + Serial.println("Проверяются только ключевые точки:"); + Serial.println(); + + int key_values[] = {0, 50, 100, 150, 200, 255}; + + for (int i = 0; i < 6; i++) { + int dac_value = key_values[i]; + dacWrite(DAC_PIN, dac_value); + + Serial.print("DAC = "); + Serial.print(dac_value); + Serial.print(" → Измерь напряжение"); + + for (int j = 0; j < 4; j++) { + delay(500); + Serial.print("."); + } + Serial.println(" СЕЙЧАС!"); + delay(2000); + } + + Serial.println(); + Serial.println("✅ Быстрая калибровка завершена!"); + dacWrite(DAC_PIN, 0); +} + +// ============================================================ +// ИНФОРМАЦИЯ И МЕНЮ +// ============================================================ + +void printWelcome() { + Serial.println(); + Serial.println("╔═════════════════════════════════════════════════╗"); + Serial.println("║ ║"); + Serial.println("║ XL4015 + ESP32 DAC ТЕСТОВЫЙ СКЕТЧ ║"); + Serial.println("║ Управление зарядным устройством ║"); + Serial.println("║ ║"); + Serial.println("╚═════════════════════════════════════════════════╝"); + Serial.println(); + Serial.println("✅ Система готова к работе!"); + Serial.println("📌 GPIO25 (DAC1) подключен к FB через 470Ω"); + Serial.println("⚡ Напряжение DAC: 0-3.3V (0-255 в коде)"); + Serial.println(); +} + +void printMenu() { + Serial.println(); + Serial.println("╔═══════════════════════════════════════════════════╗"); + Serial.println("║ СПИСОК КОМАНД ║"); + Serial.println("╠═══════════════════════════════════════════════════╣"); + Serial.println("║ ПРЯМОЕ УПРАВЛЕНИЕ DAC: ║"); + Serial.println("║ d[число] Установить DAC (0-255) ║"); + Serial.println("║ Примеры: d100, dac150, d 200 ║"); + Serial.println("║ min DAC = 255 (минимум VOUT) ║"); + Serial.println("║ max DAC = 0 (максимум VOUT) ║"); + Serial.println("║ mid DAC = 128 (среднее) ║"); + Serial.println("║ + / up DAC +1 ║"); + Serial.println("║ - / down DAC -1 ║"); + Serial.println("║ ++ / up10 DAC +10 ║"); + Serial.println("║ -- / down10 DAC -10 ║"); + Serial.println("╠═══════════════════════════════════════════════════╣"); + Serial.println("║ УПРАВЛЕНИЕ ПО БАНКАМ: ║"); + Serial.println("║ 1s 4.2V (1S батарея) ║"); + Serial.println("║ 2s 8.4V (2S батарея) ║"); + Serial.println("║ 3s 12.6V (3S батарея) ║"); + Serial.println("║ 4s 16.8V (4S батарея) ║"); + Serial.println("╠═══════════════════════════════════════════════════╣"); + Serial.println("║ КАЛИБРОВКА: ║"); + Serial.println("║ cal Полная калибровка (0-255, шаг 25)║"); + Serial.println("║ quickcal Быстрая калибровка (6 точек) ║"); + Serial.println("║ save1s [N] Сохранить DAC для 1S (4.2V) ║"); + Serial.println("║ save2s [N] Сохранить DAC для 2S (8.4V) ║"); + Serial.println("║ save3s [N] Сохранить DAC для 3S (12.6V) ║"); + Serial.println("║ save4s [N] Сохранить DAC для 4S (16.8V) ║"); + Serial.println("║ Пример: save1s 150 ║"); + Serial.println("╠═══════════════════════════════════════════════════╣"); + Serial.println("║ ИНФОРМАЦИЯ: ║"); + Serial.println("║ info Текущий статус ║"); + Serial.println("║ cv Значения калибровки ║"); + Serial.println("║ help Показать это меню ║"); + Serial.println("╚═══════════════════════════════════════════════════╝"); + Serial.println(); + Serial.println("💡 Начни с команды 'cal' для калибровки!"); + Serial.println(); +} + +void printStatus() { + Serial.println(); + Serial.println("╔═══════════════════════════════════╗"); + Serial.println("║ ТЕКУЩИЙ СТАТУС ║"); + Serial.println("╠═══════════════════════════════════╣"); + Serial.print ("║ DAC значение: "); + Serial.print(current_dac); + Serial.print(" ("); + Serial.print((current_dac * 100.0) / 255.0, 1); + Serial.println("%) ║"); + Serial.print ("║ DAC напряжение: "); + Serial.print((current_dac * 3.3) / 255.0, 2); + Serial.println("V ║"); + Serial.println("╚═══════════════════════════════════╝"); + Serial.println(); +} + +void printCalibrationValues() { + Serial.println(); + Serial.println("╔═══════════════════════════════════════╗"); + Serial.println("║ КАЛИБРОВОЧНЫЕ ЗНАЧЕНИЯ ║"); + Serial.println("╠═══════════════════════════════════════╣"); + Serial.print ("║ 1S (4.2V): DAC = "); + Serial.print(cal_1s); + Serial.println(" ║"); + Serial.print ("║ 2S (8.4V): DAC = "); + Serial.print(cal_2s); + Serial.println(" ║"); + Serial.print ("║ 3S (12.6V): DAC = "); + Serial.print(cal_3s); + Serial.println(" ║"); + Serial.print ("║ 4S (16.8V): DAC = "); + Serial.print(cal_4s); + Serial.println(" ║"); + Serial.println("╚═══════════════════════════════════════╝"); + Serial.println(); + Serial.println("Для изменения используй команды:"); + Serial.println(" save1s [число], save2s [число], и т.д."); + Serial.println(); +} + +// ============================================================ +// ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ +// ============================================================ + +int extractNumber(String str) { + // Убираем все не-цифры в начале + int startIndex = 0; + while (startIndex < str.length() && !isDigit(str[startIndex])) { + startIndex++; + } + + // Извлекаем число + String numberStr = str.substring(startIndex); + numberStr.trim(); + + if (numberStr.length() > 0) { + return numberStr.toInt(); + } + return -1; // Ошибка +} \ No newline at end of file