Этот урок будет посвящен одной из интереснейшей теме программирования- функциям. Что это такое? Это небольшая подпрограмма, находящаяся в теле основной программы, которую можно использовать много раз в течении одного цикла программы. С чем это можно сравнить? Приведу пример из жизни человека: например у нас есть функция дыхания. Мы даже не задумываемся- дышим и все с такой частотой с которой нужно организму, т.е. дыханием мы потребляем необходимое количество кислорода в воздухе. Мы можем дышать ровно и медленно когда спим, резко и часто когда заняты работой или спортом и т.д. Но функция дыхания у нас одна- мы просто дышим. Организм сам вызывает эту функцию когда ему надо. Так же и в программировании- мы можем определить функцию и вызывать ее по мере надобности. Например используем программу из урока 2:
/* Фоторезистор и светодиод www.samosdel.ru 14.05.2015 */ void setup() { // назначаем выводы, 10- выход pinMode(10, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { //вводим условие на получение данных if (analogRead(0)==0) { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } digitalWrite(13, LOW); analogWrite(10, analogRead(0)/4); Serial.println(analogRead(0)); delay(100); }
Допишем после всей программы такие строки:
void blink(){ digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second
а в теле программы удалим такие же строки и добавим вызов функции:
blink();
Программа примет следующий вид:
/* Фоторезистор и светодиод 14.05.2015 */ void setup() { // назначаем выводы, 10- выход pinMode(10, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { //вводим условие на получение данных if (analogRead(0)==0){ blink(); //вызываем функцию blink() } digitalWrite(13, LOW); analogWrite(10, analogRead(0)/4); Serial.println(analogRead(0)); delay(100); } void blink() //функция blink { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }
Теперь при обрыве резистора под фотодиодом будет так же выдаваться сигнализация об аварийном состоянии. Вы сразу спросите- как я пойму что именно испортилось- фоторезистор или подтягивающий резистор? Хороший вопрос. Но на это есть еще более лучший ответ. Мы можем передавать в функцию значения и она будет работать по этим значениям. Хочу сразу заметить что функции с оператором void не возвращают в программу никаких значений, передавать в них можно но что то получить- нет, поэтому их надо использовать только в каких то глобальных случаях. В нашем примере сделаем следующее: Вместо void blink() напишем int blink() — от этого совершенно ничего не изменится и программа так же будет работать. А вот теперь передадим нужные данные. Для этого допишем в int blink() —int blink(int x), заменим delay (1000); на delay (x); в обоих случаях. А в функции вызова целые значения, например blink (500); на обрыв фоторезистора и blink (1000); на обрыв подтягивающего резистора. Таким образом получим такую программу:
/* Фоторезистор и светодиод 14.05.2015 */ void setup() { // назначаем выводы, 10- выход pinMode(10, OUTPUT); pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { //вводим условие на получение данных if (analogRead(0)==0){ blink(500); //вызываем функцию blink() при обрыве фоторезистора } if (analogRead(0)>=1020){ blink(1000); //вызываем функцию blink() при обрыве подтягивающего резистора } digitalWrite(13, LOW); analogWrite(10, analogRead(0)/4); Serial.println(analogRead(0)); delay(100); } int blink(int x) //функция blink { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(x); // wait digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(x); // wait }
Теперь мы получаем разные сигналы при разных неисправностях! При обрыве фоторезистора светодиод будет мигать 2 раза в секунду, при обрыве подтягивающего резистора- 1 раз в секунду. Как мы это получили? При проверке уровня сигнала (если на входе 0) вызываем функцию blink со значением 500. Сама функция подставляет переданное значение в те места где мы ее прописали. Кроме того мы можем менять не только частоту мигания но и длительность свечения и длительность паузы. Попробуйте это сделать сами. Даю подсказку: в функции blink допишите int blink(int x, int y). Остальное попробуйте сами додумать. Если что то кому то непонятно- пишите в комментариях- разберем подробнее.
Таким образом функцией мы сэкономили занимаемую программой память. В противном случае пришлось бы писать на каждое условие обработчик события, здесь же мы использовали всего один обработчик и управляем им из тела основной программы. Хочу заметить что условий обычно очень много.
Кроме того мы можем присваивать высчитанное функцией значение любой переменной. Единственное условие -тип переменной должен соответствовать возвращаемому функцией значению.
Например: x=blink(50) где х- объявленная переменная в секции void setup(), blink(50)— функция с параметром 50. Для присваивания значения функции используется оператор return.
Например функция blink может выглядеть следующим образом:
int blink(int x) //функция blink { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(x); // wait digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(x); // wait return 100*x; }
Обратите внимание на тип функции int blink(int x)— в данном примере тип integer, значит и возвращаемые значения функции должны быть того же типа, т.е. integer. Данная функция возвращает значение 100*x (при этом следует помнить о пределах значений переменных и, если значения не вписываются, применить другой тип функции).