Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Основы программирования

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

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

Во-первых, нам придётся писать примеры на C++-подобном языке. Поэтому можете похвастаться перед знакомыми, что пишите программы на C++. Во-вторых, он очень упрощённый, и вам не нужно бояться его.

Если помните, мы запускали учебный пример Blink, но на самом деле мы пропустили самый первый учебный пример BareMinimum. Давайте его откроем: File→Examples→1.Basics→BareMinimum. Откроется окно с следующим кодом:


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Вам сейчас необходимо запомнить, что в программе должны быть две обязательные функции: setup() и loop(). После названия функции и круглых скобок идут фигурные скобки, внутри которых будет располагаться ваш код. Говорят, что между фигурными скобками располагается блок кода для функции или тело функции.

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

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

Рекомендую создать новый пустой скетч (так называют программы в Arduino) через File | New... (Файл | Создать) и вручную написать описанный код. Это поможет вам лучше запомнить две функции, а также увидеть, как работает среда разработки.

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

В функции setup() мы видим три строчки:


// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

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

Приблизительный перевод комментариев, которые используется в функции setup() можно перевести как:


// инициализируем цифровой порт как вывод

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


pinMode(led, OUTPUT);

В старых версиях код был немного другим:


pinMode(13, OUTPUT);

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


// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

Комментарий можно перевести как:


// Порт 13 в большинстве плат Arduino соединен со светодиодом

Нам встретилась новая функция pinMode(), которая устанавливает режим для портов. Функция состоит из двух параметров. В первом параметре указывается порт, с которым мы собираемся работать. Во втором параметре мы сообщаем, как должен работать указанный порт: работать на выход (OUTPUT) или вход (INPUT). В нашем примере, вывод под номером 13 должен выводить информацию (посылать сигнал), то есть давать указание мигать светодиоду.

Мы определили в функции setup() необходимые данные для начала работы и теперь можем приступить к непосредственной реализации задачи в функции loop().


// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Здесь мы видим уже четыре строчки кода. Первая строчка включает светодиод при помощи функции digitalWrite(). В первом параметре мы указываем номер порта, с которым собираемся работать, а во второй указываем константу HIGH. Забегая вперед, могу сказать что константа HIGH равна 1, и можно было написать digitalWrite(13, 1). Но такая запись не очень удобна, так мельтешение цифр в большом проекте затрудняет чтение кода. А здесь вы сразу видите, что на порту под номером 13 включается светодиод.

Далее идет команда, отвечающая за паузу - delay(), которая имеет один параметр - количество времени в миллисекундах. В нашем примере мы сделали паузу в одну секунду (1000 миллисекунд = 1 сек).

Следом идёт уже знакомая нам функция digitalWrite(), но уже с параметром LOW, который выключает светодиод (значение константы LOW равно 0).

И последняя строчка снова делает паузу в одну секунду.

Посмотрим, как работает программа. Когда мы загружаем программу в микроконтроллер, то Arduino активирует порт 13 в режиме выхода (функция setup()), а затем начинает последовательно выполнять четыре строчки из функции loop(): включает диод-пауза-выключает диод-пауза. Когда эти четыре строчки будут выполнены, то они снова будут вызваны и будут повторяться до тех пор, пока мы не выдернем кабель.

Что мы можем изменить в данной программе? По большому счету ничего - мы можем установить только собственные значения пауз. Поэкспериментируйте с этим. Другие изменения результата не принесут - нет смысла, например, сейчас использовать другой порт или использовать режим INPUT.

Если вы хотите что-то исправить в готовой программе из примеров, то лучше это делать в новом проекте. Создайте свой скетч и скопируйте код из примера Blink. Для начала измените значения микросекунд для паузы. Теперь попробуем написать свою собственную программу на её основе. Вам понадобится обычный провод. Один конец вставляем в порт под номером 7, а второй в порт с надписью GND.

Задумка следующая. Порт может не только принимать сигнал (работать на выход), но и посылать сигнал. Фактически порт пускает через себя ток. В этом случае режим устанавливается как INPUT или INPUT_PULLUP. Если через порт идёт ток, то заставим светодиод мигать быстро-быстро. Если движение тока прервано, то мигание будет редким.


int ledPin = 13;
int switchPin = 7;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
}

void loop()
{
  if(digitalRead(switchPin) == LOW)
  { 
    flashLed(100);
  }
  else
  {
    flashLed(500);
  }
}
  
void flashLed(int delayPeriod)
{
  digitalWrite(ledPin, HIGH);
  delay(delayPeriod);
  digitalWrite(ledPin, LOW);
  delay(delayPeriod);
}

Часть кода нам уже знакома. Смотрим на новый код. Для опытов мы используем порт 7, поэтому завели новую переменную switchPin. В функции setup() мы устанавливаем для него режим на вход в особом режиме INPUT_PULLUP (подтягивающий резистор). Его особенность состоит в том, что при соединении с землёй он будет выдавать значение LOW, а при разрыве - HIGH

В функции loop() мы реализуем условие с проверкой. Считываем значение с порта 7. Если ток идёт, то значение будет LOW светодиод будет мигать часто. В противном случае светодиод будет мигать редко.

Код для мигания светодиодом вынесен в отдельную функцию flashLed(). Это сэкономит нам количество кода. Кроме того, такая функция удобна, что мы можем в её параметре задавать разные значение паузы, не повторяя остальной код.

Запустив проект, убедимся, что светодиод мигает часто. Вытащим один конец провода и увидим, что светодиод стал мигать медленно. Опять вставляем провод на место и снова светодиод будет мигать часто. Чудеса!

INPUT_PULLUP

Когда мы подключаем плату Arduino к компьютеру через USB-порт, то можем обмениваться между ними информацией с помощью сообщений, которые отображаются в Serial Monitor. О Serial Monitor мы поговорим позже в других статьях, пока поверхностно познакомимся с ним. Допустим, у нас сгорел светодиод и он не сможет нам показать своим миганием, есть ли соединение или нет. Уберём из кода строки, относящиеся к светодиоду, и напишем код для обмена сообщениями.


//int ledPin = 13;
int switchPin = 7;

void setup()
{
  //pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop()
{
  if(digitalRead(switchPin) == LOW)
  { 
    //flashLed(100);
    Serial.println("Connected");
  }
  else
  {
    //flashLed(500);
    Serial.println("Not connected");
  }
}

Лишний код закомментирован, а функция flashLed() даже удалена. Как пользоваться программой? Запустите скетч снова, затем в Arduino IDE нажмите на значок Serial Monitor. Откроется новое окно, в котором будут быстро мелькать строки Connected с новой строки. Выдерните провод и в окне сообщения сменятся на Not connected. Таким образом, плата посылает информацию компьютеру.

На следующих занятиях мы подключим свой светодиод и заставим его не только мигать, но и затухать. Оставайтесь с нами!

Реклама