Создание функций arduino ide

Обновлено: 06.07.2024

Данный документ описывает создание библиотеки для Arduino. Объяснение начнется с написания скетча передачи кода Морзе посредством светодиода. Затем будет показано как конвертировать скетч в библиотеку. Это позволит другим пользователям легко использовать созданный код, обновлять и дополнять его.

Скетч, воспроизводящий код Морзе:

Данный скетч посредством мигания светодиода на выводе 13 выдает сигнал SOS.

Скетч содержит ряд частей кода, которые необходимо будет перенести в библиотеку. Во-первых, это функции dot() и dash(), которые управляют миганием светодиода. Во-вторых, это переменная ledPin, определяющая какой порт ввод/вывода использовать. И наконец, вызов функции pinMode(), устанавливающий режим вывода на используемом порту ввода/вывода.

Процесс конвертации скетча в библиотеку.

Библиотека содержит два файла: заголовочный файл (с расширением .h) и файлы реализации (с расширением .cpp). Заголовочный файл содержит характеристики библиотеки, т.е. список всего что содержится в ней. Создаваемый заголовочный файл будет называться Morse.h. Для дальнейшей работы с заголовочным файлом необходимо просмотреть содержание файла реализации.

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

Класс в данном случае это набор функций и переменных, объеденных в одном месте. Функции и переменные могут быть публичными (public), что означает общий доступ к ним всех, кто использует библиотеку, или частными (private), что означает доступ к ним только внутри класса. Каждый класс имеет специальную функцию конструктор, которая используется для создания экземпляра класса. Конструктор имеет тоже имя, что и класс, но не имеет типа возвращаемого значения.

В версиях Arduino 1.0 и выше нужно еще добавить:

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

В начале кода библиотеки принято помещать комментарий о ее предназначении, авторе, дате и лицензии на библиотеку.

Готовый заголовочный файл содержит:

Рассмотрим файл реализации Morse.cpp.

Далее по коду находится конструктор. Он используется для создания экземпляра создаваемого класса. В данном случае пользователь задает номер используемого порта ввода/вывода через параметр. Порта устанавливается в режим вывода, а номер сохраняется в частной переменной для использования в других функциях:

Код Morse:: означает, что функция принадлежит классу Morse. Нижний пробел в начале имени переменной _ pin — принятое обозначение для частных переменных. Вообще, имя может быть любое, но согласно принятым конвенциям именования для частных переменных принято использовать префикс "_". Это также позволяет отличить от аргумента функции (в данном случае pin).

Далее код, который конвертируется в библиотеку из изначального скетча, добавилось только Morse:: и изменилось имя переменной с pin, на _pin:

Общепринято помещать некоторые поясняющие комментарии в начале кода файла реализации. Полный код библиотеки:

Использование библиотеки.

Во-первых, необходимо создать папку Morse в подпапке libraries директории блокнота. Во-вторых, требуется скопировать файлы Morse.h и Morse.cpp в созданную папку. После запуска программы Arduino в меню Sketch > ImportLibrary будет находиться библиотека Morse. Библиотека будет компилироваться совместно со скетчами, использующими ее. Если при компиляции библиотеки возникли проблемы, то необходимо проверить, чтобы ее файлы были с расширениями .cpp и .h (не должно быть никаких дополнительных расширений .pde и .txt).

Изначальный скетч, переписанный с использованием созданной библиотеки, будет выглядеть следующим образом:

Несколько отличий от изначального скетча:

Во-вторых, создается экземпляр класса Morse, называемый morse:

При выполнении данной строки (перед выполнением функции setup()) вызывается конструктор для класса Morse и принимает аргумент, данный в примере (13).

При этом функция setup() ничего не содержит, т.к. вызов функции pinMode() произошел внутри библиотеки (когда был создан экземпляр класса).

В-третьих, для вызова функций dot() и dash() необходимо прибавить префикс morse. – имя используемого экземпляра. Может быть несколько экземпляров класса Morse, каждый со своим номером порта, хранящимся в локальной переменной _pin. Вызовом функции конкретного экземпляра определяются какие переменные, используются во время вызова. При наличии следующих двух строк:

внутри вызова morse2.dot(), переменная _pin будет иметь значение 12.

К сожалению автоматическая подсветка кода не работает с подключаемыми библиотеками. Для того чтобы подсветка заработала необходимо создать файл с названием keywords.txt. Пример:

Напротив каждой строки через табуляцию стоит зарезервированное слово, и опять через табуляцию тип слова. Классы соответствуют зарезервированному слову KEYWORD1 и окрашены в оранжевый цвет; функции – KEYWORD2 и окрашены в коричневый. Для распознавания слов необходимо перезапустить среду разработки Arduino.

Созданную библиотеку желательно всегда сопровождают примером ее применения. Для этого создается папка examples в директории Morse. Затем копируется созданный ранее скетч SOS в данную папку. (Файл скетча можно найти через меню Sketch > ShowSketchFolder). После перезапуска Arduino в меню File > Sketchbook > Examples будет находиться пункт Library-Morse, содержащий пример. Также необходимо добавить комментарии о том, как лучше использовать библиотеку.

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

Для программистов, работающих с BASIC, функции в Arduino позволяют использовать подпрограммы (GOSUB в BASIC).

Разделения кода на функции имеет ряд преимуществ:

  • Функции позволяют организовать программу. Очень часто помогают заранее составить концепцию программы.
  • Функции кодируют одно действие в одном месте программы. Далее необходимо только отладить код функции.
  • Функции сокращают шансы на появление ошибки при необходимости изменения кода.
  • Функции сокращают текст скетчей и делают его компактным, т.к. некоторые секции используются много раз.
  • Функции облегчают использование кода в других программах делая его модульным. В этом случае функции обладают еще одним небольшим преимуществом, делая код программы легким для чтения.

Существуют две обязательные функции в скетчах Arduino setup() и loop(). Другие функции должны создаваться за скобками этих функций. В следующем примере будет создана простая функция умножения двух чисел.

Пример

Синтаксис функции Arduino

Для вызова функции умножения ей передаются параметры данных:

Созданную функцию необходимо задекларировать вне скобок любой другой функции, таким образом "myMultiplyFunction()" может стоять выше или ниже функции "loop()".

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

Следующая функция будет считывать данные с датчика функцией analogRead() и затем рассчитывать среднее арифметическое. Затем созданная функция будет масштабировать данные по 8 битам (0-255) и инвертировать их. // датчик подключен к выводу 0

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

Функция – это фрагмент программного кода, к которому можно обращаться из разных мест программы. Её можно представить например как печать, штамп – один раз изготавливаем и потом штампуем в разных документах, причем по ходу можно менять аргументы (в данном случае дату), и цвет чернил, которые мы передаем в тело печати.



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



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



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



Общее описание функции

Описание функции в скетче в общем виде имеет следующую структуру. В ней тип возвращаемых данных, имя функции, входные аргументы, тело функции заключенное в фигурные кавычки. В теле функции знакомые операнды, а так же необязательный операнд return, который завершает выполнение инструкций функции и передает данные, заданного типа в место вызова функции. Для нас, новичков, функции отличаются типом возвращаемых данных и количеством входных аргументов.



Разновидности функций

Я чаще всего пользуюсь функциями, которые ничего не принимают как аргументы и ничего не возвращают. Тип void в типе возвращаемых данных функции сообщает компилятору, что не нужно ругаться, если функция ничего не возвратит. В такой функции можно например управлять состояниями входов-выходов, печатать что-нибудь в монитор порта, или изменять внешние переменные. В теле функции можно проводить манипуляции над глобальными переменными. Изменять из значения, использовать их в операндах. Так же можно создавать внутренние переменные, которые видны только в этой функции и при каждом её вызове создаются заново. То есть не сохраняют значение с прошлого вызова. Но с обозначением static внутренние переменные могут сохранять значения с прошлого вызова и их тоже разрешено здесь юзать. Подробнее об этом нюансе можно узнать из урока Arduino видимость переменных.

Функция может принимать аргументы, но ничего не возвращать.

Может так же не принимать аргументы, но возвращать данные заданного типа.

А так же и принимать аргументы и что-то возвращать.

Вызов функций

Обращаются к функциям в тексте скетча обычно такими путями:

Если функция ничего не возвращает то

Если возвращает то

Или даже можно использовать как часть логического условия

В теле функции оператор return завершает выполнение функции и возвращает данные. Его в одной функции можно использовать не один раз.

А так же с его помощью можно просто завершать выполнение функции при достижении нужного условия.

Что касается красивого структурирования скетча для arduino подобного контроллера, то функции позволяют привести текст функции main и главного цикла программы к минималистичному виду. При этом внутри самих функций может содержаться увесистый скетч со сложными вычислениями и обращением к различным коммуникациям. Само тело каждой функции может храниться в отдельном файле, редактироваться в отдельной вкладке программы Arduino IDE.

Рекомендации для лучших скетчей

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

Выводы

А пока нам необходимо запомнить, что функция определяется в программе один раз, а вызываться может множество раз. При каждом вызове функции в неё можно передать новые значения аргументов. Функция так же может возвращать нам данные предопределённого типа, а может и ничего не возвращать – тогда мы её определяем как тип void. Спасибо за подписку, лайк и комментарий и до новых встреч.

Термоклей 11мм 20см

Термоклей 11мм 20см

Клей для термопистолетаДиаметр 11 ммДлина 20 смЦвет прозрачный..

Шилд для Arduino Nano и GSM SIM800

Шилд для Arduino Nano и GSM SIM800

Шилд для проектов с использованием платы контроллера Arduino Nano и GSM модуля SIM800. Решает пробле..

Оптопара EL817 SMD

Оптопара EL817 SMD

Оптопара с транзистором на выходеПрименяется для гальванической развязки дискретного сигнала, а так ..

Arduino NANO CH340 MicroUSB + USB кабель

Arduino NANO CH340 MicroUSB + USB кабель

Плата контроллера Arduino Nano V3 в удобном формфакторе с MicroUSB на основе ATMEGA328P-MUДрайв..

Функции

Привет. Сегодня поговорим про организацию своей функции в языке программирования ардуино.

В предыдущих статьях мы писали код непосредственно в две управляющие функции программы. На этот раз посмотрим как можно организовать код более удобным способом.

В прошлый раз мы рассматривали программу устранения дребезга кнопки. Если вы уже забыли или пропустили предыдущую статью, пожалуйста, посмотрите её.

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

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

Чтобы выполнить этот урок нам понадобятся.

  • Ардуино UNO
  • Макетная плата
  • Перемычки
  • 4 Резистора номиналом 220 Ом
  • Резистор номиналом 10 кОм
  • Кнопка
  • 4 Светодиода 5 мм
  • Кабель USB

Функции

Мы уже встречались с функциями. Поэтому разобраться с этим будет довольно просто. В предыдущих проектах мы использовали функции delay(), millis(), pinMode(), digitalWrite(), setup() и loop().

Давайте напишем простую функцию для примера.

Мы создали функцию plus(). Она получает на вход две переменные типа int и возвращает их сумму. Если мы присвоим другой переменной значение этой функции, то получим результат сложения.

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

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

Сначала соберем схему на макетной плате.

Аноды светодиодов подключаем к пинам на плате ардуино, используем 5,7,9 и 11 пины. Катоды светодиодов подключаем к земле через резисторы 220 Ом.

Кнопку подключаем ко 2 пину на ардуино с одной стороны. А также к шине 5 вольт и к земле через резистор 10 кОм.

Программа

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

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

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

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

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

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

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

Полный текст программы

Заключение

Читайте также: