ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
3 апреля
1502752 Топик полностью
Бoмж (02.03.2025 19:31, просмотров: 363) ответил Nikolaev_Aleksey на А можно попросить сгенерировать код ПИД регулятора без использования float? Обычный ШИМ регулятор температуры комнаты. Ну или лампочки накаливания с датчиком освещенности.
Нужен ПИД регулятор для управления лампой накаливания 300 Ватт и фоторезистором для поддержания заданного уровня освещённости в комнате с окном. Используем Cortex M0+ микроконтроллер. 

Я разработал код ПИД-регулятора для управления лампой накаливания 300 Вт с использованием фоторезистора в качестве обратной связи для микроконтроллера Cortex M0+.

Вот ключевые особенности реализации:

  1. Структура ПИД-регулятора включает:
    • Настраиваемые коэффициенты Kp, Ki, Kd
    • Защиту от интегрального насыщения (anti-windup)
    • Ограничение выходных значений
  2. Обработка сигнала фоторезистора:
    • Усреднение нескольких измерений для уменьшения шума
    • Преобразование сырых значений АЦП в проценты освещенности
    • Возможность калибровки минимальных и максимальных значений
  3. Управление лампой:
    • Реализовано через PWM (для симистора/диммера)
    • Масштабирование выходного сигнала для управления мощностью лампы
  4. Дополнительные функции:
    • Инициализация регулятора с настраиваемыми параметрами
    • Установка целевого уровня освещенности
    • Основной цикл работы с периодом 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;
}
memento mori