Авторизация
Регистрация

Напомнить пароль

UPS для WiFi своими руками

Свет по-прежнему периодически пропадает. И хотя старый самодельный UPS на 9 вольт выходного напряжения и с питанием от БП ноутбука для WiFi ещё работает. Но вот аккумулятор на 12 вольт 7 ампер-часов уже подустал, а новый покупать неохота. Да и схема на операционнике не всем моим хотелкам уже отвечает.

Посмотрел описания и отзывы по китайским модулям для создания UPS для WiFi. Картина грустная. Настроить гистерезис включения – отключения зарядки аккумулятора нельзя. Настроить нижний порог, при котором батарея отключается от нагрузки, тоже нельзя. Индикация скромненькая. Нарастить ёмкость батареи – проблема.


Зато есть несколько банок 18650 после ремонта друзьям батареи самоката. И есть кучка ATtiny13.
Поэтому решил попробовать сделать новый UPS для своего WiFi под следующие требования:
— использование батареи 3S на 18650;
— возможность запрограммировать зарядный ток и перепрограммировать его при необходимости;
— использование схемы зарядки CC-CV;
— отключение от заряда полностью заряженного аккумулятора;
— возможность запрограммировать порог напряжения для аккумулятора, при снижении до которого, вновь включится зарядка;
— возможность задать минимальный ток, при снижении до которого при напряжении 12,6 вольт, будет отключаться заряд аккумулятора;
— контроль нижнего порога напряжения, считающегося нижним пределом для аккумулятора и при котором будет отключаться нагрузка и выдаваться сигнал аварии (красный светодиод);
— автоматически возвращаться из режима аварии и переход на зарядку, после появления сетевого питания;
— плавное нарастание тока при старте заряда аккумулятора для более бережного отношения к аккумулятору;
— возможность использования подуставших аккумуляторов, которые не способны зарядиться до 12,6 вольт (до 4,2 на элемент) и по которым нужно принимать решение о прекращении зарядки по другим критериям;
— возможность использования в качестве источника питания, блока питания от ноутбука, который использовался и в старом UPS;
— индикация режима зарядам (желтый светодиод);
— индикация питания от сети (синий светодиод);
— индикация уровня заряда аккумулятора;
— мгновенный переход на питание от батареи и обратно без задержки;
— защита от переполюсовки аккумулятора;
— возможность полностью отключить тумблером аккумулятор от схемы при разряде до аварийного уровня или при долгом отсутствии дома, чтобы не разряжался его даже малым током потребления контроллера.

Из-за выбранного варианта индикации, обнаружилась проблема нехватки выводов ATtiny13. Два вывода нужно для контроля напряжения и тока. Один для контроля напряжения питания. Один для управления выходным DC-DC преобразователем. И один для управления с помощью ШИМ сигнала DC-DC преобразователя, который и будет регулировать ток заряда аккумулятора от блока питания ноутбука.
И получилось, что индицировать включение заряда ещё одной ножки не хватает.
Пришлось добавить детектор на диоде конденсаторе и транзисторе, который включит светодиод при появлении на выходе PB0 ШИМ сигнала.
В результате получилась вот такая схема:



Прошивка создавалась на Arduino IDE 1.8.19. Уложилась в 820 байт. Частота контроллера 9,6 МГц. Опорное напряжение от внутреннего источника 1,1 вольт. По факту оказалось 1,071363 вольт.
Поэтому для точности измерений, желательно проверить уровень опорного в своём контроллере. Ну, или просто подстроить коэффициенты методом проб и ошибок.

Т.к. резисторы у меня не прецизионные, то добавлен подстроечник в делитель напряжения для измерения напряжения батареи. С его помощью при отсутствии сетевого питания были установлены одинаковые уровни напряжения на ножках контроллера PB2 и PB3.
У меня контроллер установлен в панельку, поэтому проблем с перепрошивкой при отладке не возникало.

При желании получить другое выходное напряжение, меняется выходной DC-DC преобразователь на другое напряжение.
Если есть желание получить другой ток заряда, то нужно пересчитать. Принцип расчёта описан в скетче.
В скетче приведено описание вообще всех параметров и расчётов для работы программы.

Сейчас UPS используется со сборкой 3S2P банок 18650 по 2000 миллиампер-часов каждая. Этого должно хватать часов на 10 работы WiFi. При необходимости увеличить время работы, просто добавляется число банок — 3S3P или 3S4P и/или ставятся более ёмкие аккумуляторы.

Код скетча:

/****************************************************************************************
* Программа для ATtiny13 для UPS на трёх последовательных 18650, питающего WiFi на 9 вольт 
* Для вариантов на 6 или 5 вольт, достаточно поменять версию Mini560 на соответствующее напряжение
* Скетч использует 820 байт (80%) памяти устройства. Всего доступно 1024 байт.
* Глобальные переменные используют 15 байт (23%) динамической памяти, оставляя 49 байт для локальных переменных. Максимум: 64 байт.
*
*
*  Принципы работы:
*   - Контролируем напряжение на АКБ (из трёх 18650 с BMS платой) и ток через шунт 1 Ом (1 Ватт) включенный между выходом DC-DC и АКБ
*   - Зарядный ток в программе ограничен на уровне 1,6 А. Если для вашей батареи этого мало, просто уменьшите шунт. При 0,5 Ом ток будет ограничен на уровне 3,2 А.
*   - При достижении 12,6 В (4,2 на элемент 18650) и снижении тока до 0,16 А, ШИМ отключаем и устанавливается целевое напряжение 11,7 В (3,9 В на элемент 18650)
*   - При снижении напряжения на аккумуляторе до уровня 11,7 В, снова включатся ШИМ для зарядки от БП
*   - Если ток при 12,6 В не упадёт до 0,16 А, но ШИМ дойдёт до минимального значения, то также завершаем зарядку.
*   - При снижении напряжения аккумулятора ниже 10,2 В (3,4 на элемент 18650) поднимается флаг аварии, зажигается светодиод аварии, отключается ШИМ и нагрузка.
*   - При появлении внешнего питания запустится ШИМ в штатном режиме - плавный рост ШИМ, начиная с уровня 12 на выходе PB0.
*   - Максимальный уровень ШИМ ограничен величиной 200. Это обеспечивает ток около 2 А при напряжении блока питания 19 вольт.
*   - Также считаем заряд оконченным, если напряжение на аккумуляторе не растёт больше 30 минут хотя бы на 0,035 В.
*   - Это бывает у приуставших аккумуляторах.
*   - В этом случае, также отключается заряд и поднимается флаг "АКБ заряжен"
*   - Желтый светодиод показывают когда батарея заряжается (ШИМ работает).
*   - Он подключен не к отдельной ножке контроллера, а к детектору импульсов на выходе ШИМ (РВ1)
*
*   = Частота контроллера 9,6 МГц.
*   = Образцовое напряжение задано внутренним источником 1,1 В (реально на моём экземпляре ATtiny13 опорное 1,071363 В)
*   = Частота ШИМ = 37,5 кГц
*   = Цена одного разряда АЦП = 0,001074 В (это в идеале, а в моём контроллере 0,001046 - видимо вместо 1,1 В в моём ATTiny13 пороговое 1,071363 В).
*   - Для точности - измеряем напряжение 16 раз и складываем значения.
*   - После этого не делим сумму 16 замеров на 16, а используем как есть, сравнивая её с контрольными напряжениями на шунте и блоке питания умноженными на 16
*   - Измерение напряжений на шунте производится через делитель напряжения 15 кОм и 1 кОм. (точнее 975 Ом - постоянный 910 Ом и подстроечник на 100 Ом).
*   Подстроечником выравнивал напряжение на обоих делителях - до шунта и после. Разница на делителях 0,001 В.
*   Контрольные напряжения:
*   - контролируемое значение при полном заряде - 12,6 В -> 0,762 на делителе -> 0,762 / 0,001046 * 16 = 11656
*   - контролируемое значение порога повторного включения - 11,7 В -> 0,708 на делителе -> 0,708 / 0,001046 * 16 = 10830
*   - контролируемое значение порога отключения нагрузки - 10,2 В -> 0,617 на делителе -> 0,617 / 0,001046 * 16 = 9438
*   - нижний порог включения при подключении аккумулятора - 7,5 В (три элемента 18650 по 2,5 В) -> 0,453 на делителе -> 0,453 / 0,001046 * 16 = 6929
*   Ток рассчитываем по разнице напряжений до шунта и после.
*   - для тока 1,6 А получим контрольное значение (разницу напряжений до и после шунта) -> 1,6 В / 16,53 = 0,09679 В / 0,001046  = 92,537 * 16 = 1480
*   - для тока 0,16 А получим контрольное значение (разницу напряжений до и после шунта) -> 0,16 В / 16,53 = 0,009679 / 0,001046 = 9,2537 * 16 = 148
*   - контроль прироста напряжение за 30 минут менее, чем на 0,035 В, при котором также считаем заряд оконченным -> 0,035 / 0,001046 * 16 = 32
*   Максимально можно измерить с таким делителем до переполнения АЦП -> 17,7 В
*   - Если не подключена батарея, то система отключает ШИМ и выходит в состояние "Зарядка завершена" по превышению напряжения 13,24 В на аккумуляторе.
*   - При подключении аккумулятора снова, система переходит в режим заряда. 
*
*   Контроль напряжения питания (19 В) контролируем через делитель 20 кОм и 1 кОм.
*   Если на входе нет напряжения выше 15 вольт, то отключаем заряд аккумулятора.
*	
*******************************************************************************************/


#include <avr/io.h>
#include <util/delay.h>

// Номера каналов АЦП (соответствуют физической разводке пинов ATtiny13)
#define ADC_BEFORE_SHUNT 3 						// PB3 (ADC3) - Напряжение до шунта
#define ADC_AFTER_SHUNT  1 						// PB2 (ADC1) - Напряжение после шунта (АКБ)
#define ADC_19V          2 						// PB4 (ADC2) - Контроль сети питания 19В (через делитель 20к/1к)

#define PB1_MINI560      1 						// PB1 - Выход управления EN платы MINI560
#define PB0_PWM          0 						// PB0 - ШИМ управления затвором мосфета

#define PWM_MAX        200 						// Максимально допустимое значение ШИМ - около 2 А
#define PWM_MIN        20  						// Минимально допустимое значение ШИМ - после которого принимаем решение об отключении ШИМ
#define PWM_START      160 						// Начальное значение ШИМ при заряде - около 0,3 А

// Целевые константы для 16 накопленных замеров (опорное 1.1В)
const uint16_t VOLTAGE_LOW_15V = 10630; 		// Порог наличия сети (15 В при делителе 20к/1к)
const uint16_t CURRENT_1_6A    = 1500;  		// Ток стабилизации (1.6 А) - чуть округлил от 1480 расчётных
const uint16_t CURRENT_0_16A   = 150;   		// Ток окончания заряда (0.16 А) - чуть округлил от 148 расчётных
const uint16_t VOLTAGE_12_6V   = 11656; 		// Порог ограничения напряжения (12.6 В)
const uint16_t VOLTAGE_11_7V   = 10830; 		// Порог повторного включения (12.6 - 0.9 = 11.7 В => 3,9 В на элемент 18650)
const uint16_t VOLTAGE_10_2V   = 9438;  		// Порог аварийного отключения MINI560 (10.2 В => 3,4 В на элемент 18650)
const uint16_t VOLTAGE_7_5V    = 6929;  		// Нижний порог включения при возврате аккумулятора (7.5 В)
const uint16_t VOLTAGE_0_01V   = 32;    		// Порог минимального прироста напряжения (0.035 В)
const uint16_t VOLTAGE_NO_BATT = 12250; 		// Порог повышенного напряжения (свыше 13,24 В на клеммах, АКБ отключен)



int16_t pwm_out = 0;                    		// Текущая скважность ШИМ

// Логические флаги состояний системы
bool is_charging     = true;            		// Идет процесс зарядки (CC или CV)
bool is_charged      = false;           		// Батарея полностью заряжена, ШИМ выключен
bool was_power_lost  = false;           		// Флаг: была потеряна сеть
bool no_battery_mode = false;           		// Флаг: аккумулятор физически отключен

uint16_t step_timer = 0;                		// Таймер для замедления шагов регулирования тока (до 100 мс)
uint32_t degradation_timer = 0;         		// Таймер для контроля «уставших» АКБ (30 минут)
uint16_t last_saved_voltage = 0;        		// Переменная хранения прошлого значения напряжения

// Сбор 16 замеров АЦП БЕЗ деления для повышения точности
uint16_t read_adc_16 (uint8_t channel) 
{
    uint16_t sum = 0;
    ADMUX = (1 << REFS0) | (channel & 0x03);    // Сохраняем внутреннее опорное 1.1В
    _delay_us(20);                              // Пауза для стабилизации мультиплексора АЦП

    for (uint8_t i = 0; i < 16; i++) 
	{
        ADCSRA |= (1 << ADSC);                  // Запуск преобразования
        while (ADCSRA & (1 << ADSC));           // Ожидание окончания замера
        sum += ADC;                             // Накапливаем сумму 16 замеров
    }
    return sum;                                 // Возврат полученной суммы
}

// Полное аппаратное отключение ШИМ (железобетонный стоп генерации)
void shutdown_pwm() 
{
    TCCR0B &= ~(1 << CS00);                     // СТОП ТАЙМЕР: убираем тактирование (No clock)
    TCCR0A &= ~((1 << COM0A1) | (1 << COM0A0)); // Отвязываем таймер от пина PB0
    PORTB &= ~(1 << PB0_PWM);                   // Жестко прижимаем затвор к земле (0 Вольт)
    OCR0A = 0;                                  // Сбрасываем регистр сравнения
}

// Аппаратное включение ШИМ
void start_pwm() 
{
    TCCR0A |= (1 << COM0A1);                    // Подключаем ШИМ к пину PB0
    TCCR0B |= (1 << CS00);                      // ЗАПУСК ТАЙМЕРА: тактирование напрямую (37.5 кГц при 9.6 МГц)
}


// ========================================================
// НАЧАЛЬНАЯ УСТАНОВКА
// ========================================================

void setup() 
{
    DDRB |= (1 << PB0_PWM);                      // Настраиваем PB0 на выход (ШИМ мосфета)
    
    // Инициализация PB1 под активное управление MINI560 (резистор 1.5 кОм на землю)
    DDRB |= (1 << PB1_MINI560);                  // Порт РВ1 переключить на выход
    PORTB |= (1 << PB1_MINI560);                 // Выдаем логическую 1 (5 В) — принудительно ВКЛЮЧАЕМ MINI560
    
    // Режим Fast PWM 8-bit (WGM01=1, WGM00=1), запуск тактирования таймера
    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    TCCR0B |= (1 << CS00);
    
    // Включение АЦП, выбор предделителя частоты 64 (частота АЦП 150 кГц при тактовой 9.6 МГц)
    ADMUX = (1 << REFS0);
    ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);

    _delay_ms(50);
    last_saved_voltage = read_adc_16(ADC_AFTER_SHUNT); // Базовая точка отсчета напряжения
    pwm_out = PWM_MIN;                           // Стартовое значение для мягкого пуска ШИМ
}

void loop() 
{
    // === МОНИТОРИНГ СЕТИ (каждые 10 мс)
    uint16_t val_net = read_adc_16(ADC_19V); 
    bool power_present = (val_net >= VOLTAGE_LOW_15V); 

    // ================================================================================================
    // РЕЖИМ А: СЕТИ НЕТ (РАБОТА НАГРУЗКИ ОТ АККУМУЛЯТОРА) - крутимся в этом цикле до появления питания
    // ================================================================================================
    if (!power_present)                          // Если нет питания
	{
        shutdown_pwm();              		     // Мгновенно тушим ШИМ зарядки (стоп таймера)
        was_power_lost = true;       		     // Взводим флаг: сеть пропадала

        uint16_t adc_after = read_adc_16(ADC_AFTER_SHUNT); // Измеряем батарею в разряде
        
        // Защита лития от глубокого разряда: если напряжение упало ниже 10.2 В
        if (adc_after <= VOLTAGE_10_2V) 
		{
            PORTB &= ~(1 << PB1_MINI560); 	     // Выводим 0 В на вывод EN MINI560 - отключаем от аккумулятора нагрузку
                                                 // Резистор 1.5к досадит MINI560 до нуля и погасит MINI560
        }
        
        _delay_ms(10); 
        return; 							     // Прерываем loop(), возвращаемся в начало на проверку сети
    }

    // ========================================================
    // РЕЖИМ Б: СЕТЬ ЕСТЬ (АКТИВНАЯ РАБОТА И ЗАРЯДКА)
    // ========================================================
    
    // Сценарий восстановления: если сеть ТОЛЬКО ЧТО вернулась после аварии
    if (was_power_lost)              			// Если было пропадание сети
	{
        PORTB |= (1 << PB1_MINI560); 			// Гарантированно включаем MINI560 (5 В на выходе РВ1)
		
		// Ждем 300 мс, чтобы MINI560 запустился, а переходные напряжения на входе выровнялись
        _delay_ms(300);
		
        was_power_lost = false;      			// Сбрасываем флаг Сеть пропадала
        no_battery_mode = false;     			// Сбрасываем флаг отсутствия батареи
        is_charging = true;          			// Сбрасываем автоматику в режим новой плавной зарядки
        is_charged = false;
        pwm_out = PWM_START;         			// Откатываем ШИМ на безопасный минимум
        step_timer = 0;	             			// Сбрасываем таймер шагов (каждый шаг - 10 мс - продолжительность цикла)
        degradation_timer = 0;       			// Сбрасываем таймер 30 минут ожидания роста напряжения
        
		uint16_t temp_after  = read_adc_16(ADC_AFTER_SHUNT);
        last_saved_voltage = temp_after; 
        return;

    }
	
	// Считываем датчик на клеммах аккумулятора
    uint16_t adc_after = read_adc_16(ADC_AFTER_SHUNT); 

    // --- ПРОВЕРКА ЗАЩИТЫ: ОПРЕДЕЛЕНИЕ ОТСУТСТВИЯ АККУМУЛЯТОРА ---
    if (adc_after >= VOLTAGE_NO_BATT)       	// Если напряжение на батарее больше 12,9 В (батареи нет - напряжение подскочило)
	{
        shutdown_pwm();                     	// Мгновенно выключаем ШИМ
        no_battery_mode = true;             	// Переходим в специальный защитный режим
        is_charging = false;                	// Отключаем разрешение зарядки
        is_charged = false;                 	// Опускаем флаг Батарея заряжена
    }
	
	// ========================================================
    // ОБРАБОТКА ВЕТОК СОСТОЯНИЙ (ПРИ НАЛИЧИИ СЕТИ)
    // ========================================================
	
	// --- ПОДРЕЖИМ Б.0: ОЖИДАНИЕ ПОДКЛЮЧЕНИЯ АККУМУЛЯТОРА ---
    if (no_battery_mode)                     	// Если нет батареи
	{
        shutdown_pwm();                      	// ШИМ выключен
        PORTB |= (1 << PB1_MINI560);         	// MINI560 включен и работает напрямую от сети 19 В
        
        // Выходим из защиты, только если на клеммах появилось адекватное напряжение батареи
        // (меньше порога перезапуска 12.6В, но выше 7,5 В - три батареи по 2,5 В - меньше нет смысла ставить - это мёртвые батареи)
        if (adc_after < VOLTAGE_12_6V && adc_after > VOLTAGE_7_5V) 
		{
            no_battery_mode = false;          	// Сбросить флаг отсутствия батареи
            is_charging = true;               	// Разрешаем зарядку подключенного АКБ
            pwm_out = PWM_START;              	// Плавный пуск с минимального значения ШИМ
            step_timer = 0;                   	// Сброс счётчика шагов
            degradation_timer = 0;            	// Сброс таймера 30 минут
            last_saved_voltage = adc_after;   	// Пересохранить свежее значение напряжение на батарее
        }
        _delay_ms(10);
        return;                               	// Пропускаем остальной код зарядки, пока АКБ не подключен
    }

    // Считываем напряжение до и после шунта
    uint16_t adc_before = read_adc_16(ADC_BEFORE_SHUNT);
    //uint16_t adc_after  = read_adc_16(ADC_AFTER_SHUNT); 
    
    // Вычисляем ток как знаковую разность (убирает ловушку нулевого тока)
    int16_t current_current = (int16_t)adc_before - (int16_t)adc_after;  // Вычисляем падение напряжения на шунте
    if (current_current < 0) current_current = 0;                        // Отрезаем отрицательные шумы

    // --- ПОДРЕЖИМ Б.1: ИДЕТ АКТИВНАЯ ЗАРЯДКА АКБ ---
    if (is_charging)                        	// Если есть разрешение на заряд батареи
	{
        PORTB |= (1 << PB1_MINI560);        	// Включаем МИНИ560 (1 на порт РВ1)
        
        OCR0A = (uint8_t)pwm_out;           	// Выдаём pwm_out в ШИМ порт
        start_pwm(); 							// Включить ШИМ

        step_timer++;                       	// Увеличиваем счётчик шагов
        if (step_timer >= 10)               	// Если прошло 10 шагов - заходим сюда через каждые 0,1 сек.
		{ 
            step_timer = 0;                 	// Сбрасываем в ноль счётчик шагов

            // Приоритет 1: Защита от перезаряда 12.6В (CV)
            if (adc_after >= VOLTAGE_12_6V) 	// Если напряжение на аккумуляторе больше или равно 12,6 В
			{
                if (pwm_out > PWM_MIN)      	// ... и ШИМ больше минимально допустимого значения, то ...
					pwm_out--;           		// ... уменьшить переменную ШИМ
            }
            // Приоритет 2: Стабилизация тока на уровне 1.0 А (CC)
            else                            	// Если ещё не достигли 12,6 В
			{
                // Если реальный ток меньше целевого 1А (931 единица)
                if ((uint16_t)current_current < CURRENT_1_6A)   // Если падение напряжения на шунте меньше 1 А
				{
                    if (pwm_out < PWM_MAX)  	// Если не превышен максимально разрешенный уровень ШИМ			
						pwm_out++;       		// Увеличиваем ШИМ
                } 
                // Если ток превысил целевой 1А
                else if ((uint16_t)current_current > (CURRENT_1_6A + 30)) 
				{
                    if (pwm_out > PWM_MIN)  	// Если не достигли минимально разрешенного уровня ШИМ
						pwm_out--;       		// Уменьшаем ШИМ
                }
            }
        }

        // Критерий окончания №1: Ток упал до 0.12 А при зафиксированном CV напряжении 12.6 В
		// ИЛИ скважность ШИМ опустилась до самого минимума (качать больше некуда) — переходим в отключение
		if (adc_after >= VOLTAGE_12_6V && ((uint16_t)current_current <= (CURRENT_0_16A) || pwm_out <= PWM_MIN))
        //if (adc_after >= VOLTAGE_12_6V && current_current <= CURRENT_0_16A) 
		{
            shutdown_pwm();               		// Отключаем ШИМ
            is_charging = false;          		// Сбрасываем флаг разрешения заряда
            is_charged = true;            		// Поднимаем флаг окончания заряда
            degradation_timer = 0;        		// Сбрасываем таймер 30 минут без роста напряжения
			pwm_out = 0;                  		// Сбрасываем память ШИМ
        }
        
        // Критерий окончания №2: Контроль стареющих аккумуляторов (+0.01 В за 30 минут)
        degradation_timer++;              		// Увеличиваем таймер 30 минут без роста напряжения
        if (degradation_timer >= 180000)  		// Если прошло 180000 шагов по 10 мс = ровно 30 минут
		{
            degradation_timer = 0;        		// Сбрасываем таймер 30 минут без роста напряжения
			
            // Если дельта роста напряжения меньше 9 единиц виртуального АЦП (0.01 В)
            if (last_saved_voltage > 0 && (adc_after - last_saved_voltage) < VOLTAGE_0_01V)  
			{
                shutdown_pwm();           		// Отключаем ШИМ
                is_charging = false;      		// Сбрасываем флаг разрешения заряда
                is_charged = true;        		// Отсекаем заряд по деградации
				pwm_out = 0;              		// Сбрасываем память ШИМ
            }
            last_saved_voltage = adc_after; 	// Обновляем контрольную точку
        }
    }
    
    // --- ПОДРЕЖИМ Б.2: БАТАРЕЯ ЗАРЯЖЕНА (РЕЖИМ ОЖИДАНИЯ СЕТИ) ---
    else if (is_charged)                   		// Если есть флаг Батарея заряжена
	{
        shutdown_pwm();                    		// Выключаем ШИМ (0 В на РВ0)
        PORTB |= (1 << PB1_MINI560);       		// На РВ1 выдать 1 - MINI560 работает штатно, питая потребителей напрямую от сети 19 В
        
        // Критерий возобновления заряда: естественный саморазряд батареи на 0.9 В (до 11.7 В)
        if (adc_after <= VOLTAGE_11_7V)    		// Если напряжение на аккумуляторе меньше 11,7 В, то ...
		{
            pwm_out = PWM_START;             	// Включаем ШИМ со стартовым значением - перезапуск заряда
            is_charging = true;            		// Поднимаем флаг разрешения заряда
            is_charged = false;            		// Сбрасываем флаг окончания заряда
        }
    }

    // ПРИМЕЧАНИЕ: Для тестов в Proteus оставьте задержку 10 мс. Для готового физического железа
    // её можно увеличить до 50-100 мс, чтобы дополнительно снизить энергопотребление АЦП.
    _delay_ms(10); 
}




Добавить в избранное
+8 +10
свернутьразвернуть
Комментарии (1)
RSS
+
avatar
0
  • virus_59
  • 21 октября 2026, 01:36
Если подразумевается сборка из различных/старых элементов, то я бы добавил контроль напряжения в каждом блоке 3S и возможно, балансировку.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.