Как самостоятельно реализовать функцию ШИМ (широтно-импульсной модуляции) для контроллеров серии SystemePLC S250?

ID:214350

Для решения данной задачи можно воспользоваться представленной далее программой или реализовать её в виде функционального блока.

Описание функционального блока:


Внешний вид функционального блока на языке CFC.

Функциональный блок PWM формирует ШИМ сигнал на выходе Output с заданным периодом (вход Period) и определённым значением заполнением (0 … 100 % ) на входе Duty_Cycle. Имеется возможность ограничить скважность минимальным и максимальными значением, который задаются на входы MIN_duty_cycle и MAX_duty_cycle соответственно (по умолчания задан диапазон 10 … 90 %).

Пример использования функционального блока в программе.

Программный код функционального блока:

FUNCTION_BLOCK PWM
VAR_INPUT
    EN:                 BOOL;           // Вкл/Выкл.
    Period:             TIME;           // Период ШИМ
    MIN_duty_cycle:     REAL := 0.0;    // Минимальное значение коэффициента заполнения
    MAX_duty_cycle:     REAL := 100.0;  // Максимальное значение коэффициента заполнения
    Duty_Cycle:         REAL;           // Коэффициент заполнения, 0.0..100.0
END_VAR
VAR_OUTPUT
    Output:             BOOL;           // Выход ШИМ
    // Рекомендуется добавить диагностические выходы:
    Error:              BOOL;           // Флаг ошибки
    // ErrorID:           WORD;         // Код ошибки (опционально)
END_VAR
VAR
    uliCurrent_Time:    ULINT;
    uliStart_Time:      ULINT := 0;
    uliPuls_Time:       ULINT;
    uliPeriod_Time:     ULINT;
    bFirstScan:         BOOL := TRUE;   // Флаг первого скана для инициализации
END_VAR
VAR CONSTANT
    rRange:             REAL := 100.0;  // Диапазон величины на входе Input
END_VAR

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Сброс ошибки при неактивном блоке
IF NOT EN THEN
    Output := FALSE;
    Error := FALSE;
    bFirstScan := TRUE;  // Подготовка к следующему включению
    RETURN;
END_IF

// ИНИЦИАЛИЗАЦИЯ И ПРОВЕРКА ВХОДНЫХ ДАННЫХ

// Проверка валидности периода
IF Period <= T#0s THEN
    Output := FALSE;
    Error := TRUE;
    RETURN;
END_IF;

// Проверка валидности диапазона скважности
IF MIN_duty_cycle >= MAX_duty_cycle OR MIN_duty_cycle < 0.0 OR MAX_duty_cycle > 100.0 THEN
    Output := FALSE;
    Error := TRUE;
    RETURN;
END_IF;

// Сбрасываем ошибку, если все проверки пройдены
Error := FALSE;

// ОСНОВНАЯ ЛОГИКА

SysTimeGetUs(uliCurrent_Time);
uliPeriod_Time := TIME_TO_ULINT(Period) * 1000;  // Преобразование TIME в микросекунды

// Расчет длительности импульса с ограничением и нормализацией
uliPuls_Time := REAL_TO_ULINT(
    LIMIT(MIN_duty_cycle, Duty_Cycle, MAX_duty_cycle) 
    * ULINT_TO_REAL(uliPeriod_Time) / rRange
);

// Инициализация таймера при первом скане или переполнении периода
IF bFirstScan OR (uliCurrent_Time - uliStart_Time >= uliPeriod_Time) THEN
    uliStart_Time := uliCurrent_Time;
    bFirstScan := FALSE;
END_IF

// Формирование выходного сигнала
IF (uliCurrent_Time - uliStart_Time < uliPuls_Time) AND (uliPuls_Time > 0) THEN
    Output := TRUE;
ELSE
    Output := FALSE;    
END_IF

Пример программы прилагается.
Фильтры
Поиск
Корзина