Это старая версия документа!


Эксперимент 9. Пульсирующий маячок

Мы научились пользоваться аппаратным генератором ШИМ. Попробуем с помощью него сделать что-то более интересное, чем просто светящийся не в полную мощность светодиод. Например, попробуем изменять яркость светодиода во времени по определенному закону.

Схема эксперимента

Рисунок 1. Электрическая принципиальная схема эксперимента

Рисунок 2. Монтажная схема эксперимента

Изменений в схеме, по сравнению с предыдущим экспериментом, нет

Программный код эксперимента

Exp9.ino
  1. #define LED_PIN 15
  2.  
  3. void setup() {
  4. pinMode(LED_PIN, OUTPUT);
  5. analogWriteFreq(200);
  6. analogWriteRange(1024);
  7. }
  8.  
  9. void pulse(int led_pin, int time_ms) {
  10. for (int i = 0; i < 20; i++){
  11. analogWrite(led_pin, int(sin(i / 10.0 * PI) * 500 + 500));
  12. delay(time_ms);
  13. }
  14. }
  15.  
  16. void loop() {
  17. pulse(LED_PIN, 20);
  18. }

В этом эксперименте мы впервые, столкнулись с подпрограммой. Подпрограммы нужны для того, чтобы можно было использовать один и тот же кусок кода несколько раз в программе не копируя постоянно одно и то же. Гораздо удобнее вынести такой код в отдельную подпрограмму и вызывать ее всякий раз, когда она нужна.

Кроме того подпрограмма может принимать параметры и возвращать данные. Чтобы лучше понять что это значит, напишем простейшую подпрограмму для сложения двух чисел.

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 предназначена для изменения яркости светодиода.

  1. for (int i = 0; i < 20; i++){
  2. analogWrite(led_pin, int(sin(i / 10.0 * PI) * 500 + 500));
  3. delay(time_ms);

В строке 12 нам встречается новый оператор for — это оператор цикла. Он предназначен для выполнения своего тела определенное количество раз.

for (инициализация; условие; приращение) {
  тело цикла;
}

Инициализация (Initialization) выполняется самой первой и один раз. Каждый раз в цикле проверяется условие (condition), если оно верно, выполняется блок операторов и приращение (increment), затем условие проверяется вновь. Когда логическое значение условия становится ложным, цикл завершается.

Так вот оператор for, в нашем случае, проходит по всем элементам этой последовательности, которую создал для него range(20). Каждый раз он берет следующий элемент последовательности, присваивает его переменной i, и выполняет тело цикла. И так до тех пор, пока не сделает это со всеми элементами последовательности.

Получается, что в нашем случае, тело цикла будет запущено 20 раз и переменная i последовательно получит значения от 0 до 19. Шаги цикла принято называть итерациями. В нашем случае будет 20 итераций цикла. На каждой итерации мы будем устанавливать новую яркость светодиода. А вычислять яркость на каждой итерации мы будем по формуле в строке 13. Переменная i используется в ней для вычисления яркости.

Мы не будем вдаваться в детали математики в формуле из строки 13, но обязательно дадим ссылку, где можно почитать о функциях библиотеки math подробнее, если это интересно.