Проблема с PIR датчиком

alexpzas
Offline
Зарегистрирован: 09.06.2013

Доброго времени суток. Вродебы простая задача но столкнулся со след. проблемой - есть вот такой датчик

http://arduino.shopium.ua/products/arduino-pir-sensor/  , по срабатыванию датчика должен включаться свет в комнате с пом. реле,на ардуину залил стандартный скетч из примеров


//Время калибровки датчика (10-60 сек. по даташиту)
int calibrationTime = 30;       

//Время, в которое был принят сигнал отсутствия движения(LOW)
long unsigned int lowIn;        

//Пауза, после которой движение считается оконченным
long unsigned int pause = 1000; 

//Флаг. false = значит движение уже обнаружено, true - уже известно, что движения нет
boolean lockLow = true;
//Флаг. Сигнализирует о необходимости запомнить время начала отсутствия движения
boolean takeLowTime; 

int pirPin = 41;    //вывод подключения PIR датчика
int ledPin = 50;   //вывод сигнального диода
int relayPin = 40;  //реле пин
int PhotoRPin = A8; //Фоторезистор
int PhotoRValue;

void setup()
{
  Serial.begin(9600);
  
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(relayPin, OUTPUT);

  //!ВНИМАНИЕ! При использовании n-p-n реле необходимо в след. строчке поменять HIGH на LOW
  digitalWrite(relayPin, LOW);
  delay(4000);
  digitalWrite(pirPin, LOW);

  //дадим датчику время на калибровку
  for(int i = 0; i < calibrationTime; i++)
  {
    //Во время калибровки будет мигать сигнальный диод
    i % 2 ? digitalWrite(ledPin, HIGH) : digitalWrite(ledPin, LOW);
    delay(1000);
  }
  //По окончанию калибровки зажжем сигнальный диод 
  digitalWrite(ledPin, HIGH);
  Serial.println("SENSOR ACTIVE");
  delay(50);
  dht.begin();
}

void loop()
{

  {
   PhotoRValue = analogRead(PhotoRPin); 
   Serial.println(PhotoRValue);
   delay(1000);
   }
  //Если обнаружено движение
  if(digitalRead(pirPin) == HIGH)
  {
    //Если до этого момента еще не включили реле
    if(lockLow)
    {
      lockLow = false;  

      //Включаем реле.
      //!ВНИМАНИЕ! При использовании n-p-n реле необходимо в след. строчке поменять LOW на HIGH
      if (PhotoRValue<50)
      {
       digitalWrite(relayPin, HIGH);
       digitalWrite(ledPin, HIGH);
       delay(50);
      }
    }        
    takeLowTime = true;
  }

  //Ели движения нет
  if(digitalRead(pirPin) == LOW)
  {      
    //Если время окончания движения еще не записано
    if(takeLowTime)
    {
      lowIn = millis();          //Сохраним время окончания движения
      takeLowTime = false;       //Изменим значения флага, чтобы больше не брать время, пока не будет нового движения
    }
    //Если время без движение превышает паузу => движение окончено
    if(!lockLow && millis() - lowIn > pause)
    { 
      //Изменяем значение флага, чтобы эта часть кода исполнилась лишь раз, до нового движения
      lockLow = true;                
      digitalWrite(relayPin, LOW);
      digitalWrite(ledPin, LOW);
       delay(50);
    } }}

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

 

alexpzas
Offline
Зарегистрирован: 09.06.2013

кстати переменную  long unsigned int pause = 1000; ставил значение и 180000, езультат тотже (((

alexpzas
Offline
Зарегистрирован: 09.06.2013

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

// Рабочая версия
#include <LiquidCrystal.h>
LiquidCrystal lcd(3, 4, 25, 24, 23, 22);
#include "DHT.h"
#define DHTPIN 2  
#define DHTTYPE DHT11 
DHT dht(DHTPIN, DHTTYPE);

//Время калибровки датчика (10-60 сек. по даташиту)
int calibrationTime = 30;       
//Время, в которое был принят сигнал  движения(HIGH)
long unsigned int timee;        
//Пауза, после которой движение считается оконченным
// 5 минут , таймер-резистр самого датчика стоит на минимуме 5 сек.
long unsigned int pause = 300000; 
int pirPin = 41;       //вывод подключения PIR датчика
int ledPin = 50;       //вывод сигнального диода (реле включено)
int ledPin2 = 44;       //вывод сигнального диода 2 (нет движения)
int relayPin = 40;     //реле пин
int PhotoRPin = A8;    //Фоторезистор
int PhotoRValue;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.print("Microklimat:");
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);  
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);
  delay(500);
  digitalWrite(pirPin, LOW);

  //дадим датчику время на калибровку
  for(int i = 0; i < calibrationTime; i++)
  {
    //Во время калибровки будет мигать сигнальный диод
    i % 2 ? digitalWrite(ledPin, HIGH) : digitalWrite(ledPin, LOW);
    delay(1000);
  }
  //По окончанию калибровки зажжем сигнальный диод 
  digitalWrite(ledPin, LOW);
  digitalWrite(ledPin2, LOW);
  Serial.println("SENSOR ACTIVE");
  delay(50);
  dht.begin();
}

void loop()
{
  //выводим температуру и влажность на екранчик
 lcd.setCursor(0, 1);
 float h = dht.readHumidity();
 float t = dht.readTemperature();
    if (isnan(t) || isnan(h)) {
    lcd.print("Temp-ra error");
  } else {
    lcd.print("C=");
    lcd.print(t);
    lcd.print(" H=");
    lcd.print(h);
  }
  {
   PhotoRValue = analogRead(PhotoRPin); 
   delay(1000);
   }
  //Если обнаружено движение
  if(digitalRead(pirPin) == HIGH)
  {
    // Записываем время когда началось дижение
     timee=millis();
     digitalWrite(ledPin2, LOW);
     // Проверяем освещённость в комнате
      if (PhotoRValue<50)
      {
      //Включаем реле.
       digitalWrite(relayPin, HIGH);
       digitalWrite(ledPin, HIGH);
      // delay(50);
      }        
   }
  //Ели движения нет
  if(digitalRead(pirPin) == LOW)
  {   
    digitalWrite(ledPin2, HIGH);   
    //Если время без движение превышает паузу => движение окончено
    if(millis()- timee > pause)
    { 
      digitalWrite(relayPin, LOW);
      digitalWrite(ledPin, LOW);
       // delay(50);
      }
  }
}

 

ourlive
Offline
Зарегистрирован: 26.05.2012

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

msng
Offline
Зарегистрирован: 07.06.2012

датчик и так должен работать, без ардуино

на нем есть два подстроечных сопротивления Sx - чувствительность и Tx - время

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

покупал подобный датчик только на ebay, очень похож на Ваш только питание у него до 20в.

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
long unsigned int pause = 300000;

это корректно?

alexpzas
Offline
Зарегистрирован: 09.06.2013

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

long unsigned int pause = 300000; 

Взято из примера (неработающего), так как компилятор не ругался, так его и оставил, по умолчанию работает, но как я понимаю можно оставить в таком виде

int pause = 300000; 
ourlive
Offline
Зарегистрирован: 26.05.2012

для начала выставите минимальное время на датчике аппаратно, потом выясните какой тип переменной в millis(), убедитесь, что это не int и переназначте переменную pause и timee правильным типом.

vovanxp
vovanxp аватар
Offline
Зарегистрирован: 19.10.2014
Здравствуйте,можно использовать arduino UNO вместо mega?
 
 
 

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Можно, разрешаем.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

vovanxp пишет:

Здравствуйте,можно использовать arduino UNO вместо mega?

Меньше памяти, меньше ног, меньше uart, меньше прерываний.

Эсли все это не существенно - используйте Уно вместо Меги.

Giza
Offline
Зарегистрирован: 06.06.2016

Подскажите,такая проблема у меня в терминале все время идут записи "motion detected" и L постоянно мигает. В чем проблема? 

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Проблема или в скетче, или в железе.

Giza
Offline
Зарегистрирован: 06.06.2016

Можно по подробнее плиз,в скетче все номально а датчик движения у менятакой ,ниже фото датчика,на ардуино он все время подет единичку

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Ну раз в скетче всё нормально, то замеряйте выход (который на ардуину идет) мультиметром, тоже будет все время единичку выдавать?

Giza
Offline
Зарегистрирован: 06.06.2016

Мультиметр ничего не дает,хотя он работает. Не понимаю в чем дело,датчик сам работает мигает когда движение есть,а сигнальный выход (2 провода желтый и зеленый) все время подает единичку на ардуино и на ардуино L  все время мигает,хотя он должен мигать каогда есть движение. (Просто я "чайник" в этом деле)

popUP
Offline
Зарегистрирован: 09.10.2014

Может Что-то поможет Вам из моего небогатого опыта.

Я далеко не специалист по датчикам движения, но вот на дня себе собирал упражнение с использованием простого датчика для ардуинки, активно гуглил и тут читал. 

Может Вам поможет поискать где-то подробнее вот такое мое наблюдение, подтвержденное тут на форуме в какой-то статье: когда датчик сработал и идет время аппаратной задержки (ваши 3 минуты) он нихрена не ловил новых движений в принципе, точнее не выдавал в ничего кроме 1 во все время задержки. Т.е. как я читал и опробовал, задержка нужна для того, чтобы пока она есть подключенное устройство, например реле, было активно. Вряд ли там есть какая-то сложная логика. Может у Вас устройство наворочено более чем http://ru.aliexpress.com/item/1pcs-High-Quality-HC-SR501-Infrared-PIR-Mo...

Я у себя ставил задержку на датчике в минимум, а лампочку засвечивал программно ардуинкой. в это время сигналы от датчика накапливал. Кода не дам, не сохранил, меня в конце концов устроила аппаратная задержка датчика, а то, что я наваял - слегка где-то глючило :)

Вот мой код на сегодня, если интересно. В следующей версии избавился от Delay по многочисленным советам тутошних Гуру, чего и вам советую, а то во время после чтения датчика в строке 67, ничего другого у вас не происходит.

/* 
 Подключены устройства
 - Arduino Nano v3
 - LCD 20x4      i2c
 - RTC DS1307    i2c
 Подключены датчики
 - DHT 11  температура и влажность  
 - LN35    температура   
 - PIR     движения
 - Photo   фоторезистор + 10 kOm
 Ну и еще
 - КТ 973 (2 шт) , резистор 2.2kOm, диод на обратный ток, на линии 12В
 - КТ 972 (2 шт) резистор 10kOm,на линии 12В
 - Спикер с конденсатором на 10 mf
 */

//подключаем библиотеки
#include <Wire.h>
#include <RTClib.h>
#include "DHT.h"
#include <LiquidCrystal_I2C.h>

//назначаем пины

// ВХОДЫ
#define DHTPIN A0      // Датчик Температуры и влажности
int tempPin  = A1;      // Датчик Температуры LN 35
int photoPin = A2;    // Датчик освещенности - фоторезистор? плюс на выход REF (1.1в)
int pirPin   = A3;       // Датчик движения 

//ВЫХОДЫ
int spkPin = 6;       // Спикер
int lednightPin = 9;    // Транзистор включающий Ночник
int ledtablePin = 10;   // Транзистор включающий Стол
int fanPin = 11;         // Транзистор включающий Кулер

// Объявляем что можем
RTC_DS1307 RTC;                      // Часы
LiquidCrystal_I2C lcd(0x27,20,4);    // адрес LCD

#define DHTTYPE DHT11                 // DHT 11  
//#define DHTTYPE DHT22                 // D 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE, 6);

// И переменные
float tempC;        //для датчика температуры LN35
int reading;        //для датчика температуры LN35

int t;              // для DHT
int h;              // для DHT

int Light;          // Для фоторезистора
int LightR;

long unsigned int lowIn;           // для датчика движения
long unsigned int pause = 5000;    // для датчика движения
boolean lockLow = true;            // для датчика движения
boolean takeLowTime;               // для датчика движения

int FAN_pwm = 100;                 // Значение от 0...255 (0 - 5в)

/////*******************************************************************************
void setup() {

  Serial.begin(9600);
  Wire.begin();
  dht.begin();   /// Starting DHT

  RTC.begin();
  //RTC.adjust(DateTime(__DATE__, __TIME__));             // установка времени на часах по времени компьютера

  // Запускаем приветствие на LCD
  lcd.init();                       
  lcd.backlight();   
  lcd.clear();   
  lcd.setCursor(0, 1);
  lcd.print("     P R I V E T ");  
  lcd.setCursor(0, 2);
  lcd.print("     SWEET  HOME");  
  delay (1000); 
  lcd.clear(); 

   // Режимы входов-выходов, включаем подтягивающие резисторы, где надо
  // устанавливаем начальные значения вкл/выкл
  pinMode(pirPin, INPUT);
   digitalWrite(pirPin, LOW);     //было в примере
  pinMode (tempPin, INPUT); 
 //  digitalWrite (tempPin, HIGH);   /// если включаю - перестает меняться значение на датчике, 1023
  pinMode(photoPin, INPUT);
  // digitalWrite(photoPin,LOW); 

  pinMode (spkPin, OUTPUT); 
  pinMode (lednightPin, OUTPUT);  
  // digitalWrite(lednightPin, HIGH);   // тут KT972, закрыт при HIGH
  pinMode (ledtablePin, OUTPUT);  
  // digitalWrite(ledtablePin, HIGH);   // тут KT972, закрыт при HIGH
  pinMode (fanPin, OUTPUT);  
  // digitalWrite(fanPin, LOW);          // тут KT973, закрыт при LOW


  // пикнем любым способом, tone проще
  tone (spkPin, 700, 100);                //noTone (SPK_pin);  // отключает сигнал, если нет длительности
  //analogWrite (SPK_pin, 10);   delay(500);  analogWrite (SPK_pin, 0);

}


//////// Ц И К Л /////////////////////////////////

void loop() {

  READ_DATA();
  LCDPRN ();
  PIR_start();
  // FAN_start();
  TABLE_start ();
  delay(500);
}

////Подпрограммы ****************************************************************
////////????????????????????????????????????????????????????????????????/////////
void READ_DATA (){
 // delay(250);
  analogReference(INTERNAL);
  reading = analogRead(tempPin);   //// чтение показаний датчика LN35 
  //tempC = (reading/1024.0)*5000/10;   // для расчета с опорным напряжением по дефолту (5в)
  tempC = reading/9.31;                  // для расчета с опорным напряжением INTERNAL (1.1в)

  h = dht.readHumidity();          // Чтение DHT 11
  t = dht.readTemperature();
  
//  delay(250);                      // вроде как рекомендуют паузу между чтением аналоговых выходов ?
  analogReference(DEFAULT); 
  Light = analogRead(photoPin);   // Чтение фоторезистора
  LightR = Light;
}

///////////////////////////////////////
void PIR_start(){
  if(digitalRead(pirPin) == HIGH && Light > 500){
    analogWrite(lednightPin, 180);   //the led visualizes the sensors output pin state
  }
  if(digitalRead(pirPin) == LOW){       
    analogWrite(lednightPin, 255);  
    // digitalWrite(lednightPin, HIGH);  
  }
}
///////////////////////////////////////
void TABLE_start (){
  if (Light < 500){ 
    //  digitalWrite (ledtablePin, HIGH);
    analogWrite (ledtablePin, 255);
  }
  else if (Light > 500){ 
    analogWrite (ledtablePin, 150);
  }
  if (Light > 700)
  {
    analogWrite (ledtablePin, 50);
  } 
}
/////////////////////////////////////////////////////////////////////////
void LCDPRN (){
   
  DateTime now = RTC.now();
  lcd.setCursor(0,0); 
  lcd.print(now.day(), DEC); 
  lcd.print('/'); 
  lcd.print(now.month(), DEC); 
  lcd.print('/');  
  lcd.print(now.year(), DEC);   

  lcd.setCursor(11, 0);  
  lcd.print(' ');  
  if (now.hour() <10) {
    lcd.print(' ');
  }
  lcd.print(now.hour(), DEC);  
  lcd.print(':'); 
  lcd.setCursor(15, 0); 
  if (now.minute() <10) {
    lcd.print('0');
  }
  lcd.print(now.minute(), DEC);   
  lcd.print(':');  
  lcd.setCursor(18, 0);  
  if (now.second() <10) {
    lcd.print('0');
  }
  lcd.print(now.second(), DEC);

  lcd.setCursor(0, 1);
  lcd.print("TEMP:");
  if (t>=0&t<10) lcd.print(' ');
  if (t<0&t>-10) lcd.print(' ');
  lcd.print(t);   
  lcd.print("C  HUMID:");
  lcd.print(h);   
  lcd.print("% ");

  lcd.setCursor(0, 3);
  lcd.print("L      "); 
  lcd.setCursor(2, 3);
  lcd.print(LightR);

  lcd.setCursor(7, 3);
  lcd.print(" SHELF      "); 
  lcd.setCursor(14, 3);
  lcd.print(tempC);
    //lcd.print(reading);
}

/////////////////////////////////////////////////////////////////
void FAN_start(){

  if (tempC <=25 ){
    FAN_pwm = 0;
    analogWrite (fanPin, FAN_pwm);
    //    digitalWrite (fanPin, LOW);
    //   lcd.setCursor(16, 3);
    //   lcd.print(" -");
  }
  if (tempC > 25 ){
    FAN_pwm = 150;
    analogWrite (fanPin, FAN_pwm);
    //   lcd.setCursor(16, 3);
    //   lcd.print(" *");
  }
  if (tempC > 28 ){
    FAN_pwm = 200;
    //   lcd.setCursor(16, 3);
    //   lcd.print("**");
    analogWrite (fanPin, FAN_pwm);
  }
  if (tempC >34 ){
    FAN_pwm = 255;
    //    lcd.setCursor(16, 3);
    //    lcd.print("**");
    analogWrite (fanPin, FAN_pwm);
    tone (spkPin, 2000, 500);
  } 
}





 

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

Если в Вашем PIR стоит микросхема BISS0001 (скорее всего это так), то у неё два режима работы  выходной логики. 1. - добавление времени включения к текущему на первоначально заданную величину тоесть при попадании сигнала в зону захвата PIR датчика (а он довольно чувствительный, хватает небольшого движения руки)  происходит продление выходного сигнала (на выходе будет постоянно присутствовать "1"). 2. - блокировка датчика PIR на время установленой задержки тоесть отрабатывается полное времы задержки и происходит переход выхода в "0" и только после этого появляется возможность повторного включения. Режимы работы выбираются перемычками на плате или прямой подачей иправляющего сигнала на ножку микросхемы (в даташите всё есть).

 

s1981
Offline
Зарегистрирован: 22.12.2013

Помогите разобраться. Без реле все работает нормально. подключаю реле, реле включается при движении и все когда гаснет диод движения, оно щелкает и остается включенным, так до бесконечности.