Инструкция по программированию Arduino
Друзья, на связи снова специалист Giant 4 Алексей! Мы продолжаем наш небольшой курс статей, по использованию платы Arduino Nano и так называемой адресной лентой, на основе светодиодов ws2812b. На сегодня это уже четвертая статья. В прошлый раз мы написали первую программу для управления лентой. Но все-таки нужно иметь хотя бы небольшое представление о языке программирования, которым мы пользовались. Иначе говорить о чем-то дальше будет просто бессмысленно. И так, перед Вами C/C++ подобный язык. Конечно же, мы не будем изучать его полностью, но я постараюсь затронуть основные моменты.
Основные функции
Конечно же, это функции setup() и loop() и они нам уже знакомы.
Функция setup() вызывается автоматически, при старте программы. Она выполняется один раз и ничего не возвращает, поэтому мы обозначаем данную функцию типом void. В дальнейшем мы разберем, что это значит.
Функция loop() начинает выполняться после завершения функции setup(), данная функция тоже ничего не возвращает и выполняется по кругу бесконечное количество раз.
И loop(), и setup() являются необходимым минимумом программы. Эти функции должны всегда присутствовать, иначе компилятор выдаст ошибку. Как правило, в setup() происходит инициализация объектов. А в loop() выполняется основная программа и вызываются другие функции.
void setup()
{
}
void loop()
{
}
Типы данных
Конечно же, когда речь идет о программировании, то приходится использовать данные разного типа. Типов достаточно много, но мы разберем лишь некоторые из них.
- Boolean – это логический тип данных, переменные такого типа могут принимать лишь два значения true или false. Где true – это истина, а false – это ложь. Без этого типа было бы невозможно организовать логику программы. Для того, чтобы объявить переменную такого типа, необходимо записать «boolean a;». И тогда нам будет доступна переменная с именем «а» типа boolean. А для того, чтобы присвоить данной переменной значение, нужно сделать такую запись – «a = true;». Хотя можно присвоить значение сразу, при объявлении переменной «boolean a = true;». А чтобы в дальнейшем изменить значение переменной, достаточно просто присвоить ей новое значение. Кстати, да, знак равенства – это операция присваивания. Записи с такой операцией принято читать справа налево. «a = true;» - Значение true присваивается переменно «a».
void setup()
{
}
void loop()
{
boolean a = true;
a = false;
}
Таким же образом, как мы объявляли переменные типа boolean, можно объявить переменную любого типа.
- int – пожалуй, самый используемый и востребованный тип. В переменных такого типа хранятся целые числа от -32768 до 32767. Данные ограничения связанны с тем, что на переменную выделяется два байта памяти и больше записать просто не получится. Хотя, если понадобится, то можно воспользоваться другими типами, на которые выделено больше памяти, например, тип long (от -2 147 483 648 до 2 147 483 647).
int i = 256;
- String – строковый тип. В переменную такого типа можно записать строку или массив символов.
void setup()
{
}
void loop()
{
String s = "Привет";
}
Переменная
Переменная – это имя, закреплённое за выделенной областью памяти. Переменная позволяет опустить потребность контроля, за расположением принадлежащей ей ячейки памяти. Достаточно записать значение в переменную, и значение попадет в выделенную для этого область памяти. При этом, пока существует переменная, присвоенное ей значение будет оставаться в целостности и не будет случайно стерто.
Как мы уже могли понять, переменные могут быть разных типов и содержать в себе разные данные. Мало того, очень важно то, в каком месте объявлена переменная, так как объявление работает лишь в рамках тела, обособленного фигурными скобками. Как только тело заканчивается, переменная перестает существовать. В следующем примере при каждом повторе функции loop(), в начале работы, переменная инициализируется и ей присваивается значение, а в момент завершения, переменная перестает существовать.
{
}
void loop()
{
String s = "Привет";
}
С этим нужно быть аккуратным, так как на инициализацию переменной тратится немного вычислительного ресурса микроконтроллера.
void setup()
{
int a;
}
void loop()
{
a = 1;
}
Но при этом, если в теле функции, где объявлена переменная, есть еще какое-то тело, например, условие, то все будет отлично работать.
void setup()
{
}
void loop()
{
int a;
if()
{
a = 1;
}
}
Также можно объявить глобальную переменную, которая будет видна из любой части программы. Но тогда она никогда не будет очищена. И любое место, где она использована, может повлиять на ее значение. Будьте аккуратны.
boolean myBool;
void setup()
{
myBool = true;
}
void loop()
{
myBool = false;
}
Арифметические операторы
С одним из арифметических операторов Arduino вы уже знакомы – это оператор присваивания «=». Но есть и другие, их немного и смысл, думаю, будет понятен и без объяснений.
- «+» - сложение;
- «-» - вычитание;
- «*» - умножение;
- «/» - деление;
- «%» = остаток от деления.
Но, не смотря на всю простоту, я приведу пример.
int myInt = 0;
void setup()
{
myInt = 1 + 2;
}
void loop()
{
myInt = myInt * 3;
}
В первой строчке мы объявляем переменную типа int с именем myInt. В пятой строке мы присваиваем нашей переменной значение из суммы чисел «1» и «2», то есть myInt равен трем. В десятой строке мы присваиваем переменной значение, равное значению переменной, умноженной на «3». Следовательно, 3 * 3 = 9. Но так как функция loop() выполняется по кругу, то при втором проходе, когда переменная уже равна 9, ей будет уже присвоено произведение двух чисел «9» и «3». Следовательно, переменная будет хранить в себе число 27. А при третьем проходе значение превратится в 81. И так будет продолжаться до бесконечности.
Функции
И снова мы возвращаемся к этому, только теперь мы уже вооружены некоторыми знаниями и готовы писать свои функции для Ардуино. Да, помимо стандартных setup() и loop() мы можем создавать свои, совершенно любого назначения. Помните, я говорил, что перед названием функции мы пишем «void» именно потому что она ничего не возвращает? Так вот, функция – это отдельно стоящий блок программы, который мы можем вызвать в любой момент. Мы имеем возможность передать функции какие-то значения, чтобы использовать их в теле функции. Также мы можем распорядиться таким образом, чтобы функция вернула значение нам, к примеру, результат расчета. И «void» — это еще один тип данных, использующийся только в купе с функциями. Если перед названием функции стоит «void» — это значит, что функция ничего не возвращает, она делает свои операции и просто заканчивает работу. Функции при программировании Arduino используют, как правило, в тех случаях, когда одно и то же действие необходимо повторять из разных частей программы и с разными значениями. Не понятно? Не страшно, сейчас разберем все подробно.
Создать функцию в Arduino очень просто, ее даже не нужно объявлять, достаточно только записать. Давайте создадим функцию с названием «myFun». Эта функция ничего не принимает, ничего не возвращает и даже ничего не выполняет. Пока что она просто есть.
int myInt = 0;
void setup()
{
myInt = 1 + 2;
}
void loop()
{
myInt = myInt * 3;
}
void myFun()
{
}
Теперь давайте заставим данную функцию выполнять операцию сложения.
void setup()
{
}
void loop()
{
}
void myFun()
{
int sum = 5 + 4;
}
В данном случае, хоть в теле функции и происходит математическая операция, она никогда не будет выполнена, так как функция ниоткуда не вызывается. Давайте исправим это. Теперь при каждом прохождении тела loop() данная функция будет вызываться и производить сложение, присваивая результат переменной sum.
void setup()
{
}
void loop()
{
myFun();
}
void myFun()
{
int sum = 5 + 4;
}
Но на данной момент это совершенно бессмысленная операция, так как переменная sum существует только в пределах функции. Давайте изменим тип нашей функции с «void» на «int». И теперь «myFun()» должна возвращать значение типа int. Для этого используется команда return.
void setup()
{
}
void loop()
{
myFun();
}
int myFun()
{
int sum = 5 + 4;
return sum;
}
Но сейчас по-прежнему функционал программы не совсем корректен, потому что значение, полученное в функции, и которое она возвращает, возвращается в место вызова функции. И чтобы его использовать в дальнейшем, необходимо его к чему-то присвоить. Давайте исправляться дальше.
void setup()
{
}
void loop()
{
int mySum = myFun();
}
int myFun()
{
int sum = 5 + 4;
return sum;
}
В теле функции loop() мы объявили переменную типа int и присвоили ей возвращаемое функцией myFun() значение. Но программа до сих пор выглядит глупо. Мы и так знаем результат сложения «5» и «4». Поэтому давайте передавать в myFun() значение, которые хотим сложить. Для этого в круглых скобках необходимо объявить через запятую тип и имя параметров, которые мы хотим получить. А при вызове функции передать ей эти параметры. Выглядит это следующим образом.
void setup()
{
}
void loop()
{
int mySum = myFun(4, 5);
}
int myFun(int a, int b)
{
int sum = a + b;
return sum;
}
Теперь, вызывая нашу функцию из разных мест программы, мы можем передавать ей разные значения и получать сумму этих значений. Да, как правило, задачи у функций немного посложнее, но мы пока только учимся, и поэтому я стараюсь использовать максимально простые примеры для первых экспериментов в программировании Ардуино. Сейчас мы разберемся, что из себя представляет оператор if и вернемся к написанию функций.
Оператор If
Оператор if представляет из себя некоторое условие, которое используется в сочетании с операторами сравнения. Их несколько, но пока что мы разберем только один, а уже потом затронем остальные. Первый оператор сравнения, о котором мы с вами узнаем – это оператор равенства. Обозначается он как два, стоящие друг за другом, знака равно «==». И давайте сразу перейдем к записи условия. Тут в теле loop() я объявил две переменных, «a» и «b» типа int. Затем идет условие, которое правильно читать следующим образом – «если a равно b, тогда выполняются следующие действия». В нашем случае «следующие действия» — это вызов функции, который не произойдет, потому что оператор сравнения «равно» вернет значение «false» и в тело условия программа не зайдет.
void setup()
{
}
void loop()
{
int a = 3;
int b = 4;
if(a == b)
{
myFun();
}
}
Да, вы поняли правильно, в качестве значения if принимает либо true, либо false. Следовательно, такая запись тоже возможна. Правда, смысла она не имеет, так как если условие предопределено, то нужды писать его нет.
void setup()
{
}
void loop()
{
int a = 3;
int b = 4;
if(false)
{
myFun();
}
}
Кстати, в программе и такая запись возможна :)
void setup()
{
}
void loop()
{
boolean myBool = false;
int a = 3;
int b = 4;
if(myBool)
{
myFun();
}
}
Также может возникнуть такая ситуация, что при выполнении условия нужно выполнить одни команды, а при невыполнении условия, нужно выполнить другие команды. Для этого существует конструкция if – else. С низу будет пример, а читается это так – «если «a» равно «b», то вызывается функция myFun_01, иначе вызывается функция myFun_02». Прелесть этой записи в том, что никогда и ни при каких обстоятельствах не будут вызваны обе функции. Тут либо одна, либо другая.
void setup()
{
}
void loop()
{
int a = 3;
int b = 4;
if(a == b)
{
myFun_01();
}
else
{
myFun_02();
}
}
Теперь, когда все стало понятным, давайте вернемся к операторам сравнения в ардуино. Их не очень много, и они интуитивно понятны. Я просто перечислю их, потому что объяснения тут излишни.
x == y (x равно y)
x != y (x не равно y)
x < y (x меньше чем y)
x > y (x больше чем y)
x <= y (x меньше чем или равно y)
x >= y (x больше чем или равно y)
И снова функции
Тут я не хочу усложнять материал, а просто привести пример в купе с операторами условия. Давайте напишем функцию, где будем сравнивать два числа, а возвращаемым значением данной функции будет строка, говорящая о результате сравнения. Итак, простая программа для Arduino.
void setup()
{
}
void loop()
{
int a = 3;
int b = 4;
String myStr = myFun(a, b);
}
String myFun(int x, int y)
{
String str;
if(x > y)
{
str = x + " больше " + y;
}
else
{
if(x < y)
{
str = x + " меньше " + y;
}
else
{
str = x + " равно " + y;
}
}
return str;
}
Пожалуй, все, что есть в данной программе, мы проходили, кроме сложения строк. Но на этом я не буду заострять свое внимание, просто посмотрите и примите, что так можно делать. Причем значение типа int автоматически преобразуется в строку.
В 10-ой строке у нас идет вызов функции, причем результат ее работы присвоен к переменной типа String.
С 13-ой строки начинается функция, она принимает два значения типа int и возвращает значение типа String. Мы все это уже проговаривали.
В 16-ой строке идет условие if-else, при попадании в которое у нас формируется строка. Но самая интересная часть для нас - это тело else, начинающееся с 20 строки. Тут в else мы вложили еще один оператор if-else. Так тоже можно делать. И вложение может быть очень глубоким, а не на одну ступень.
Я специально решил показать подобный пример, чтобы в дальнейшем облегчить понимание происходящего.
Комментарии
Комментарии – это строки в программе, служащие для информирования программиста о том, как работает его программа. При компиляции комментарии пропускаются, поэтому можно писать их в любом количестве. Зачастую не принято комментировать каждую строку, обычно подписывают функционал и принадлежность функций или блоков, чтобы по прошествии времени быстро вспомнить их назначение. Комментарии бывают однострочные и многострочные. Однострочные начинаются с символов «//» и после вся строка будет комментарием. Многострочные комментарии имеют обособление, в начале ставится «/*», а в конце «*/».
void setup()
{
/* В данном примере
функция setup()
не используется*/
}
void loop()
{
int a = 3; //объявляю переменную типа int
int b = 4;
}
Цикл
И напоследок этого короткого и не полного курса по языку программирования Arduino, я хочу поговорить про циклы. Их существует несколько видов, и, как мы уже поняли, сама функция loop() – это тоже цикл. Но я все-таки не буду охватывать все и остановлюсь на циклах типа for.
Конструкция for используется для набора команд, заключенных в фигурные скобки. Заголовок состоит из трех частей «for(int i = 0; i < 10; i++)». Самой первой (и единожды) выполняется инициализация переменной, отвечающая за счетчик цикла «int i = 0». При каждом прохождении цикла проверяется условие «i < 10», если оно верно, то цикл продолжает выполняться. Также если условие верно, то происходит приращение из третий части «i++», тут каждый проход цикла к i прибавляется единица. Также переменную, объявленную в цикле, можно использовать в теле цикла.
void setup()
{
}
void loop()
{
String str;
for(int i = 0; i < 10; i++)
{
str = "номер " + i;
}
}
В данном примере у нас присутствует цикл на 10 итераций, от 0 до 9. Также при каждом заполнении у нас перезаписывается переменная, строкового типа. В данную переменную мы пишем слово «номер», а затем через строковое сложение прибавляем реальный номер итерации. Думаю, на этом с циклами можно закончить.
Заключение
Вот и подошла к концу очередная статья. Конечно же мы затронули далеко не все темы, а то что затронули, раскрыли не полностью. Но тем не менее, у нас не книга по программированию, а пока лишь ознакомительная статья. И знаний, полученных сегодня, вполне хватит, чтобы мы с вами продолжили совместную продуктивную работу с Ардуино в следующей статье.
Товары
- Комментарии