Про датчик движения и подключение его к Arduino

25.10.2016 19:00

jazon



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

Датчик движения, или датчик перемещения - устройство (прибор) обнаруживающий перемещение каких либо объектов. Очень часто эти устройства, используются в системах охраны, сигнализации и мониторинга. Форм факторов этих датчиков существует великое множество, но мы рассмотрим именно модуль датчика движения для подключения к платам Arduino, и именно от фирмы RobotDyn.  Почему именно этой фирмы? Я не хочу заниматься рекламой этого магазина и его продукции, но именно продукция данного магазина была выбрана в качестве лабораторных образцов благодаря качественной подаче своих изделий для конечного потребителя. Итак, встречаем - датчик движения(PIR Sensor) от фирмы RobotDyn:



Эти датчики малы по габаритам, потребляют мало энергии и просты в использовании. Кроме того - датчики движения фирмы RobotDyn имеют еще и маркированные шелкографией контакты, это конечно мелочь, но очень приятная. Ну а тем кто использует такие же датчики, но только других фирм, не стоит беспокоиться - все они имеют одинаковый функционал, и даже если не промаркированы контакты, то цоколёвку таких датчиков легко найти в интернете. 

Основные технические характеристики датчика движения(PIR Sensor):

Зона работы датчика: от 3 до 7 метров

Угол слежения: до 110о

Рабочее напряжение: 4,5...6 Вольт

Потребляемый ток: до 50мкА

Примечание: Стандартный функционал датчика можно расширить, подключив на пины IN и GND датчик освещенности, и тогда датчик движения будет срабатывать только в темноте.

Инициализация устройства.

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

Угол и область обнаружения.

Угол обнаружения(слежения) составляет 110 градусов, диапазон расстояния обнаружения от 3 до 7 метров, иллюстрация ниже показывает всё это:

 

Регулировка чувствительности(дистанции обнаружения) и временной задержки. 

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



Подключение датчика:

  • PIR Sensor[PIN GND] - Arduino Nano[PIN GND]
  • PIR Sensor[PIN 5V]   - Arduino Nano[PIN 5V]
  • PIR Sensor[PIN OUT] - Arduino Nano[PIN A0]
  • PIR Sensor[PIN IN] - для датчика освещенности
  • PIR Sensor[PIN GND] - для датчика освещенности

Типичная схема подключения дана на схеме ниже, в нашем случае датчик показан условно с тыльной стороны и подключен к плате Arduino Nano.



Скетч демонстрирующий работу датчика движения(используем программу Serial Monitor Pro):

/*
 * PIR Sensor[PIN GND] -> Arduino Nano[PIN GND]
 * PIR Sensor[PIN 5V]  -> Arduino Nano[PIN 5V]
 * PIR Sensor[PIN OUT] -> Arduino Nano[PIN A0]
 */
void setup() 
{
  //Установить соединение с монитором порта
  Serial.begin(9600);
}

void loop() 
{
  //Считываем пороговое значение с порта А0
  //обычно оно выше 500 если есть сигнал
  if(analogRead(A0) > 500)
  {
    //Сигнал с датчика движения
    Serial.println("Есть движение !!!");
  }
  else
  {
    //Нет сигнала
    Serial.println("Всё тихо...");
  }
}


Скетч является обычной проверкой работы датчика движения, в нём есть много недостатков, таких как:

  1. Возможные ложные срабатывания, датчику необходима самоинициализация в течение одной минуты.
  2. Жесткая привязка к монитору порта, нет выходных исполнительных устройств(реле, сирена, светоиндикация)
  3. Слишком короткое время сигнала на выходе датчика, при обнаружении движения необходимо программно задержать сигнал на более долгий период времени.

Усложнив схему и расширив функционал датчика, можно избежать вышеописанных недостатков. Для этого потребуется дополнить схему модулем реле и подключить обычную лампу на 220 вольт через данный модуль. Сам же модуль реле будет подключен к пину 3 на плате Arduino Nano. Итак принципиальная схема:


 

Теперь пришло время немного усовершенствовать скетч, которым проверялся датчик движения. Именно в скетче, будет реализована задержка выключения реле, так как сам датчик движения имеет слишком короткое время сигнала на выходе при срабатывании. Программа реализует 10-ти секундную задержку при срабатывании датчика. При желании это время можно увеличить или уменьшить, изменив значение переменной DelayValue . Ниже представлен скетч и видео работы всей собранной схемы:

/*
 * PIR Sensor[PIN GND]  -> Arduino Nano[PIN GND]
 * PIR Sensor[PIN 5V]   -> Arduino Nano[PIN 5V]
 * PIR Sensor[PIN OUT]  -> Arduino Nano[PIN A0]
 * Relay Module[PIN IN] -> Arduino Nano[PIN 3]
 */
 //relout - пин(выходной сигнал) для модуля реле
const int relout = 3;

//prevMillis - переменная для хранения времени предидущего цикла сканирования программы
//interval - временной интервал для отсчета секунд до выключения реле
unsigned long prevMillis = 0;
int interval = 1000;

//DelayValue - период в течение которого реле удерживается во включенном состоянии
int DelayValue = 10;

//initSecond - Переменная итерации цикла инициализации  
int initSecond = 60;

//countDelayOff - счетчик временных интервалов
static int countDelayOff = 0;

//trigger - флаг срабатывания датчика движения
static bool trigger = false;

void setup() 
{
  //Стандартная процедура инициализации порта на который подключен модуль реле
  //ВАЖНО!!! - чтобы модуль реле оставался в первоначально выключенном состоянии
  //и не срабатывал при инициализации, нужно записать в порт входа/выхода 
  //значение HIGH, это позволит избежать ложных "перещелкиваний", и сохранит 
  //состояние реле таким, каким оно было до включения всей схемы в работу
  pinMode(relout, OUTPUT);
  digitalWrite(relout, HIGH);

  //Здесь всё просто - ждем когда закончатся 60 циклов(переменная initSecond)
  //продолжительностью в 1 секунду, за это время датчик "самоинициализируется"
  for(int i = 0; i < initSecond; i ++)
  {
    delay(1000);
  }
}

void loop() 
{
  //Считать значение с аналогового порта А0
  //Если значение выше 500
  if(analogRead(A0) > 500)
  {
    //Установить флаг срабатывания датчика движения
    if(!trigger)
    {
      trigger = true;
    }
  }

  //Пока флаг срабатывания датчика движения установлен
  while(trigger)
  {
    //Выполнять следующие инструкции
    //Сохранить в переменной currMillis 
    //значение миллисекунд прошедших с момента начала 
    //выполнения программы
    unsigned long currMillis = millis();
    //Сравниваем с предидущим значением миллисекунд
    //если разница больше заданного интервала, то:
    if(currMillis - prevMillis > interval)
    {
      //Сохранить текущее значение миллисекунд в переменную prevMillis
      prevMillis = currMillis;
      //Проверяем счетчик задержки сравнивая его со значением периода 
      //в течение которого реле должно удерживаться во включенном 
      //состоянии
      if(countDelayOff >= DelayValue)
      {
        //Если значение сравнялось, то:
        //сбросить флаг срабатывания датчика движения
        trigger = false;
        //Обнулить счетчик задержки
        countDelayOff = 0;
        //Выключить реле
        digitalWrite(relout, HIGH);
        //Прервать цикл
        break;
      }
      else
      {
        //Если значение всё еще меньше, то
        //Инкрементировать счетчик задержки на единицу
        countDelayOff ++;
        //Удерживать реле во включенном состоянии
        digitalWrite(relout, LOW);
      }
    }
  }
}


В программе присутствует конструкция:

unsigned long prevMillis = 0;

int interval = 1000;

    ...

unsigned long currMillis = millis();

if(currMillis - prevMillis > interval)

{

    prevMillis = currMillis;

    ....

    // Наши операции заключенные в тело конструкции

    ....

}

Чтобы внести ясность, было решено отдельно прокомментировать эту конструкцию. Итак, данная конструкция позволяет выполнить как бы параллельную задачу в программе. Тело конструкции срабатывает примерно раз в секунду, этому способствует переменная interval. Сначала, переменной currMillis присваивается значение возвращаемое при вызове функции millis(). Функция millis() возвращает количество миллисекунд прошедших с начала программы. Если разница currMillis - prevMillis больше чем значение переменной interval то это означает, что уже прошло более секунды с начала выполнения программы, и нужно сохранить значение переменной currMillis в переменную prevMillis затем выполнить операции заключенные в теле конструкции. Если же разница currMillis - prevMillis меньше чем значение переменной interval, то между циклами сканирования программы еще не прошло секунды, и операции заключенные в теле конструкции пропускаются.   


Ну и в завершение статьи видео от автора:



Расскажи о нас

Сообщение

Если у Вас есть опыт в работе с Arduino и собственно есть время для творчества, мы приглашаем всех желающих стать авторами статей публикуемых на нашем портале. Это могут быть как уроки, так и рассказы о ваших экспериментах с Arduino. Описание различных датчиков и модулей. Советы и наставления начинающим. Пишите и размещайте свои статьи в соответсвующей ветке форума.