Этот урок будет посвящен одной из интереснейшей теме программирования- функциям. Что это такое? Это небольшая подпрограмма, находящаяся в теле основной программы, которую можно использовать много раз в течении одного цикла программы. С чем это можно сравнить? Приведу пример из жизни человека: например у нас есть функция дыхания. Мы даже не задумываемся- дышим и все с такой частотой с которой нужно организму, т.е. дыханием мы потребляем необходимое количество кислорода в воздухе. Мы можем дышать ровно и медленно когда спим, резко и часто когда заняты работой или спортом и т.д. Но функция дыхания у нас одна- мы просто дышим. Организм сам вызывает эту функцию когда ему надо. Так же и в программировании- мы можем определить функцию и вызывать ее по мере надобности. Например используем программу из урока 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 (при этом следует помнить о пределах значений переменных и, если значения не вписываются, применить другой тип функции).