Подключение pir датчика d203s к ардуино.

Farmatsevt
Farmatsevt аватар
Offline
Зарегистрирован: 27.09.2018

Здравствуйте. Можно ли подключить инфракрасный датчик движения d203s напрямую к ардуино, и сложно ли будет писать под это дело код?

Мне нужно сделать автоматическую включалку света на этом датчике. Зачем ардуино? Дело в том, что я хочу приделать сюда и фоторезистор, и, соответственно должно получается так: если за окном темно инфракрасный датчик работает и фиксирует движения, если светло, то работать он не должен. Так же для того, чтобы прописать все необходимые задержки, чтобы, например, при случайном коротковременном затенении фоторезистора сразу он не срабатывал. Ардуинку планируют использовать маленькую, на attiny85.

P.S. Готовая платка из Китая с этим датчиком меня по ряду причин не устроила, поэтому прошу её, как решение проблемы, не предлагать.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Можно.

Почему именно на этом датчике? есть более подходящие для ARduino

На attiny 85 сами перепишите (с АЦП для определения освещенности придется помучаться, возьмите лучше ProMini), уберите датчик DHT и BT модуль обмена:

#include <EEPROM.h>
#include "DHT.h"
#include <SoftwareSerial.h>

#define LBLUE 10
#define LGREEN 11
#define LRED 12
#define FRES1 A0
#define FRES2 A2
#define CYCLE_GET_TEMP 307
#define RELAY1 8 //lamp
#define RELAY2 9
#define RCWL 7
#define RIP 6
#define DHTPIN 5
#define BTRXD 4
#define BTTXD 3
#define BTKEY 2
#define BTSTATUS A4

SoftwareSerial BT(BTTXD, BTRXD);
DHT dht(DHTPIN, DHT22);

unsigned long timerSec = 0;
unsigned int timerGetTemp = 300;
unsigned int timerNightON = 0;
unsigned int timerDayON = 0;
unsigned int timerLightON = 0;
String strCommand = "";
boolean flagPowerON = false;
float currentHum, currentTemp;
boolean flagTempOK = false;
unsigned int valNight1, valNight2;
boolean flagRIP = true, flagRCWL = true; // test value
boolean flagStreetLightON = false;
boolean flagNightON = false;
byte swNightValue = 127;
byte swNightDelay = 10; //sec - delay ON/off Night mode
byte valMaxStreetLightON = 127;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LBLUE, OUTPUT);
  pinMode(LGREEN, OUTPUT);
  pinMode(LRED, OUTPUT);
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RCWL, INPUT);
  pinMode(RIP, INPUT);
  //off all led and relay
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LBLUE, HIGH);
  digitalWrite(LGREEN, HIGH);
  digitalWrite(LRED, HIGH);
  digitalWrite(RELAY1, LOW);
  digitalWrite(RELAY2, LOW);
  //BT sets
  pinMode(BTKEY, OUTPUT);
  digitalWrite(BTKEY, LOW);
  BT.begin(9600);
  // get settings from eeprom
  // address = 0 = Power ON = 1 OFF = 0
  byte item = EEPROM.read(0);
  if (item == 255) {
    EEPROM.write(0, 0);
  }
  if ((item == 0) || (item == 255)) {
    flagPowerON = false;
    printConsoleText("Power is OFF");
  } else {
    flagPowerON = true;
    printConsoleText("Power is ON");
  }
  // address = 1 = swNightValue
  swNightValue = EEPROM.read(1);
  // address = 2 = swNightDelay
  swNightDelay = EEPROM.read(2);
  // address = 3 = valMaxStreetLightON
  valMaxStreetLightON = EEPROM.read(3);
}

void loop() {
  // put your main code here, to run repeatedly:
  // read console command
  if (Serial.available()) {
    while (Serial.available()) {
      strCommand += char(Serial.read());
      delay(50);
    }
  }
  // read BT console
  if (BT.available()) {
    while (BT.available()) {
      strCommand += char(BT.read());
      delay(50);
    }
  }
  // exec command
  strCommand.trim();
  if (strCommand.length() > 3) {
    executeCommand();
    strCommand = "";
  }
  // - 
  /*unsigned int bs = analogRead(BTSTATUS);
  if (bs != btst) {
    btst = bs;
    Serial.println(bs);
  }*/
  // count timers
  unsigned long ctmr = (long(millis() / 1000));
  if ((timerSec > 4294900) && (ctmr < 100)) {
    timerSec = 0;
  }
  if (ctmr > timerSec) {
    timerSec = ctmr;
    //digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //test
    // run every sec
    // read sensors
    // analize sensor and show led and log
    int ar1 = analogRead(FRES1);
    byte brl =  map(ar1, 0, 1023, 0, 255);
    int rrl = brl - valNight1;
    if ((rrl > 5) || (rrl < (-5))) {
      valNight1 = brl;
      String st = "FRES1 changed ";
      st += String(brl);
      printConsoleText(st);
    }
    ar1 = analogRead(FRES2);
    brl = map(ar1, 0, 1023, 0, 255);
    rrl = brl - valNight2;
    if ((rrl > 5) || (rrl < (-5))) {
      valNight2 = brl;
      String st = "FRES2 changed ";
      st += String(brl);
      printConsoleText(st);
    }
    if (!flagStreetLightON) {
      if ((valNight1 < swNightValue) && (valNight2 < swNightValue)) {
        ++timerNightON;
      } else {
        ++timerDayON;
      }
      if (timerNightON >= swNightDelay) {
        timerNightON = 0;
        timerDayON = 0;
        if (!flagNightON) {
          flagNightON = true;
          digitalWrite(LED_BUILTIN, HIGH);
          printConsoleText("Night is ON");
        }
      }
      if (timerDayON >= swNightDelay) {
        timerNightON = 0;
        timerDayON = 0;
        if (flagNightON) {
          flagNightON = false;
          digitalWrite(LED_BUILTIN, LOW);
          printConsoleText("Day is ON");
        }
      }
    } else {
      // calculate time Light
      ++timerLightON;
      if (timerLightON >= valMaxStreetLightON) {
        timerLightON = 0;
        timerNightON = 0;
        timerDayON = 0;
        flagStreetLightON = false;
        printConsoleText("Lamp OFF");
        // off ligth relay
        digitalWrite(RELAY1, LOW);
      }
    }
    // analize sensor and execute action
    byte flm = digitalRead(RCWL);
    if (flm == 1) {
      if (flm != flagRCWL) {
        printConsoleText("RCWL is ON");
      }
      flagRCWL = true;
      digitalWrite(LGREEN, LOW);
    } else {
      if (flm != flagRCWL) {
        printConsoleText("RCWL is OFF");
      }
      flagRCWL = false;
      digitalWrite(LGREEN, HIGH);
    }
    // get RIPs sensors
    flm = digitalRead(RIP);
    if (flm == 1) {
      if (flm != flagRIP) {
        printConsoleText("RIP is ON");
      }
      flagRIP = true;
      digitalWrite(LBLUE, LOW);
    } else {
      if (flm != flagRIP) {
        printConsoleText("RIP is OFF");
      }
      flagRIP = false;
      digitalWrite(LBLUE, HIGH);
    }
    //--
    if (flagPowerON) {
      // power is on
      if ((!flagStreetLightON) && (flagNightON)) {
        //  analize RIPs sensors and switch  ligth on
        if ((flagRIP) && (flagRCWL)) {
          flagRIP = false;
          flagRCWL = false;
          flagStreetLightON = true;
          printConsoleText("Lamp ON");
          timerLightON = 0;
          // lamp relay on
          digitalWrite(RELAY1, HIGH);
        }
      }
    } else {
      // off relay
      flagStreetLightON = false;
      digitalWrite(RELAY1, LOW);
      digitalWrite(RELAY2, LOW);
    }
    // load temp and hum
    ++timerGetTemp;
    if (timerGetTemp >= CYCLE_GET_TEMP) {
      timerGetTemp = 0;
      //get current temp and hum
      currentHum = dht.readHumidity();
      currentTemp = dht.readTemperature();
      if (isnan(currentHum) || isnan(currentTemp)) {
        flagTempOK = false;
      } else {
        flagTempOK = true;
      }
    }
    // end run every sec
  }
}

void executeCommand() {
  strCommand.toLowerCase();
  if ((strCommand.indexOf("poweroff") > -1)) {
    flagPowerON = false;
    EEPROM.write(0, 0);
    printConsoleText("Power is OFF");
  }
  if ((strCommand.indexOf("setbtlsch") > -1)) {
    digitalWrite(BTKEY, HIGH);
    //- begin cmd
    String cmd = "AT";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    String val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    //- begin cmd
    cmd = "AT+ORGL";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    //- begin cmd
    cmd = "AT+ROLE=0";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    //- begin cmd
    cmd = "AT+UART=9600,0,0";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    //- begin cmd
    cmd = "AT+PSWD=5812";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    //- begin cmd
    cmd = "AT+NAME=LSCHBT";
    Serial.println(cmd);
    BT.println(cmd);
    delay(500);
    val = "";
    if (BT.available()) {
      while (BT.available()) {
        val += char(BT.read());
        delay(50);
      }
      Serial.println(val);
    }
    // - end cmd
    digitalWrite(BTKEY, LOW);
  }
  if ((strCommand.indexOf("uptime") > -1)) {
    String ss = "Uptime: " + String(int(timerSec / 3600)) + " hours";
    printConsoleText(ss);
    ss = "Current valNight1 = " + String(valNight1);
    printConsoleText(ss);
    ss = "Current valNight2 = " + String(valNight2);
    printConsoleText(ss);
    ss = "Current flagRIP = " + String(flagRIP);
    printConsoleText(ss);
    ss = "Current flagRCWL = " + String(flagRCWL);
    printConsoleText(ss);
    ss = "Current flagStreetLightON = " + String(flagStreetLightON);
    printConsoleText(ss);
    ss = "Current swNightValue = " + String(swNightValue);
    printConsoleText(ss);
    ss = "Current swNightDelay = " + String(swNightDelay);
    printConsoleText(ss);
    ss = "Current valMaxStreetLightON = " + String(valMaxStreetLightON);
    printConsoleText(ss);
  }
  if ((strCommand.indexOf("poweron") > -1)) {
    flagPowerON = true;
    EEPROM.write(0, 1);
    printConsoleText("Power is ON");
  }
  if ((strCommand.indexOf("gettemp") > -1)) {
    if (flagTempOK) {
      String ct = "Temperature: ";
      ct += currentTemp;
      ct += " °C    Humidity: ";
      ct += currentHum;
      ct += " %";
      printConsoleText(ct);
    } else {
      printConsoleText("No Temperature and Humidity");
    }
  }
  if ((strCommand.indexOf("setnightvalue") > -1)) {
    byte sv = GetStrValCommand("setnightvalue", strCommand.indexOf("setnightvalue"));
    if (sv > 0 ) {
      swNightValue = sv;
      EEPROM.write(1, sv);
      printConsoleText("OK");
    }
  }
  if ((strCommand.indexOf("setnightdelay") > -1)) {
    byte sv = GetStrValCommand("setnightdelay", strCommand.indexOf("setnightdelay"));
    if (sv > 0 ) {
      swNightDelay = sv;
      EEPROM.write(2, sv);
      printConsoleText("OK");
    }
  }
  if ((strCommand.indexOf("setmaxstreetlighton") > -1)) {
    byte sv = GetStrValCommand("setmaxstreetlighton", strCommand.indexOf("setmaxstreetlighton"));
    if (sv > 0 ) {
      valMaxStreetLightON = sv;
      EEPROM.write(3, sv);
      printConsoleText("OK");
    }
  }
}

byte GetStrValCommand(String CS, int indexStr) {
  int lc = CS.length();
  int ls = strCommand.length();
  if ((indexStr + lc) >= ls) {
    return 0;
  }
  int rv = 0;
  String rs = "";
  for (int i = 0; i <= 2 ; ++i) {
    if ((indexStr + lc + i) > ls) {
      break;
    }
    int ti = int(strCommand[indexStr + lc + i]);
    if ((ti >= 48) && (ti <= 57)) {
      rs = rs + strCommand[indexStr + lc + i];
    }
  }
  int lrs = rs.length();
  if (lrs < 1) {
    return 0;
  }
  if (lrs == 1) {
    rv = (int(rs[0]) - 48);
  }
  if (lrs == 2) {
    int is = int(rs[0]) - 48;
    rv += 10 * is;
    rv += (int(rs[1]) - 48);
  }
  if (lrs == 3) {
    int is = int(rs[0]) - 48;
    rv += 100 * is;
    is = int(rs[1]) - 48;
    rv += 10 * is;
    rv += (int(rs[2]) - 48);
  }
  if (rv > 255) {
    rv = 255;
  }
  return rv;
}

void printConsoleText(String inText) {
  Serial.println(inText);
  // print BT console
  if (analogRead(BTSTATUS) > 500) {
    BT.println(inText);
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

andycat пишет:

На attiny 85  ... с АЦП для определения освещенности придется помучаться

А что там за проблемы с АЦП? Вроде такой же analogRead, как везде? Что там не так?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ЕвгенийП пишет:

 Вроде такой же analogRead, как везде

Не знал, спасибо. Тогда ТС еще проще.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А я -то испугался, что я что-то пропустил. Это моя любимая микросхема, но я чаще её пользую ручками в атмел-студии. Но в IDE,  если в менеджере плат её установить, то analogRead точно есть. Вот я и подумал, может там с ним не так что-нибудь, т.к. сам-то я его толком не использовал.

strarbit
Offline
Зарегистрирован: 12.06.2016
Farmatsevt
Farmatsevt аватар
Offline
Зарегистрирован: 27.09.2018

Большое спасибо! А какой датчик, более подходят для ардуино? Мне не принципиально какой использовать, выбор пал на этот, так как он стоял в палатке, которая мне пришла из Китая, и которая меня не устраивает.

sadman41
Offline
Зарегистрирован: 19.10.2016

Какой молоток лучше подходит для орехов? Сможете ответить с первого раза и в точку?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Требования сначала к системе и датчику опишите

Farmatsevt
Farmatsevt аватар
Offline
Зарегистрирован: 27.09.2018

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sr-hc501

Farmatsevt
Farmatsevt аватар
Offline
Зарегистрирован: 27.09.2018

Так это я о нем и говорил, когда имел ввиду "палатку из Китая"). Если бы в нем все было хорошо, тогда и ардуина была бы не нужна, так как там есть место под фоторезистор. Меня в нем не устраивают задержки. К примеру, зафиксировал этот контроллер движение, выдал лог.1, далее идёт задержка этой лог.1 (почему-то можно выставить минимум 5 мин, что уже не очень). Далее, если движений больше нет, то по истечении задержки, лог.1 пропадает и если сразу после этого снова пройтись под датчиком, то лог.1 он не выдаст, так как у него есть ещё какая-то задержка прим. 10с между выключением и последующим включением. Есть ещё пара моментов, которые меня не устраивают, которые уже касаются работы фоторезистора.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

так для этого МК и придумали чтоб программировать исполнительные устройства под нужную логику :)

скетч выше я дал, или исправляйте или пишите сами.

Farmatsevt
Farmatsevt аватар
Offline
Зарегистрирован: 27.09.2018

Так это понятно, но тут то дело в том, что есть ненужные задержки. К примеру, если мне нужно чтобы задержка была не 5 мин (а как я уже говорил ниже не ставится), а 1 мин. Тут контроллером её уже не убрать). Так, конечно, удобней бы было подключать готовый блок.
И ещё маленький вопрос, сложно ли будет написать такую программу, которая бы всем этим заправляла? С программированием дело имел, основы знаю.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Farmatsevt пишет:
Так это понятно, но тут то дело в том, что есть ненужные задержки. К примеру, если мне нужно чтобы задержка была не 5 мин (а как я уже говорил ниже не ставится), а 1 мин. Тут контроллером её уже не убрать). Так, конечно, удобней бы было подключать готовый блок. И ещё маленький вопрос, сложно ли будет написать такую программу, которая бы всем этим заправляла? С программированием дело имел, основы знаю.

нифига не понял, как так задержку минуту не убрать?

501 датчик можно сделать минимальный несколько секунд - все остальное программируется

а программу вам кинул выше - там все это есть - и датчик освещения и регулировки значений времени включения и выключения, и удаленная настройка через BT.

код древний, кривенький, но уже больше года исправно в деревне трудится