Нужен ПИД регулятор для управления лампой накаливания 300 Ватт и
фоторезистором для поддержания заданного уровня освещённости в
комнате с окном. Используем Cortex M0+ микроконтроллер.
memento mori
Я разработал код ПИД-регулятора для управления лампой накаливания 300 Вт с использованием фоторезистора в качестве обратной связи для микроконтроллера Cortex M0+.
Вот ключевые особенности реализации:
- Структура ПИД-регулятора включает:
- Настраиваемые коэффициенты Kp, Ki, Kd
- Защиту от интегрального насыщения (anti-windup)
- Ограничение выходных значений
- Обработка сигнала фоторезистора:
- Усреднение нескольких измерений для уменьшения шума
- Преобразование сырых значений АЦП в проценты освещенности
- Возможность калибровки минимальных и максимальных значений
- Управление лампой:
- Реализовано через PWM (для симистора/диммера)
- Масштабирование выходного сигнала для управления мощностью лампы
- Дополнительные функции:
- Инициализация регулятора с настраиваемыми параметрами
- Установка целевого уровня освещенности
- Основной цикл работы с периодом 100 мс
Для адаптации под ваше конкретное оборудование потребуется:
- Реализовать функции чтения АЦП для фоторезистора
- Настроить управление мощностью лампы (через симистор или реле)
- Откалибровать параметры регулятора (Kp, Ki, Kd) экспериментально для вашей комнаты
- Определить минимальные и максимальные значения освещенности
Обратите внимание на возможность изменения скорости реакции системы через настройку параметров ПИД-регулятора, что позволит адаптировать его к различным условиям естественного освещения.
/**
* ПИД-регулятор для управления лампой накаливания 300 Вт
* с обратной связью через фоторезистор для поддержания
* заданного уровня освещенности в комнате с окном.
*
* Микроконтроллер: Cortex M0+
*/
... include <stdint.h>
... include <stdbool.h>
// Конфигурация пинов (необходимо настроить под конкретную плату)
... define PHOTO_SENSOR_PIN 0 // Пин для фоторезистора (АЦП)
... define LAMP_CONTROL_PIN 1 // Пин для управления симистором/реле/диммером
// Настройки АЦП
... define ADC_MAX_VALUE 4095 // 12-бит АЦП
... define SENSOR_SAMPLES 5 // Количество измерений для усреднения
// Параметры ПИД-регулятора
typedef struct {
float kp; // Пропорциональный коэффициент
float ki; // Интегральный коэффициент
float kd; // Дифференциальный коэффициент
float min_output; // Минимальное значение выхода
float max_output; // Максимальное значение выхода
float setpoint; // Заданное значение
float integral; // Интегральная составляющая
float prev_error; // Предыдущая ошибка (для дифф. составляющей)
float prev_input; // Предыдущее значение входа
bool anti_windup; // Флаг защиты от интегрального насыщения
} PIDController_t;
// Инициализация ПИД-регулятора с начальными параметрами
void PID_Init(PIDController_t *pid, float kp, float ki, float kd, float min, float max) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->min_output = min;
pid->max_output = max;
pid->setpoint = 0.0f;
pid->integral = 0.0f;
pid->prev_error = 0.0f;
pid->prev_input = 0.0f;
pid->anti_windup = true;
}
// Установка заданного значения (уровня освещенности)
void PID_SetTarget(PIDController_t *pid, float setpoint) {
pid->setpoint = setpoint;
}
// Вычисление выхода ПИД-регулятора
float PID_Compute(PIDController_t *pid, float input, float dt) {
// Вычисление ошибки
float error = pid->setpoint - input;
// Пропорциональная составляющая
float p_term = pid->kp * error;
// Интегральная составляющая с защитой от насыщения
pid->integral += pid->ki * error * dt;
// Дифференциальная составляющая (по входному значению)
// Это лучше, чем по ошибке, т.к. исключает резкие изменения
// при изменении уставки
float d_term = pid->kd * (input - pid->prev_input) / dt;
pid->prev_input = input;
// Суммирование всех составляющих
float output = p_term + pid->integral - d_term;
// Ограничение выходного значения
if (output > pid->max_output) {
output = pid->max_output;
// Защита от интегрального насыщения
if (pid->anti_windup && error > 0) {
pid->integral -= pid->ki * error * dt;
}
} else if (output < pid->min_output) {
output = pid->min_output;
// Защита от интегрального насыщения
if (pid->anti_windup && error < 0) {
pid->integral -= pid->ki * error * dt;
}
}
pid->prev_error = error;
return output;
}
// Чтение значения с фоторезистора с фильтрацией
uint16_t ReadLightSensor(void) {
uint32_t sum = 0;
// Считываем несколько значений и усредняем для фильтрации шума
for (int i = 0; i < SENSOR_SAMPLES; i++) {
sum += ReadADC(PHOTO_SENSOR_PIN); // Функция чтения АЦП (необходимо реализовать)
}
return (uint16_t)(sum / SENSOR_SAMPLES);
}
// Функция управления яркостью лампы через PWM или другой метод
void SetLampBrightness(float brightness_percent) {
// Ограничиваем значение от 0 до 100%
if (brightness_percent < 0.0f) brightness_percent = 0.0f;
if (brightness_percent > 100.0f) brightness_percent = 100.0f;
// Преобразуем проценты в значение PWM (0-255 для 8-бит PWM)
uint8_t pwm_value = (uint8_t)(brightness_percent * 2.55f);
// Установка значения PWM (необходимо реализовать)
SetPWM(LAMP_CONTROL_PIN, pwm_value);
}
// Главная функция управления освещением
void LightControlTask(void) {
static PIDController_t pid;
static bool initialized = false;
// Инициализация при первом запуске
if (!initialized) {
// Начальные коэффициенты ПИД (требуется подстройка)
PID_Init(&pid, 0.5f, 0.2f, 0.1f, 0.0f, 100.0f);
// Установка целевого уровня освещенности (0-100%)
// Значение необходимо откалибровать на основе показаний АЦП
PID_SetTarget(&pid, 50.0f);
initialized = true;
}
// Получаем текущий уровень освещенности
uint16_t raw_light = ReadLightSensor();
// Преобразуем сырое значение АЦП в проценты освещенности
// Необходима калибровка для определения min_light и max_light
const uint16_t min_light = 500; // Показания АЦП при минимальной освещенности
const uint16_t max_light = 3800; // Показания АЦП при максимальной освещенности
float current_light_percent;
// Проверка граничных условий
if (raw_light <= min_light) {
current_light_percent = 0.0f;
} else if (raw_light >= max_light) {
current_light_percent = 100.0f;
} else {
// Линейное преобразование
current_light_percent = (float)(raw_light - min_light) / (max_light - min_light) * 100.0f;
}
// Вызов ПИД-регулятора (dt = время между вызовами в секундах)
const float dt = 0.1f; // 100 мс между вызовами
float lamp_power = PID_Compute(&pid, current_light_percent, dt);
// Установка мощности лампы
SetLampBrightness(lamp_power);
}
// Функции, которые необходимо реализовать для конкретного микроконтроллера
// Чтение значения АЦП
uint16_t ReadADC(uint8_t pin) {
// Реализация чтения АЦП для конкретного микроконтроллера
// ...
return 0; // Заглушка
}
// Установка PWM
void SetPWM(uint8_t pin, uint8_t value) {
// Реализация управления PWM для конкретного микроконтроллера
// Для лампы накаливания может потребоваться симистор или реле
// ...
}
// Пример основного цикла программы
int main(void) {
// Инициализация периферии микроконтроллера
// ...
// Основной цикл
while (1) {
LightControlTask();
// Задержка 100 мс
DelayMs(100);
}
return 0;
}
-
- спасибо. слишком красивый код - Nikolaev_Aleksey(03.03.2025 09:07)
- Тут есть одна тонкость. Спектр излучения лампочки накаливания зависит от мощности. Тёмно-красная ниточка спирали вас не обрадует полумраком. Этот аспект нужно подкинуть в качестве условия. - Бapбoc(02.03.2025 19:40)
- А добавить автоматическую калибровку ПИД коэффициентов можешь? Бoмж(16601 знак., 02.03.2025 19:34)