Arduino для начинающих. часть 2

Содержание

Что за Github и зачем он мне?

Github — это огромное сообщество программистов. Да, ваш код будет публично светиться на весь интернет, но… любой человек может предложить свои правки к вашему коду. Мне, например, очень помогли с SmartDelay два человека, один из которых сделал свою подобную библиотеку и мы поподсматривали чуть-чуть код друг у друга. Лучше две хорошие библиотеки, чем две глюкавые, правда?

Чтобы поместить вашу библиотеку в Github надо сделать там аккаунт, сгенерить ключ и создать репозиторий с там же именем, что ваша библиотека (папка). Файлы можно загрузить через web-шнтерфейс.

Для установки библиотеки из Github в Arduino IDE достаточно скопировать URL и воспользоваться утилитой git:

Или загрузить ZIP — это будет как раз библиотека Arduino, как и все прочие библиотеки.

Test Yourself

Q: Here’s the same question for you. What is the value of i after the loop has finished executing?The value of i is (click to find out)
I has the value 0 since ‘i’ had to be greater than or equal to 1 to stay in the loop.

Arduino For loop Array Example

The reason that you start with the control loop variable at zero is
that arrays are defined starting from index zero. If you don’t use zero
as an initial starting point then you can get an off by one error —
meaning you can write to a array location that does not exist. For an
array of 10 values only indices 0..9 are valid.

Note: Note: Even if the array position does not exist, the loop will still
write data to that location — meaning you are overwriting other
variables — an extremely bad idea!

Here’s an example of setting up an array initialising each element
with a random number. Then printing out the array values in turn.

millis()

Standard form of a for loop

The standard form of the for loop initialises the control variable to
0. For exiting the loop the condition tests whether the variable is
smaller than the number of loops needed. You don’t have to use this but
it makes life easier when dealing with arrays.

The value of ‘i’ goes from 0 to 9 for the code within the curly
braces. So it traverses 10 values. The reason it is easier for array use
is that arrays start from .

TIP: it is best to use the standard form of the Arduino for-loop so
that you never access an array value incorrectly.

The standard form is this:

At the end of the loop code (outside curly braces) the value of ‘i’
will be 10, because when ‘i’ reaches 10 the statement ‘i<10’ is false
so the loop is exited.

Note: At the end of the loop ‘i’ has the value 10.

Программа

Мы больше не будем использовать 13 пин и диод на плате, поэтому уберем связанные с ним переменные из кода. Но добавим массив пинов для светодиодов и счетчик.

В массиве есть элемент 13. Однако мы не будем подключать к нему диод, а будем использовать его для флага, что все светодиоды нужно выключить.

В функции setup() настроим пины на ввод и вывод.

Теперь реорганизуем код устраняющий дребезг кнопки. Мы должны передать в функцию состояние кнопки в текущий момент и получить в ответ обработанное нажатие на кнопку, если оно было.

Кроме того упростим функцию. Избавимся от подсчета миллисекунд, а просто сделаем задержку между считыванием состояния кнопки.

В основном цикле будем вызывать функцию debounce() и передавать в нее предыдущее значение кнопки. И если значения отличаются, а текущее значение = HIGH, то есть кнопка была нажата, вызываем другую функцию ledON().

Функция ledON() хранит текущее значение переменной счетчика i. И включает соответствующий светодиод из массива. Но до того, как включить нужный диод, функция выключает все. Если i = 4, это значение 13 в массиве, мы выключаем все диоды. А следующим нажатием, i = 5, сбрасываем счетчик на 0.

Работа программы

Recent Articles

  1. Learn how to use the TP4056 properly. There’s a right way, and a wrong way, to use it to safely charge Lithium Ion batteries.

  2. A tutorial on using the ADS1115 precision 16 bit ADC for low power use.

  3. Arduino Nano ISP: How to program an ATmega328P using an Arduino Nano as the ISP programmmer. One common problem: Programming a sketch into the chip without a reset control — solved here.

  4. I2C tutorial: Learn all about the 2 wire I2C serial protocol. Learn how easy it is to use, how it works and when to use it…

  5. How to test and use an Arduino Joystick including a new library to make it super easy.

  6. How to use the MCP4728, a versatile four channel DAC with built in voltage reference.

    The MCP4728 chip is a four channel 12 bit DAC, with memory that outputs voltage that you can use for calibration, anywhere you want a fixed voltage.

    Read morereport this ad

Where to use for-loops

You can use for loops anywhere inside a function, so you can
use them in the standard Arduino setup(), and loop() functions, and within
your own functions.

The following example shows a for-loop that loops round
printing the numbers 0 to 9. It is placed into the setup() function
since you only want to perform the for-loop action one time — otherwise
if you place it within the loop() function it repeatedly outputs
information — making you head spin (try it and see)!

Arduino for loop example

How the Arduino for loop works

The Arduino for loop provides a mechanism to repeat a section
of code depending on the value of a variable. So you set the initial
value of the variable, the condition to exit the loop (testing the variable), and the action on
the variable each time around the loop.

Initialiser section: The initial value of the control variable.
Condition Section: The condition to stop the loop.
Iterator Section: The loop variable action (increment or decrement).

These three elements are parameters to the for loop and are separated by semicolons:

initialiser test iterator

Математические функции

Функция min(x, y)

Описание

Возвращает наименьшее из двух чисел, поддерживает все числовые типы данных.

Синтаксис

min(x, y)

Параметры

x — первое число

y — второе число

Возвращаемое значение

Меньшее из двух чисел

Пример
Примечания

Следует избегать использования функций внутри функции, например min(a++, b);, так как из-за внутренней реализации она может вернуть неверный результат.

Функция max(x, y)

Описание

Возвращает наибольшее из двух чисел, поддерживает все числовые типы данных.

Синтаксис

max(x, y)

Параметры

x — первое число

y — второе число

Возвращаемое значение

Наибольшее из двух чисел

Пример
Примечания

Следует избегать использования функций внутри функции, например max(a++, b);, так как из-за внутренней реализации она может вернуть неверный результат.

Функция abs()

Описание

Возвращает модуль число (абсолютное значение числа).

Синтаксис

abs(x)

Параметры

x — число

Возвращаемое значение

Вернет x, если x — положительное число или 0, иначе вернет -x

Пример
Примечания

Следует избегать использования функций внутри функции, например abs(a++);, так как из-за внутренней реализации она может вернуть неверный результат.

Функция constrain(x, a, b)

Описание

Функция проверяет, входит ли число x в диапазон . Если x меньше, чем a, то функция вернет a, если x больше, чем b, то вернет b. Иначе вернет x. Поддерживает все числовые типы.

Синтаксис

constrain(x, a, b)

Параметры

x — проверяемое число

a — нижняя граница диапазона

b — верхняя граница диапазона

Возвращаемое значение

Если x входит в диапазон , то возвращает x, если оно меньше нижней границы, то вернется a, если же оно больше верхней границы, то вернется b.

Пример
Примечания

Следует избегать использования функций внутри функции, например constrain(Serial.parseInt(), minimumValue, maximumValue);, так как из-за внутренней реализации она может вернуть неверный результат.

Функция map(value, fromLow, fromHigh, toLow, toHigh)

Описание

Функция пропорционально переносит число из одного диапазона в другой. Причем число не обязательно должно быть ограничено рамками первого интервала. Также верхняя граница интервала может быть меньше нижний границы.

Синтаксис

map(value, fromLow, fromHigh, toLow, toHigh)

Параметры

value — число, которое следует пропорциональное перенести из первого интервала во второй

fromLow — нижняя граница текущего интервала

fromHigh — верхняя граница текущего интервала

toLow — нижняя граница целевого интервала

toHigh — верхняя граница целевого интервала

Возвращаемое значение

Число, пропорционально перенесенное из одного интервала в другой

Пример
Примечания

Функция map() использует целочисленную математику, поэтому при необходимости использования в проекте вычислений с большей точностью, чем целые числа, не рекомендуется использовать данную функцию, а делать все вычисления следует вручную.

Функция pow(base, exponent)

Описание

Функция возвращает результат операции возведения числа в степень. И параметры, и результат — числа с плавающей точкой.

Синтаксис

pow(base, exponent)

Параметры

base — число

exponent — степень

Возвращаемое значение

Результат возведения в степень

Пример

Функция sq(x)

Описание

Вычисляет квадрат числа: результат умножения числа самого на себя.

Синтаксис

sq(x)

Параметры

x — число, квадрат которого требуется вычислить

Возвращаемое значение

Квадрат числа

Пример
Примечания

Функция sqrt(x)

Описание

Вычисляет квадратный корень из числа.

Синтаксис

sqrt(x)

Параметры

x — число, квадратный корень из которого требует вычислить

Возвращаемое значение

Квадратный корень

Пример

4Использование библиотеки ArduinoThreadдля создания параллельных потоков

Чтобы решить поставленную задачу, воспользуемся замечательной библиотекой ArduinoThread, которая позволяет с лёгкостью создавать псевдо-параллельные процессы. Она работает похожим образом, но позволяет не писать код по проверке времени – нужно выполнять задачу в этом цикле или не нужно. Благодаря этому сокращается объём кода и улучшается читаемость скетча. Давайте проверим библиотеку в действии.

Библиотека ArduinoThread

Первым делом скачаем с официального сайта архив библиотеки и разархивируем его в директорию libraries/ среды разработки Arduino IDE. Затем переименуем папку ArduinoThread-master в ArduinoThread.

Схема подключений останется прежней. Изменится лишь код программы.

#include <Thread.h>  // подключение библиотеки ArduinoThread
const int soundPin = 3;  // переменная с номером пина пьезоэлемента
const int ledPin = 13;  // переменная с номером пина светодиода

Thread ledThread = Thread(); // создаём поток управления светодиодом
Thread soundThread = Thread(); // создаём поток управления сиреной

void setup() {
    pinMode(soundPin, OUTPUT); // объявляем пин 3 как выход.
    pinMode(ledPin, OUTPUT);   // объявляем пин 13 как выход.

    ledThread.onRun(ledBlink);  // назначаем потоку задачу
    ledThread.setInterval(1000); // задаём интервал срабатывания, мсек
    
    soundThread.onRun(sound);     // назначаем потоку задачу
    soundThread.setInterval(20); // задаём интервал срабатывания, мсек
}

void loop() {
    // Проверим, пришло ли время переключиться светодиоду:
    if (ledThread.shouldRun())
        ledThread.run(); // запускаем поток
    
    // Проверим, пришло ли время сменить тональность сирены:
    if (soundThread.shouldRun())
        soundThread.run(); // запускаем поток
}

// Поток светодиода:
void ledBlink() { 
    static bool ledStatus = false;    // состояние светодиода Вкл/Выкл
    ledStatus = !ledStatus;           // инвертируем состояние
    digitalWrite(ledPin, ledStatus);  // включаем/выключаем светодиод
}

 // Поток сирены:
void sound() { 
    static int ton = 100;  // тональность звука, Гц
    tone(soundPin, ton);  // включаем сирену на "ton" Гц
    if (ton }

В программе мы создаём два потока – ledThread и soundThread, каждый выполняет свою операцию: один мигает светодиодом, второй управляет звуком сирены. В каждой итерации цикла для каждого потока проверяем, пришло ли время его выполнения или нет. Если пришло – он запускается на исполнение с помощью метода run(). Главное – не использовать оператор delay(). В коде даны более подробные пояснения.

Параллельное выполнение потоков на Arduino

Загрузим код в память Ардуино, запустим. Теперь всё работает в точности так, как надо!

2 Управление светодиодом и пьезоизлучателемс помощью оператора delay()

Напишем вот такой скетч и загрузим его в Ардуино.

const int soundPin = 3; /* объявляем переменную с номером пина, 
                           на который подключён пьезоэлемент */
const int ledPin = 13;  // объявляем переменную с номером пина светодиода
                     
void setup() {
    pinMode(soundPin, OUTPUT); // объявляем пин 3 как выход.
    pinMode(ledPin, OUTPUT);   // объявляем пин 13 как выход.
}

void loop() {
    // Управление звуком:
    tone(soundPin, 700); // издаём звук на частоте 700 Гц
    delay(200);
    tone(soundPin, 500); // на частоте 500 Гц
    delay(200);
    tone(soundPin, 300); // на частоте 300 Гц
    delay(200);
    tone(soundPin, 200); // на частоте 200 Гц
    delay(200);
    
    // Управление светодиодом:
    digitalWrite(ledPin, HIGH); // зажигаем
    delay(200);
    digitalWrite(ledPin, LOW); // гасим
    delay(200);
}

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

Дело в том, что обычным образом эту задачу не решить. Задачи выполняются микроконтроллером строго последовательно. Оператор delay() задерживает выполнение программы на указанный промежуток времени, и пока это время не истечёт, следующие команды программы не будут выполняться. Из-за этого мы не можем задать разную длительность выполнения для каждой задачи в цикле loop() программы. Поэтому нужно как-то сымитировать многозадачность.

Основные теоретические вопросы

Вольт-амперная характеристика (сокр. ВАХ) – это график отображающий зависимость величины тока протекающего через любой прибор от напряжения, приложенного к нему. Простая и очень ёмкая характеристика для анализа нелинейных компонентов. С её помощью можно выбрать режимы работы, и определить характеристики источника питания для прибора.

Взгляните на пример линейной и нелинейной ВАХ.

График под номером 1 на рисунке отображает линейную зависимость тока от напряжения, такую имеют все приборы резистивного характера, например:

  • Лампа накаливания;
  • обогреватель;
  • резистор (сопротивление);

График номер 2 – это ВАХ характерная для p-n переходов диодов, транзисторов и диодов.

https://youtube.com/watch?v=StyLDWdXF-8

Основы основ

Несколько формальных вещей, то есть таких, о которых все знают, но иногда забывают…

В Arduino IDE, как в C/C++, необходимо помнить о регистрах символов. Ключевые слова, такие как if, for всегда записываются в нижнем регистре. Каждая инструкция заканчивается на «;». Точка с запятой сообщает компилятору, какую часть интерпретировать как инструкцию.

Скобки {..} используются для обозначения программных блоков. Мы используем их для ограничения тела функции (см. ниже), циклов и условных операторов.

Хорошей практикой является добавление комментариев к содержимому программы, это помогает легко понять код. Однострочные комментарии начинаются с // (двойная косая черта). Многострочные комментарии начинаются с /* и заканчиваются на */

Если мы хотим подключить в нашу программу какую-либо библиотеку, мы используем команду include. Вот примеры подключения библиотек:

#include <SPI.h> // стандартная библиотека
#include «svoya_biblioteka.h» // библиотека в каталоге проекта

Горячие клавиши Arduino IDE

Для упрощения работы в Arduino IDE используются «горячие клавиши» или хоткеи, от английского hotkeys, что в переводе и означает «горячие клавиши». Это комбинации клавиш на клавиатуре, которые выполняют различные действия в операционной системе и программах. Все команды доступны через меню «Файл», но через хоткеи работать гораздо быстрее.

Разберем горячие клавиши и их назначение.

Правка

Ctrl+Z отмена одной операции
Ctrl+Y возврат одной отмененной операции
Ctrl+F поиск по коду
Atrl+A выделение всего кода
Ctrl+P печать содержимого вкладки
Ctrl+X вырезать выделенный код
Ctrl+C копировать выделенный код
Ctrl+V вставить выделенный код

Сохранение и работа с вкладками

Ctrl+S сохранить текущий скетч
Ctrl+Shift+S сохранить текущий скетч с выбором имени сохраняемого файла
Ctrl+W закрыть текущую вкладку
Ctrl+Shift+N новая вкладка
Ctrl+Alt+Стрелка вправо переключение на вкладку справа от активной
Ctrl+Alt+Стрелка влево переключение на вкладку слева от активной

Другое

Ctrl+N открыть новое окно редактора
Ctrl+O открыть существующий файл скетча
Ctrl+Слэш ( / или русская точка) закомментирование строки
Ctrl+K открыть папку со скетчами
Ctrl+T автоформатирование кода
Ctrl+Shift+M монитор порта
Ctrl+, (русская буква Б) страница настроек Arduino IDE.

FAQ

Всё верно. Разработчики хотят иметь прибыль от своего полезного и качественного продукта.

Но для использования виртуальных пинов через вебхуки элементы управления не требуются, т.е. приложение можно использовать только для получения токена и бесплатно.

Можно только по Wi-Fi?

Нет. Подключение может любым: Wi-Fi, Ethernet, и даже COM-порт через USB компьютера. Всё зависит от целей, задач и вида микроконтроллера.

Почему не использовать готовые решения?

10. Именно такая цифра — делитель стоимости подобных «готовых» устройств (в некоторых случаях меньше или больше, но какой смысл переплачивать, если с равными усилиями получается дешевле и веселее?)

Что еще можно сделать по этой технологии?

А что угодно!

  • Управляемую подсветку (меняющую цвет, яркость, режимы работы);
  • Сбор информации с самых разных датчиков (температура, влажность, давление);
  • Умные выключатели и розетки;
  • ИК-пульт (наподобие Яндекс.Пульта);
  • Управление компьютером через Алису;
  • Голосовое управление детскими игрушками;
  • Сигнализацию с постановкой на охрану голосом (и проверкой статуса).

А считывать состояния Blynk умеет?

Да, ссылка на запрос состояния выглядит так:

https://blynk-cloud.com/<ваш_токен>/get/V0

Так же можно считывать и состояния датчиков, но это тема уже совсем другой статьи 🙂

Насколько это надежно? (Китай долго не проработает…)

Ардуино (в том числе китайские версии) прошли в массах не одну проверку температурой, влажностью и временем. Лично на моем опыте собранные устройства функционируют по сей день в течение 3 лет. Что называется, слепил — и забыл.

Кроме того, модульные сборки имеют преимущество перед «коробочными» в том, что любой модуль, датчик, реле и т.п. можно заменить (при этом недорого!) без вреда для всей схемы. Их намного легче размещать в ограниченном пространстве (в кастомных корпусах, или вообще без корпуса).

А главный плюс — любое устройство в любой момент можно свободно развивать по функционалу в зависимости от приходящих в голову идей — бесценен!

4Использование библиотеки ArduinoThreadдля создания параллельных потоков

Чтобы решить поставленную задачу, воспользуемся замечательной библиотекой ArduinoThread, которая позволяет с лёгкостью создавать псевдо-параллельные процессы. Она работает похожим образом, но позволяет не писать код по проверке времени – нужно выполнять задачу в этом цикле или не нужно. Благодаря этому сокращается объём кода и улучшается читаемость скетча. Давайте проверим библиотеку в действии.

Библиотека ArduinoThread

Первым делом скачаем с официального сайта архив библиотеки и разархивируем его в директорию libraries/ среды разработки Arduino IDE. Затем переименуем папку ArduinoThread-master в ArduinoThread.

Схема подключений останется прежней. Изменится лишь код программы.

#include <Thread.h>  // подключение библиотеки ArduinoThread
const int soundPin = 3;  // переменная с номером пина пьезоэлемента
const int ledPin = 13;  // переменная с номером пина светодиода

Thread ledThread = Thread(); // создаём поток управления светодиодом
Thread soundThread = Thread(); // создаём поток управления сиреной

void setup() {
    pinMode(soundPin, OUTPUT); // объявляем пин 3 как выход.
    pinMode(ledPin, OUTPUT);   // объявляем пин 13 как выход.

    ledThread.onRun(ledBlink);  // назначаем потоку задачу
    ledThread.setInterval(1000); // задаём интервал срабатывания, мсек
    
    soundThread.onRun(sound);     // назначаем потоку задачу
    soundThread.setInterval(20); // задаём интервал срабатывания, мсек
}

void loop() {
    // Проверим, пришло ли время переключиться светодиоду:
    if (ledThread.shouldRun())
        ledThread.run(); // запускаем поток
    
    // Проверим, пришло ли время сменить тональность сирены:
    if (soundThread.shouldRun())
        soundThread.run(); // запускаем поток
}

// Поток светодиода:
void ledBlink() { 
    static bool ledStatus = false;    // состояние светодиода Вкл/Выкл
    ledStatus = !ledStatus;           // инвертируем состояние
    digitalWrite(ledPin, ledStatus);  // включаем/выключаем светодиод
}

 // Поток сирены:
void sound() { 
    static int ton = 100;  // тональность звука, Гц
    tone(soundPin, ton);  // включаем сирену на "ton" Гц
    if (ton }

В программе мы создаём два потока – ledThread и soundThread, каждый выполняет свою операцию: один мигает светодиодом, второй управляет звуком сирены. В каждой итерации цикла для каждого потока проверяем, пришло ли время его выполнения или нет. Если пришло – он запускается на исполнение с помощью метода run(). Главное – не использовать оператор delay(). В коде даны более подробные пояснения.

Параллельное выполнение потоков на Arduino

Загрузим код в память Ардуино, запустим. Теперь всё работает в точности так, как надо!

Примеры void setup()

Чаще всего внутри void setup указываются следующие инструкции:

  • pinMode с указанием номера и типа пина. Это инструкция определяет режим работы пинов ардуино.
  • Serial.begin с указанием скорости (чаще всего, 9600). Эта инструкция инициализирует работы с последовательным портом на указанной скорости.
  • Инструкции подключения и инициализации различных объектов библиотек ардуино. Например, servo.atach(6) укажет библиотеке, что сервопривод мы подключили к 9 пину, и все последующие действия код библиотеки будет совершать именно с этим портом.
  • Инициализацию глобальных переменных, если мы по каким-то причинам не можем сделать это при определении переменных в глобальной области видимости.
  • Выполнение других настроек и начальных значений для переменных и объектов.

Если говорить об ошибке redefinision of void setup’, то она возникает в том случае, если мы подключаем модуль или скетч, в котором уже есть данная функция. Это и вызывает ошибку

Светодиодные ленты

Светодиодная лента представляет собой цепь соединённых светодиодов. Соединены они не просто так, например обычная 12V лента состоит из сегментов по 3 светодиода в каждом. Сегменты соединены между собой параллельно, то есть на каждый приходят общие 12 Вольт. Внутри сегмента светодиоды соединены последовательно, а ток на них ограничивается общим резистором (могут стоять два для более эффективного теплоотвода):

Таким образом достаточно просто подать 12V от источника напряжения на ленту и она будет светиться. За простоту и удобство приходится платить эффективностью. Простая математика: три белых светодиода, каждому нужно по ~3.2V, суммарно это 9.6V. Подключаем ленту к 12V и понимаем, что 2.5V у нас просто уходят в тепло на резисторах. И это в лучшем случае, если резистор подобран так, чтобы светодиод горел на полную яркость.

Подключаем к Arduino

Здесь всё очень просто: смотрите предыдущий урок по управлению нагрузкой постоянного тока. Управлять можно через реле, транзистор или твердотельное реле. Нас больше всего интересует плавное управление яркостью, поэтому продублирую схему с полевым транзистором:

Конечно же, можно воспользоваться китайским мосфет-модулем! Пин VCC кстати можно не подключать, он никуда не подведён на плате.

Управление

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

Про RGB и адресные светодиодные ленты мы поговорим в отдельных уроках.

Питание и мощность

Светодиодная лента потребляет немаленький ток, поэтому нужно убедиться в том, что выбранный блок питания, модуль или аккумулятор справится с задачей. Но сначала обязательно прочитайте урок по закону Ома! Потребляемая мощность светодиодной ленты зависит от нескольких факторов:

  • Яркость. Максимальная мощность будет потребляться на максимальной яркости.
  • Напряжение питания (чаще всего 12V). Также бывают 5, 24 и 220V ленты.
  • Качество, тип и цвет светодиодов: одинаковые на вид светодиоды могут потреблять разный ток и светить с разной яркостью.
  • Длина ленты. Чем длиннее лента, тем больший ток она будет потреблять.
  • Плотность ленты, измеряется в количестве светодиодов на метр. Бывает от 30 до 120 штук, чем плотнее – тем больший ток будет потреблять при той же длине и ярче светить.

Лента всегда имеет характеристику мощности на погонный метр (Ватт/м), указывается именно максимальная мощность ленты при питании от номинального напряжения. Китайские ленты в основном имеют чуть меньшую фактическую мощность (в районе 80%, бывает лучше, бывает хуже). Блок питания нужно подбирать так, чтобы его мощность была больше мощности ленты, т.е. с запасом как минимум на 20%.

  • Пример 1: нужно подключить 4 метра ленты с мощностью 14 Ватт на метр, лента может работать на максимальной яркости. 14*4 == 56W, с запасом 20% это будет 56*1.2 ~ 70W, ближайший блок питания в продаже будет скорее всего на 100W.
  • Пример 2: берём ту же ленту, но точно знаем, что яркость во время работы не будет больше половины. Тогда можно взять блок на 70 / 2 == 35W.

Важные моменты по току и подключению:

  • Подключение: допустим, у нас подключено ленты на 100W. При 12 Вольтах это будет 8 Ампер – весьма немаленький ток! Ленту нужно располагать как можно ближе к блоку питания и подключать толстыми (2.5 кв. мм и толще) проводами. Также при создании освещения есть смысл перейти на 24V ленты, потому что ток в цепи будет меньше и можно взять более тонкие провода: если бы лента из прошлого примера была 24-Вольтовой, ток был бы около 4 Ампер, что уже не так “горячо”.
  • Дублирование питания: лента сама по себе является гибкой печатной платой, то есть ток идёт по тонкому слою меди. При подключении большой длины ленты ток будет теряться на сопротивлении самой ленты, и чем дальше от точки подключения – тем слабее она будет светить. Если требуется максимальная яркость на большой длине, нужно дублировать питание от блока питания дополнительными проводами, или ставить дополнительные блоки питания вдоль ленты. Дублировать питание рекомендуется каждые 2 метра, потому что на такой длине просадка яркости становится заметной уже почти на всех лентах.
  • Охлаждение: светодиоды имеют не 100% КПД, плюс ток в них ограничивается резистором, и как результат – лента неслабо греется. Рекомендуется приклеивать яркую и мощную ленту на теплоотвод (алюминиевый профиль). Так она не будет отклеиваться и вообще проживёт гораздо дольше.

Выполнение задач FreeRTOS в Arduino IDE

Исходя из основных принципов использования FreeRTOS в Arduino, рассмотренных в предыдущем разделе статьи, первым делом в программе мы подключим заголовочный файл библиотеки FreeRTOS. Затем создадим прототипы функций. Поскольку у нас будет три задачи то, соответственно, создадим для них три прототипа.

Arduino

#include <Arduino_FreeRTOS.h>
void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );
void Taskprint( void *pvParameters );

1
2
3
4

#include <Arduino_FreeRTOS.h>

voidTaskBlink1(void*pvParameters);

voidTaskBlink2(void*pvParameters);

voidTaskprint(void*pvParameters);

Далее в функции void setup() мы инициализируем последовательную связь со скоростью 9600 бит/с и создадим три задачи используя API-функцию xTaskCreate(). Первоначально, установим приоритет для всех задач равный ‘1’, и запустим планировщик (scheduler).

Arduino

void setup() {
Serial.begin(9600);
xTaskCreate(TaskBlink1,»Task1″,128,NULL,1,NULL);
xTaskCreate(TaskBlink2,»Task2 «,128,NULL,1,NULL);
xTaskCreate(Taskprint,»Task3»,128,NULL,1,NULL);
vTaskStartScheduler();
}

1
2
3
4
5
6
7

voidsetup(){

Serial.begin(9600);

xTaskCreate(TaskBlink1,»Task1″,128,NULL,1,NULL);

xTaskCreate(TaskBlink2,»Task2 «,128,NULL,1,NULL);

xTaskCreate(Taskprint,»Task3″,128,NULL,1,NULL);

vTaskStartScheduler();

}

Запрограммируем функцию для первой задачи task1 мигания светодиодом.

Arduino

void TaskBlink1(void *pvParameters)
{
pinMode(8, OUTPUT);
while(1)
{
digitalWrite(8, HIGH);
vTaskDelay( 200 / portTICK_PERIOD_MS );
digitalWrite(8, LOW);
vTaskDelay( 200 / portTICK_PERIOD_MS );
}
}

1
2
3
4
5
6
7
8
9
10
11

voidTaskBlink1(void*pvParameters)

{

pinMode(8,OUTPUT);

while(1)

{

digitalWrite(8,HIGH);

vTaskDelay(200portTICK_PERIOD_MS);

digitalWrite(8,LOW);

vTaskDelay(200portTICK_PERIOD_MS);

}
}

Аналогично запрограммируем функцию для выполнения задачи Task2. Функция для выполнения задачи Task3 будет выглядеть следующим образом:

Arduino

void Taskprint(void *pvParameters)
{
int counter = 0;
while(1)
{
counter++;
Serial.println(counter);
vTaskDelay( 500 / portTICK_PERIOD_MS );
}
}

1
2
3
4
5
6
7
8
9
10

voidTaskprint(void*pvParameters)

{

intcounter=;

while(1)

{

counter++;

Serial.println(counter);

vTaskDelay(500portTICK_PERIOD_MS);

}
}

На этом все – мы успешно запрограммировали проект FreeRTOS для Arduino. Более подробно его работу вы можете посмотреть на видео, приведенном в конце статьи.

Чтобы проверить работу проекта, подключите два светодиода к цифровым контактам 7 и 8, загрузите код программы в плату Arduino и откройте окно монитора последовательной связи (Serial monitor) – в нем вы увидите как счетчик обновляется каждые 500 мс.

Также вы сможете наблюдать как мигают два светодиода с различными интервалами. Попробуйте изменять введенные приоритеты задач в функции xTaskCreate и посмотрите как меняется работа проекта.

В данной статье мы рассмотрели простые задачи FreeRTOS, выполняемые в Arduino Uno, но вы на их основе можете реализовать уже более сложные задачи, пригодные для практического применения.

Зачем всё это нужно?

Arduino IDE позволяет использовать синтаксис C++11, оказывается. То есть, там очень развитый объектно-ориентированный язык. Нам же хочется сосредотачиваться на нашем гениальном коде и размазанная по программе лишняя логика частенько мешает сосредоточиться. Взять, например, всякие дисплейчики, кнопочки, датчики и релюшки — у каждого же своя логика, зачем её смешивать с общей логикой программы. Тот же, например, дисплей. У него много полей, статических и изменяемых. Ой, поле — это же класс. Поле может входить в меню (класс меню) или нет, быть часть частью виртуального дисплея (класс), которых на физическом эеране может быть насколько (дисплеи: рабочий, настроек, диагностики и т.п.). Меню, в свою очередь, управляется кнопками (классы кнопок могут быть разными) или джойстиком (класс). Всё это вместе — класс «дисплей», который можно объявить в своей программе как:

Если вы делаете проект не совсем на коленке не кое как и собираетесь что-то потом менять или повторно использовать какие-то свои наработки — лучше оформить сделанное в виде библиотек Arduino. В идеале, конечно же, положить в Github для других людей, если вам не жалко и вы не против, что кто-то ваш код исправит или дополнит.

Раз уж мы в прошлой статье делали кнопочку, давайте её оформим как класс и библиотеку?

Итак, наша задача сделать так, чтобы мы могли в своих скетчах писать: