Аппаратный PWM (ШИМ) для Repak Pi 3 #
К СВЕДЕНИЮ
Библиотека WiringRP предоставляет функции для управления встроенным в SoC аппаратным ШИМ-контроллером (PWM0).
На Repka Pi 3 (SoC Allwinner H5): Выход PWM0 подключен к контакту PL10 (физический пин 33) и аппаратно доступен только в 5-м варианте распиновки GPIO-разъема.
На Repka Pi 4 (SoC Allwinner H6): В текущих версиях образа Repka OS аппаратный ШИМ-контроллер не активирован в дереве устройств (Device Tree). В связи с этим, функции для работы с аппаратным ШИМ на Repka Pi 4 не работают. Для генерации ШИМ-сигнала на Repka Pi 4 используйте функции программного ШИМ (раздел Soft PWM).
На Repka Pi 5 данный функционал несколько отличается и описан ниже.
setupPwm() #
Инициализирует функцию управления интегрированным ШИМ контроллером.
Синтаксис #
int setupPwm(void)
Параметры #
Ничего.
Возврат #
0 при успешном выполнении, или отрицательное значение в случае ошибки.
releasePwm() #
Высвобождает ресурсы задействованные функцией управления интегрированным ШИМ контроллером.
Синтаксис #
void releasePwm(void)
Параметры #
Ничего.
Возврат #
Ничего.
pwmSetClock() #
Устанавливает предделитель системной частоты таймера OSC24MHz ШИМ.
Синтаксис #
void pwmSetClock(int divisor)
Параметры #
divisor - значение предделителя частоты таймера OSC24MHz ШИМ, допустимые значения:
PWM_CLK_DIV_120(значение по умолчанию).PWM_CLK_DIV_180.PWM_CLK_DIV_240.PWM_CLK_DIV_360.PWM_CLK_DIV_480.PWM_CLK_DIV_12K.PWM_CLK_DIV_24K.PWM_CLK_DIV_36K.PWM_CLK_DIV_48K.PWM_CLK_DIV_72K.PWM_CLK_DIV_1.
Возврат #
Ничего.
pwmSetMode() #
Устанавливает режим генерирования сигнала ШИМ контроллером.
Синтаксис #
void pwmSetMode(int mode)
Параметры #
mode - значение режима генерирования сигнала ШИМ контроллером, допустимые значения:
PWM_CYCLE_MODE- цикл.PWM_PULSE_MODE- пульс.
Возврат #
Ничего.
pwmSetRange() #
Устанавливает количество полных циклов в тактовой частоте ШИМ.
Синтаксис #
void pwmSetRange(unsigned int range)
Параметры #
range - количество полных циклов в тактовой частоте, вычисляемой по формуле PWM_CLK = 24 MHz / pre-scale. Принимает значение в диапазоне от 0 до 65535.
Возврат #
Ничего.
pwmWrite() #
Устанавливает количество активных циклов в тактовой частоте ШИМ.
Синтаксис #
void pwmWrite(int value)
Параметры #
value - количество активных циклов в тактовой частоте, вычисляемой по формуле PWM_CLK = 24 MHz / pre-scale. Принимает значение в диапазоне от 0 до 65535. Для значения должно выполнятся условие value <= range (см. pwmSetRange() выше).
Возврат #
Ничего.
pwmToneWrite() #
Устанавливает частоту модулируемого ШИМ сигнала. Использоваться для генерации нот и аккордов.
Синтаксис #
void pwmToneWrite(int freq)
Параметры #
freq - частота сигнала. Принимает значение в диапазоне от 0 до 65535.
Возврат #
Ничего.
Пример использования pwmWrite #
Код имитирует аналоговый выход с помощью широтно-импульсной модуляции для изменения яркости свечения светодиода, подключенного к выходу контроллера PWM0 (PL10). Уровень яркости задается в диапазоне от 0% до 100%, и отображается в целевой диапазон от 0 до 1000 с помощью функции map().
ПРЕДУПРЕЖДЕНИЕ
Пример может быть запущен только на 5-ом варианте распиновки GPIO-разъема.
#include <stdlib.h>
#include "wiringRP.h"
#include "pwm.h"
// Глобальные переменные и константы
void setup() {
// Инициализация библиотек wiringRP
if(setupWiringRP(WRP_MODE_SUNXI) < 0)
exit(EXIT_FAILURE);
setupPwm();
// Инициализация пользовательских объектов
pwmSetClock(PWM_CLK_DIV_120);
pwmSetMode(PWM_CYCLE_MODE);
pwmSetRange(1000);
}
void loop() {
// Основной цикл программы
for (int i = 0; i < 100; i++) {
int val = map(i, 0, 100, 0, 1000);
pwmWrite(val);
delay(10);
}
for (int i = 100; i > 0; i--) {
int val = map(i, 0, 100, 0, 1000);
pwmWrite(val);
delay(10);
}
}
ONDESTROY() {
// Освобождение занятых ресурсов, выключение напряжения на пинах
pwmWrite(0);
// Завершение работы библиотек
releaseWiringRP();
releasePwm();
exit(0); // выход из программы
}
MAIN_WIRINGRP();
Пример использования pwmTone #
Код запускает функцию частотно-импульсной модуляции (24 MHz) для воспроизведения мелодии на пьезоэлектрическом динамике, подключенном к выходу контроллера PWM0 (PL10).
ПРЕДУПРЕЖДЕНИЕ
Пример может быть запущен только на 5-ом варианте распиновки GPIO-разъема.
#include <stdlib.h>
#include "wiringRP.h"
#include "pwm.h"
// Глобальные переменные и константы
const int frq[17] = {440, 165, 440, 440, 165, 440, 330, 294, 262, 494, 440, 494, 262, 294, 330, 165, 440};
const int pause[17] = {250, 250, 250, 250, 250, 250, 125, 125, 125, 125, 125, 125, 125, 125, 250, 250, 250};
void setup() {
// Инициализация библиотек wiringRP
if(setupWiringRP(WRP_MODE_SUNXI) < 0)
exit(EXIT_FAILURE);
setupPwm();
// Инициализация пользовательских объектов
pwmSetClock(PWM_CLK_DIV_120);
pwmSetMode(PWM_CYCLE_MODE);
pwmSetRange(65535);
}
void loop() {
// Основной цикл программы
for (int j = 0; j < 17; j++) {
pwmToneWrite(frq[j]);
delay(pause[j]);
pwmToneWrite(0);
delay(pause[j]);
}
}
ONDESTROY() {
// Освобождение занятых ресурсов, выключение напряжения на пинах
pwmWrite(0);
// Завершение работы библиотек
releasePwm();
releaseWiringRP();
exit(0); // выход из программы
}
MAIN_WIRINGRP();
Пример использования Servo PWM #
Код формирует импульсы для управления серводвигателем SG90, подключенным к выходу контроллера PWM0 (PL10).
ПРЕДУПРЕЖДЕНИЕ
Пример может быть запущен только на 5-ом варианте распиновки GPIO-разъема.
// For servo SG90 (5V)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "wiringRP.h"
#include "pwm.h"
// Глобальные переменные и константы
const int DEG_0 = 110;
const int DEG_180 = 510;
const int PULSE_TIME = 2;
const int STEP_DEG = 1;
const int DECELERATION = 1;
void setup() {
// Инициализация библиотек wiringRP
if(setupWiringRP(WRP_MODE_SUNXI) < 0)
exit(EXIT_FAILURE);
setupPwm();
// Инициализация пользовательских объектов
pwmSetClock(PWM_CLK_DIV_120);
pwmSetMode(PWM_CYCLE_MODE);
pwmSetRange(3999); // 50 Hz
}
void loop() {
// Основной цикл программы
// Поворот вала ротора на 180 градусов по часовой стрелке с максимальной скоростью
for (int i = 0; i <= 180; i += STEP_DEG) {
int val = map(i, 0, 180, DEG_0, DEG_180);
pwmWrite(val);
delay(PULSE_TIME * DECELERATION * STEP_DEG);
}
// Поворот вала ротора на 180 градусов против часовой стрелки с максимальной скоростью
for (int i = 180; i >= 0; i -= STEP_DEG) {
int val = map(i, 0, 180, DEG_0, DEG_180);
pwmWrite(val);
delay(PULSE_TIME * DECELERATION * STEP_DEG);
}
}
ONDESTROY() {
// Освобождение занятых ресурсов, выключение напряжения на пинах
pwmWrite(0);
// Завершение работы библиотек
releaseWiringRP();
releasePwm();
exit(0); // выход из программы
}
MAIN_WIRINGRP();
Аппаратный PWM (ШИМ) для Repak Pi 5 #
setupPwm() #
Инициализирует функцию управления интегрированным ШИМ контроллером.
Синтаксис
int setupPwm(void)
Параметры
Ничего.
Возврат
0 при успешном выполнении, или отрицательное значение в случае ошибки.
releasePwm() #
Высвобождает ресурсы задействованные функцией управления интегрированным ШИМ контроллером.
Синтаксис
void releasePwm(void)
Параметры
Ничего.
Возврат
Ничего.
pwmSetRangePi5() #
Устанавливает длительность периода сигнала ШИМ.
Синтаксис
int pwmSetRangePi5(unsigned int range, int port)
Параметры
range - период сигнала в наносекундах(0 - 4294967295)
port - номер устройства pwm.(0 - 15)
Возврат
0 -. команда выполнена успешно
-1 - ошибка при выполнении
pwmWritePi5() #
Устанавливает длительность импульса ШИМ(скважность).
Синтаксис
int pwmWritePi5(int value, int port);
Параметры
value - длительность импульса в наносекундах(0 - 4294967295)
port - номер устройства pwm.(0 - 15)
Возврат
0 -. команда выполнена успешно
-1 - ошибка при выполнении.
pwmToneWritePi5()
Устанавливает частоту модулируемого ШИМ сигнала. С длительностью импульса 50%.
Синтаксис
int pwmToneWritePi5(int freq, int port);
Параметры
freq - частота сигнала в Гц. Принимает значение в диапазоне (0 - 1000000000).
port - номер устройства pwm.(0 - 15)
Возврат
0 -. команда выполнена успешно
-1 - ошибка при выполнении.
Пример использования pwmWrite #
Код имитирует аналоговый выход с помощью широтно-импульсной модуляции для изменения яркости свечения светодиода, подключенного к выходу контроллера PWM3 (35 пин). Уровень яркости задается в диапазоне от 0% до 100%, и отображается в целевой диапазон от 0 до 40000(параметр PERIOD) с помощью функции map().
ПРЕДУПРЕЖДЕНИЕ
Пример может быть запущен только на 5-ом варианте распиновки GPIO-разъема.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "wiringRP.h"
#include "pwm.h"
#define PORT 3
#define PERIOD 40000
// Глобальные переменные и константы
void setup() {
// Инициализация библиотек wiringRP
if(setupWiringRP(WRP_MODE_SUNXI) < 0)
exit(EXIT_FAILURE);
setupPwm();
// Инициализация пользовательских объектов
pwmSetRangePi5(PERIOD, PORT);
}
void loop() {
// Основной цикл программы
for (int i = 0; i < 100; i++) {
int val = map(i, 0, 100, 0, PERIOD);
pwmWritePi5(val, PORT);
delay(10);
}
for (int i = 100; i > 0; i--) {
int val = map(i, 0, 100, 0, PERIOD);
pwmWritePi5(val, PORT);
delay(10);
}
}
ONDESTROY() {
// Освобождение занятых ресурсов, выключение напряжения на пинах
pwmWritePi5(0, PORT);
// Завершение работы библиотек
releaseWiringRP();
releasePwm();
exit(0); // выход из программы
}
MAIN_WIRINGRP();