Выбрать главу

state = 1 - state;

Такая строка не имеет смысла в математике, но он есть при программировании. Знак "=" означает "присвоить результат выражения после меня переменной передо мной" - в данном случае, новое значение state будет вычислено как единица минус старое значение state.

Далее в программе вы видите, что мы используем state для выяснения должен-ли светодиод быть включён или выключен. Как я говорил, это приводит к странному результату.

Результат странный из-за способа считывания кнопки. Arduino очень быстрая; она выполняет свои команды со скоростью 16 миллионов в секунду - вполне может быть, что и несколько миллионов строк кода за секунду. Это означает что пока ваш палец нажимает кнопку, Arduino может снять данные с кнопки несколько сотен раз и изменить столько-же раз состояние светодиода. Результат непредсказуем; светодиод может остаться выключённым когда вы хотите его включить и наоборот. Поскольку даже сломанные часы показывают верное время дважды в день, программа может выдавать верный результат каждый раз какое-то время, но и долгое время - неправильный.

Как ним исправить эту ситуацию? Требуется определить момент нажатися конпки - именно в этот момент следует изменять state. Способ, который мне нравится, таков - хранить старое значение val перед считыванием нового; это позволяет мне сравнить текущее положение кнопки с предыдущим и изменить state только когда кнопка стала "HIGH" после того, как была "LOW".

Пример 4-4 содержит следующий код:

Пример 4-4. Включить светодиод при нажатии кнопки и оставить его включённым после отпускания кнопки с новой, улучшеной формулой!

#define LED  13   // the pin for the LED

#define BUTTON 7  // the input pin where the

                  // pushbutton is connected

int val = 0; // val will be used to store the state

                  // of the input pin

int old_val = 0; // this variable stores the previous

                  // value of "val"

int state = 0; // 0 = LED off and 1 = LED on

void setup() {

  pinMode(LED, OUTPUT); // tell Arduino LED is an output

  pinMode(BUTTON, INPUT); // and BUTTON is an input

}

void loop(){

  val = digitalRead(BUTTON); // read input value and store it

                             // yum, fresh

  // check if there was a transition

  if ((val == HIGH) && (old_val == LOW)){

    state = 1 - state;

  }

  old_val = val;  // val is now old, let's store it

  if (state == 1) {

    digitalWrite(LED, HIGH); // turn LED ON

  } else {

    digitalWrite(LED, LOW);

  }

}

Попробуйте код, мы почти закончили!

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

Когда кнопка "дребезжит", Arduino видит быструю последовательность сигналов включения и выключения. Существует множество видов антидребезга, но для нашего, простого кода, я заметил что достаточно добавить 10...50-миллисекундную задержку чтобы код определил изменение.

Окончательный код показан в примере 4-5.

Пример 4-5. Включить светодиод при нажатии кнопки и оставить его включённым после отпускания кнопки, включая простой антидребезг. Теперь с новой, улучшенной формулой!

#define LED  13   // the pin for the LED

#define BUTTON 7  // the input pin where the

                  // pushbutton is connected

int val = 0; // val will be used to store the state

                  // of the input pin

int old_val = 0; // this variable stores the previous

                  // value of "val"

int state = 0; // 0 = LED off and 1 = LED on

void setup() {

  pinMode(LED, OUTPUT); // tell Arduino LED is an output

  pinMode(BUTTON, INPUT); // and BUTTON is an input

}

void loop(){

  val = digitalRead(BUTTON); // read input value and store it

                              // yum, fresh

  // check if there was a transition

  if ((val == HIGH) && (old_val == LOW)){

    state = 1 - state;

    delay(10);

  }

  old_val = val; // val is now old, let's store it

  if (state == 1) {

    digitalWrite(LED, HIGH); // turn LED ON

  } else {

    digitalWrite(LED, LOW);

  }

5. Продвинутый ввод-вывод

Всё, что мы изучили в четвёртой главе - в большинстве простейшие операции, которые мы можем делать с Arduino: управлять цифровым выводом и читать цифровод ввод. Если бы Arduino был разговорным языком, это было бы всего лишь двумя буквами алфавита. Учитывая то, что в этом алфавите всего пять букв, вы можете увидеть сколько еще работы надо сделать чтобы писать поэмы на Arduino.

5.1 Пробуем другие датчики включения-выключения

5.1.1 Выключатели

То-же самое что и кнопка, но не изменяет своё состоянии при отпускании.

5.1.2 Термостаты

Выключатель, который срабатывает при достижении установленной температуры.

5.1.3 Магнитные переключатели, также известные как "герконы"

Имеют два контакта, которые соединяются если рядом расположить магнит, используются в сигнализации против взлома для определения открытого окна.

5.1.4 Ковровые переключатели

Маленькие пластинки, которые можно положить под ковёр чтобы определить присутствие человека (или тяжёлого кота).

5.1.5 Датчики наклона

Простой электронный компонент, сделанный из двух контактов и маленького металлического шарика (или капельки ртути, но я не рекомендую использовать такие). Рис. 5-1 показывает внутренности типичной модели. Когда датчик расположен вертикально, шарик замыкает оба контакта, и устройство работает как если-бы вы нажали кнопку. Когда вы наклоняете датчик, шарик движется и контакты размыкаются, как если-бы вы отпустили кнопку. Используя такой простой компонент, вы можете создавать, например, интерфейсы управления жестами, которые реагируют на движения или встряхивание обьекта.

Рис. 5-1. Конструкция датчика наклона

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

Рис. 5-2. Типичный инфракрасный датчик

Теперь вы можете поэкспериментировать, найдя всевозможные устройства, имеющие два замыкающихся контакта, такие как термостат, управляющий температурой в комнате (используйте старый, который не подключён к системе), или просто расположив рядом два контакта и капнув на них водой.