Это старая версия документа!
Мы научились пользоваться аппаратным генератором ШИМ. Попробуем с помощью него сделать что-то более интересное, чем просто светящийся не в полную мощность светодиод. Например, попробуем изменять яркость светодиода во времени по определенному закону.
Рисунок 1. Электрическая принципиальная схема эксперимента
Рисунок 2. Монтажная схема эксперимента
Изменений в схеме, по сравнению с предыдущим экспериментом, нет
#define LED_PIN 15 void setup() { analogWriteFreq(200); analogWriteRange(1024); } void pulse(int led_pin, int time_ms) { for (int i = 0; i <= 20; i++){ } } void loop() { pulse(LED_PIN, 20); }
В этом эксперименте мы впервые, столкнулись с подпрограммой. Подпрограммы нужны для того, чтобы можно было использовать один и тот же кусок кода несколько раз в программе не копируя постоянно одно и то же. Гораздо удобнее вынести такой код в отдельную подпрограмму и вызывать ее всякий раз, когда она нужна.
Кроме того подпрограмма может принимать параметры и возвращать данные. Чтобы лучше понять что это значит, напишем простейшую подпрограмму для сложения двух чисел.
int summator(int a, int b) { c = a + b; return c; } result = summator(2, 3);
Здесь мы объявили подпрограмму с именем summator
и указали, что она возвращает тип int
и принимает на вход два параметра. Первый параметр будет записан в переменную a
, второй в переменную b
. Обе переменные также типа int
. Далее идет тело подпрограммы, оно находится внутри фигурных скобок. В коде подпрограммы мы складываем переменные a
и b
и записываем результат сложения в переменную c
. И возвращаем полученный результат с помощью оператора return
.
А основная программа состоит только из одной строки, в которой мы вызываем подпрограмму summator
, передавая ей в качестве параметров два числа - 2 и 3. Подпрограмма складывает их и полученный результат оказывается в переменной result
.
Подпрограммы, которые принимают параметры и возвращают результат принято называть функциями. В нашем эксперименте мы объявили функцию pulse
она принимает в качестве параметров объект номер пина и число — время задержки. pulse
не возвращает результата, т.к. указан тип void
.
Функция pulse
предназначена для изменения яркости светодиода.
for i in range(20): l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500)) time.sleep_ms(t)
В строке 12 нам встречается два новых оператора.
Оператор for
— это оператор цикла, как и знакомый нам while
, но действует он иначе. Он предназначен для прохода по всем элементам. Но элементам чего? Сейчас разберемся.
Сначала взглянем на оператор range()
, он предназначен для генерирования ряда чисел в определенном диапазоне. range(20)
генерирует последовательность чисел 0, 1, 2, 3, 4 … 19. Это будет 20 целых чисел от 0 до 19.
Так вот оператор for
, в нашем случае, проходит по всем элементам этой последовательности, которую создал для него range(20)
. Каждый раз он берет следующий элемент последовательности, присваивает его переменной i
, и выполняет тело цикла. И так до тех пор, пока не сделает это со всеми элементами последовательности.
Получается, что в нашем случае, тело цикла будет запущено 20 раз и переменная i последовательно получит значения от 0 до 19. Шаги цикла принято называть итерациями. В нашем случае будет 20 итераций цикла. На каждой итерации мы будем устанавливать новую яркость светодиода. А вычислять яркость на каждой итерации мы будем по формуле в строке 13. Переменная i
используется в ней для вычисления яркости.
Мы не будем вдаваться в детали математики в формуле из строки 13, но обязательно дадим ссылку, где можно почитать о функциях библиотеки math
подробнее, если это интересно.