25.01.2010

Уроки Wiring (3)

Урок 3. Из чего сделан скетч?

(продолжение, начало см. Урок 2. ArduinoIDE)

В предыдущем уроке мы даже толком не разобрали текст нашего скетча "Blink". Присмотримся к нему повнимательнее:

/*
  Blink
 
 Turns on an LED on for one second, then off for one second, repeatedly.
 
 The circuit:
 * LED connected from digital pin 13 to ground.
 
 * Note: On most Arduino boards, there is already an LED on the board
 connected to pin 13, so you don't need any extra components for this example.
 
 
 Created 1 June 2005
 By David Cuartielles
 
 http://arduino.cc/en/Tutorial/Blink
 
 based on an orginal by H. Barragan for the Wiring i/o board
 
 */

int ledPin =  13;    // LED connected to digital pin 13

// The setup() method runs once, when the sketch starts

void setup()   {                
  // initialize the digital pin as an output:
  pinMode(ledPin, OUTPUT);     
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                     
{
  digitalWrite(ledPin, HIGH);   // set the LED on
  delay(1000);                  // wait for a second
  digitalWrite(ledPin, LOW);    // set the LED off
  delay(1000);                  // wait for a second
}

Поспешу оговориться: если вы уже программировали на C/С++, разобраться не составит труда. Остальным придется потрудиться, но помните: язык создавался с оглядкой на дизайнеров (людей гуманитарного склада ума), что вынудило авторов сто раз думать о простоте и понятности, прежде чем вводить новый оператор в синтаксис.

Первым делом, отбросим комментарии. Это такой произвольный текст пояснительного характера, который программист вставляет в текст программы, дабы не запамятовать, что же он там понаделал три года назад. Справедливости ради - есть масса других способов этого добиться, например правильно называть переменные.

Пока что запомните: если в строке встретилось два слеша //, то они, вместе со всеми символы правее, до конца этой строки компилятору глубоко безразличны. Если в комментарий надо превратить сразу несколько строк, то его начинают с  /* и заканчивают */.   Таким образом, вышеприведенный код для компилятора будет значительно проще и короче:

int ledPin =  13;

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

void loop()                     
{
  digitalWrite(ledPin, HIGH);   
  delay(1000);                  
  digitalWrite(ledPin, LOW);   
  delay(1000);                  
}


Кстати, комментирование применяют и для отладки, чтобы временно "выключить" фрагмент скетча. В ArduinoIDE для этого есть горячая клавиша Ctrl+/, которая позволяет быстро закомментировать или раскомментировать выделенный фрагмент текста.

Итак, первая строка скетча:

int ledPin =  13;

Это объявление переменной с именем ledPin. Компилятор забронирует в памяти микроконтроллера пару байт для хранения целого числа, позволяя вам начиная с этого места обращаться к нему по имени 'ledPin'. Заодно он присвоит ему начальное значение 13.

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

void setup() {
}

Забегая вперед - это определение функции. Однако, функция setup особенная: она исполняется один раз после старта скетча (по включению питания Arduino или после сброса). Туда можно смело вынести все действия, которые должны выполниться один раз, например - настройка скорости последовательного порта или выбор режима работы универсальных пинов (на ввод или на вывод). Все эти действия должны быть вписаны между открывающей и закрывающей фигурными скобками { }.

И, кстати, сейчас там только одна строчка:

pinMode(ledPin, OUTPUT);

Оператор языка Wiring 'pinMode' устанавливает для одного из указанных пинов режим ввода или вывода. В данном случае номер пина берется из переменной ledPin (напоминаю, что там было число 13, а следовательно - речь про digital13, к которому подключен тестовый светодиод L), режим задается константой OUTPUT, что логически подготавливает нас к тому, что через этот пин будет что-то выводиться.

Если понадобится сделать из тринадцатого пина вход, используйте константу INPUT. Но по умолчанию все цифровые пины после старта скетча и так уже находятся в режиме ввода. И еще одно важное замечание: режим вход/выход можно переключать в процессе работы скетча, сколько угодно раз! Главное, чтобы схема была для этого предназначена.

void loop() {
}

Функция loop также должна быть в любом скетче - она вызывается сразу после завершения setup, а потом снова и снова... до бесконечности. Может быть, это покажется вам немного странным, но в применении к микроконтроллерам вообще и к Ардуино в частности, встречается довольно часто: надо постоянно опрашивать кнопки и датчики, давать команды на моторы или реле, выводить данные на дисплей. Собственно, именно поэтому однократно исполняемые действия и вынесены в setup - если что-то надо сделать один раз, сделайте именно в ней.

Разберем, из чего состоит тело loop:

digitalWrite(ledPin, HIGH);

Это еще один оператор языка Wiring, который переключает состояние пина в одно из двух возможных. HIGH соответствует логической единице (она же - напряжение питания микроконтроллера, для Duemilanova это +5 Вольт), LOW - логическому нулю, это меньше +0,5 В.

Светодиод L подключен в Arduino следующим образом:



Анатомию этой схемы мы разберем позже, пока стоит запомнить, что если на пине Ардуино установить напряжение , светодиод начнет светиться - как говорят, он "откроется" и через него потечет ток. Если же на этом входе будет меньше 1,5В, то этого напряжения не хватит для его открывания, и он обидится светиться не будет.

Итак, оператор digitalWrite(ledPin, HIGH) формирует +5В на выходе 13 и зажигает таким образом светодиод L.

delay(1000);

Эта команда delay заставляет микроконтроллер остановиться и ничего не делать целую 1000 миллисекунд - безумно много! Кстати, 1000 мс = 1 с ;)

digitalWrite(ledPin, LOW);

Этой командой светодиод отключается (см. выше).
Дальше снова происходит задержка в одну секунду.
А потом... тело loop заканчивается, но поскольку он вызывается беспрерывно, то управление снова переходит на начало - исполняется digitalWrite(ledPin, HIGH), и так далее.

Визуально можно представить так:



Если бы у нас под руками был специальный прибор осциллограф, то подключив его к digital13 мы увидели бы примерно такую картину:



Говоря строгим языком, мы добились на этом выходе колебаний с частотой 0,5 Гц ( 1 Гц  соответствует одному полному колебанию в секунду). Меняя две величины задержки в delay, можно добиваться другой частоты мигания, а если они начать менять их отношение, то изменится скважность сигнала (сейчас мы получили то, что обычно называют меандр).

Но чтобы пользоваться Arduino все это знать необязательно. Все мигает, как и задумано, не так ли? ;)

В качестве домашнего задания: попробуйте поправить скетч таким образом, чтобы светодиод мигал не равномерно, как сейчас, а периодически подмигивал 3-х кратными вспышками. Какая задержка должна быть между вспышками, чтобы глаз их все еще различал?

В следующем уроке мы подробнее разберем основные конструкции языка Wiring.

3 комментария:

  1. Ответы
    1. Не согласен ;) Перечитайте википедию на эту тему, что ли ;)

      Удалить
  2. Мне кажется, автор недооценивает (не понимает?) значение комментариев. Самодокументируемый код (с "правильными" названиями переменных) может сообщить лишь, ЧТО делает программа, а комментарии нужны, чтобы сообщить - ЗАЧЕМ.

    ОтветитьУдалить