Проблемы с сведением двух скетчей.

Stix19
Offline
Зарегистрирован: 18.07.2016

Добрый всем вечер. Такой вот вопрос назрел. Надо подключить к ардуино уно 2 пир датчика(hc sr501) и 1 ультразвуковой датчик(hc sr04). Естественно при определённых условиях, прописанных в скетче должен загореться светодиод.

Взял 2 скетча.

для PIR HC SR501:

//Тестировалось на Arduino IDE 1.0.1
//Время калибровки датчика (10-60 сек. по даташиту)
int calibrationTime = 30;      
//Время, в которое был принят сигнал отсутствия движения(LOW)
long unsigned int lowIn;       
//Пауза, после которой движение считается оконченным
long unsigned int pause = 5000;
//Флаг. false = значит движение уже обнаружено, true - уже известно, что движения нет
boolean lockLow = true;
//Флаг. Сигнализирует о необходимости запомнить время начала отсутствия движения
boolean takeLowTime;
int pirPin = 2;    //вывод подключения PIR датчика
int ledPin = 13;   //вывод сигнального диода

void setup()
{
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT); 
  digitalWrite(pirPin, LOW);
  //дадим датчику время на калибровку
  Serial.print("Calibrating");
  for(int i = 0; i < calibrationTime; i++)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}

void loop()
{
  //Если обнаружено движение
  if(digitalRead(pirPin) == HIGH)
  {
    //Если еще не вывели информацию об обнаружении
    if(lockLow)
    {
      lockLow = false;     
      Serial.println("Motion detected");
      delay(50);
    }        
    takeLowTime = true;
  }

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

для HC SR04:

 

//Тестировалось на Arduino IDE 1.0.1
#define Trig 9
#define Echo 8
#define ledPin 13

void setup() 
{  
  pinMode(Trig, OUTPUT); //инициируем как выход 
  pinMode(Echo, INPUT); //инициируем как вход 
  pinMode(ledPin, OUTPUT); 
  Serial.begin(9600); 
  /* задаем скорость общения. В нашем случае с компьютером */unsigned int impulseTime=0; 
unsigned int distance_sm=0; 

void loop() 
{  
  digitalWrite(Trig, HIGH); 
  /* Подаем импульс на вход trig дальномера */
  delayMicroseconds(10); // равный 10 микросекундам 
  digitalWrite(Trig, LOW); // Отключаем 
  impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса 
  distance_sm=impulseTime/58; // Пересчитываем в сантиметры 
  Serial.println(distance_sm); // Выводим на порт 
  if (distance_sm<30) // Если расстояние менее 30 сантиметром 
  {     
    digitalWrite(ledPin, HIGH); // Светодиод горит 
  }  
  else 
  {   
    digitalWrite(ledPin, LOW); // иначе не горит 
  }   
  delay(100); 
  /* ждем 0.1 секунды, Следующий импульс может быть излучён, только после исчезновения эха от предыдущего. 
   Это время называется периодом цикла (cycle period). 
   Рекомендованный период между импульсами должен быть не менее 50 мс.  */
}
Stix19
Offline
Зарегистрирован: 18.07.2016

После сведения получил вот такой скетч:

//Тестировалось на Arduino IDE 1.0.1
//Время калибровки датчика (10-60 сек. по даташиту)
int calibrationTime = 30;      
//Время, в которое был принят сигнал отсутствия движения(LOW)
long unsigned int lowIn;       
//Пауза, после которой движение считается оконченным
long unsigned int pause = 5000;
//Флаг. false = значит движение уже обнаружено, true - уже известно, что движения нет
boolean lockLow = true;
//Флаг. Сигнализирует о необходимости запомнить время начала отсутствия движения
boolean takeLowTime;
int pirPin = 2;    //вывод подключения PIR датчика
int ledPin = 13;   //вывод сигнального диода
int pirPin1 = 3;
int trig = 8;
int echo = 9; 
void setup()
{
  Serial.begin(9600);
pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(pirPin, INPUT);
  pinMode(pirPin1, INPUT);
  pinMode(ledPin, OUTPUT); 
  digitalWrite(pirPin, LOW);
  digitalWrite(pirPin1, LOW);
  //дадим датчику время на калибровку
  Serial.print("Calibrating");
  for(int i = 0; i < calibrationTime; i++)
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
}
unsigned int impulseTime=0; 
unsigned int distance_sm=0;
void loop()
 
{
  //Если обнаружено движение
  if(digitalRead(pirPin) == HIGH)
  if(digitalRead(pirPin1) == HIGH)
  {
    //Если еще не вывели информацию об обнаружении
    if(lockLow)
    {
      lockLow = false;     
      Serial.println("Motion detected");
      delay(50);
    }        
    takeLowTime = true;
  }
 
  //Ели движения нет
  if(digitalRead(pirPin) == LOW)
  if(digitalRead(pirPin1) ==LOW)
  {      
    //Если время окончания движения еще не записано
    if(takeLowTime)
    {
      lowIn = millis();          //Сохраним время окончания движения
      takeLowTime = false;       //Изменим значения флага, чтобы больше не брать время, пока не будет нового движения
    }
    //Если время без движение превышает паузу => движение окончено
    if(!lockLow && millis() - lowIn > pause)
    { 
      //Изменяем значение флага, чтобы эта часть кода исполнилась лишь раз, до нового движения
      lockLow = true;               
      Serial.println("Motion finished");
      delay(50);
      
    }
    
  }
  {
   digitalWrite(trig, HIGH); 
  /* Подаем импульс на вход trig дальномера */
  delayMicroseconds(10); // равный 10 микросекундам 
  digitalWrite(trig, LOW); // Отключаем 
  impulseTime=pulseIn(echo, HIGH); // Замеряем длину импульса 
  distance_sm=impulseTime/58; // Пересчитываем в сантиметры 
  Serial.println(distance_sm); // Выводим на порт 
  if (distance_sm<30) // Если расстояние менее 30 сантиметром 
  {     
    digitalWrite(ledPin, HIGH); // Светодиод горит 
  }  
  else 
  {   
    digitalWrite(ledPin, LOW); // иначе не горит 
    delay(100);
  }
  }
  
}
 
 
Вся проблема в том, что ультразвуковой датчик (hc sr04) отрабатывает как положено и светодиод загорается, а вот PIR датчики совершенно не реагируют на движение. Что только не делал, ни какой разницы, потому и решил создать тему и обратиться к Вашей помощи.
Спасибо.
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Создай классы HC SR501 и HC SR04 отладь каждый и потом сведи.

ПС: для светодиода тоже. Меньше будет проблем.

Stix19
Offline
Зарегистрирован: 18.07.2016

qwone пишет:

Создай классы HC SR501 и HC SR04 отладь каждый и потом сведи.

ПС: для светодиода тоже. Меньше будет проблем.

 

Спасибо за информацию, но я не так давно начал заниматься программированием, чтоб полностью понять Ваш совет и как создать классы. Так понимаю, у меня в коде 2 класса(на 2 вида датчиков), которые должны работать по отдельности и потом свести в один или я не так это понимаю?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Там скорее еще проще. Надо убрать калибровку.

Смотри http://smart-home.te.ua/arduino-datchyk-dvyzhenyya-hc-sr501-pir/

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

вот собрал программку.

//Class_HC_SR501
class qw_HC_SR501{
   public:
    qw_HC_SR501(int pin); // конструктор
    boolean motion_is_detected();// 
   private:
    int HC_SR501pin; // нога для HC_SR501
};
qw_HC_SR501::qw_HC_SR501(int pin){
  HC_SR501pin = pin;
  pinMode(HC_SR501pin, INPUT);
};
boolean qw_HC_SR501::motion_is_detected(){
  return  digitalRead(HC_SR501pin) ;
};
// светодиод
class qw_led{
   public:
    qw_led(int pin); // конструктор
    void light();//включить светодиод
    void dark();//выключить светодиод     
   private:
    int ledPin; // нога для светодиода
};
qw_led::qw_led(int pin){; // конструктор
ledPin = pin;
digitalWrite(ledPin, 0);
}
void qw_led::light(){//включить светодиод
  digitalWrite(ledPin, 0);
}
void qw_led::dark(){//выключить светодиод
  digitalWrite(ledPin,1); 
}

// ===== Программа =====
const int pirPin = 2;    //вывод подключения PIR датчика
const int ledPin = 13;   //вывод сигнального диода

qw_HC_SR501 DA1(pirPin);// подключили HC_SR501
qw_led VD1(ledPin);// подключили светодиод
void setup() {
 
}

void loop() {
  delay (1000);
  if (DA1.motion_is_detected()) VD1.light();
  else VD1.dark();
}
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

вот собрал программку.

А у нас чего, пины могут иметь отрицательные значения? И их так много, аж 65535? Это я к тому, что - бездарный расход оперативы.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Можно поинтересоваться, какой процент от всей доступной памяти был так бездано израсходован?

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

andriano пишет:

Можно поинтересоваться, какой процент от всей доступной памяти был так бездано израсходован?

я всю доступную память в банк на депозит ложу - кодю доходы от процентов

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

andriano пишет:

Можно поинтересоваться, какой процент от всей доступной памяти был так бездано израсходован?

Достаточный, чтобы в больших проектах не применять этот код. Вы, наверное, байтики ещё не считали в оперативе? Если не жмёт - то можно всё, но жать начинает вот в таких вот бездарных местах. Впрочем, для over9000 всех поделок на ардуине указанный код применять можно - "всем похер" (с).

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Цитата из компилятора:Скетч использует 1 280 байт (3%) памяти устройства. Всего доступно 32 256 байт.
Скетч использует 1 280 байт (3%) памяти устройства. Всего доступно 32 256 байт.
Глобальные переменные используют 13 байт (0%) динамической памяти, оставляя 2 035 байт для локальных переменных. Максимум: 2 048 байт.
 
Ай-Ай-Яй. 13 байт (0%) динамической памяти израсходовал оперативы. Нехороший qwone.
 
А голая программа,тоже цитата:Скетч использует 450 байт (1%) памяти устройства. Всего доступно 32 256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2 039 байт для локальных переменных. Максимум: 2 048 байт.
 
Похоже 4 байта действительно просрал. Вот на большой проект их нехватит.
const int pirPin = 2;    
const int ledPin = 13;

Похоже при такой конструкции ни один байт ардуины не пострадал. Что флеш, что озу.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

 
Ай-Ай-Яй. 13 байт (0%) динамической памяти израсходовал оперативы. Нехороший qwone.

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

DIYMan пишет:

andriano пишет:

Можно поинтересоваться, какой процент от всей доступной памяти был так бездано израсходован?

Достаточный, чтобы в больших проектах не применять этот код. Вы, наверное, байтики ещё не считали в оперативе?

Считать байтики - дело нехитрое. Иногда считаю, иногда - нет. С моей точки зрения умение считать байтики существенно проигрывает умению определять, в каких случаях стоит считать байтики, а в каких - нет. В данном случае - не стоит. Я не занимаюсь оптимизацией ради оптимизации.

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

andriano пишет:

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

Верно, ключевое здесь - знание когда надо экономить, а когда не обязательно. Профи конечно это всё знают, а новичок даже и не догадывается. И будет лепить int'ы где надо и где не надо. Поэтому надо сразу приучать делать правильно, чтобы новички не привыкали везде писать int'ы

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Jeka_M пишет:

Поэтому надо сразу приучать делать правильно, чтобы новички не привыкали везде писать int'ы

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

2andriano: Из недостатков лёгкого вхождения в программирование МК, кое даёт Arduino IDE, считаю невероятное количество говнокода, которое расплодилось в сети. Плохо - оно как-то само получается. А вот хорошо - можно ведь и чуть-чуть научиться, правда? И да, я тоже против оптимизации ради оптимизации, как самоцели. Но тут - другой случай, обучательный.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

DIYMan пишет:
Из недостатков лёгкого вхождения в программирование МК, кое даёт Arduino IDE, считаю невероятное количество говнокода, которое расплодилось в сети.

Ардуино тут ни при чем.

Сейчас так на любом ресурсе, посвященном программированию. И, думаю, не только программрованию. По крайней мере, с автомобилями - точно так же.

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

Цитата:
И да, я тоже против оптимизации ради оптимизации, как самоцели. Но тут - другой случай, обучательный.

Согласен.

Есть только два замечания:

- резковато это как-то прозвучало (а может, это проблема с моим восприятием),

- пример для обучения неудачный. Собственно, могу даже сформулировать формальный критерий: если не используются массивы, экономить на длине типа данных совершенно бесперспективно (хотя, кроме объема може сказываться скорость обработки, например, в прерывании).

Stix19
Offline
Зарегистрирован: 18.07.2016

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

//Class_HC_SR501
class qw_HC_SR501{
   public:
    qw_HC_SR501(int pin); // конструктор
    boolean motion_is_detected();// 
   private:
    int HC_SR501pin; // нога для HC_SR501
};
qw_HC_SR501::qw_HC_SR501(int pin){
  HC_SR501pin = pin;
  pinMode(HC_SR501pin, INPUT);
};
boolean qw_HC_SR501::motion_is_detected(){
  return  digitalRead(HC_SR501pin) ;
};
// светодиод
class qw_led{
   public:
    qw_led(int pin); // конструктор
    void light();//включить светодиод
    void dark();//выключить светодиод     
   private:
    int ledPin; // нога для светодиода
};
qw_led::qw_led(int pin){; // конструктор
ledPin = pin;
digitalWrite(ledPin, 0);
}
void qw_led::light(){//включить светодиод
  digitalWrite(ledPin, 0);
}
void qw_led::dark(){//выключить светодиод
  digitalWrite(ledPin,1); 
}

// ===== Программа =====
const int pirPin = 2;    //вывод подключения PIR датчика
const int ledPin = 13;   //вывод сигнального диода

qw_HC_SR501 DA1(pirPin);// подключили HC_SR501
qw_led VD1(ledPin);// подключили светодиод
void setup() {
 
}

void loop() {
  delay (1000);
  if (DA1.motion_is_detected()) VD1.light();
  else VD1.dark();
}

А если уж совсем честно, то как написать класс на вторую часть кода (под HC SR04) и как их потом свести для меня не понятно(((

Полезу в поиск, узнавать каким образом пишется класс и какая строка за, что отвечает.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

На лови с датчиком до цели. Программу проверил на ошибки. живьем не пробовал.

//Class_HC_SR501
class qw_HC_SR501{
   public:
    qw_HC_SR501(int pin); // конструктор
    boolean motion_is_detected();// 
   private:
    int HC_SR501pin; // нога для HC_SR501
};
qw_HC_SR501::qw_HC_SR501(int pin){
  HC_SR501pin = pin;
  pinMode(HC_SR501pin, INPUT);
};
boolean qw_HC_SR501::motion_is_detected(){
  return  digitalRead(HC_SR501pin) ;
};
// Class HC SR04
class qw_HC_SR04{
   public:
      qw_HC_SR04(int pin1,int pin2);
      unsigned int impulseTime; 
      unsigned int distance_sm();
   private:
    int HC_SR04_Trig_pin; // нога Trig для HC SR04 
    int HC_SR04_Echo_pin; // нога Echo для HC SR04 
};
qw_HC_SR04::qw_HC_SR04(int pin1,int pin2){// конструктор
  HC_SR04_Trig_pin = pin1;
  HC_SR04_Echo_pin = pin2;
  pinMode(HC_SR04_Trig_pin, OUTPUT); //инициируем как выход 
  pinMode(HC_SR04_Echo_pin, INPUT); //инициируем как вход  
};
unsigned int qw_HC_SR04::distance_sm(){
  digitalWrite(HC_SR04_Trig_pin, HIGH); 
  /* Подаем импульс на вход trig дальномера */
  delayMicroseconds(10); // равный 10 микросекундам 
  digitalWrite(HC_SR04_Trig_pin, LOW); // Отключаем
  impulseTime=pulseIn(HC_SR04_Echo_pin, HIGH); // Замеряем длину импульса 
  return impulseTime/58; // Возвращаем дистанцию  в сантиметрах 
};
// светодиод вывод-земля
class qw_led{
   public:
    qw_led(int pin); // конструктор
    void light();//включить светодиод
    void dark();//выключить светодиод     
   private:
    int ledPin; // нога для светодиода
};
qw_led::qw_led(int pin){ // конструктор
ledPin = pin;
digitalWrite(ledPin, 0);
}
void qw_led::light(){//включить светодиод
  digitalWrite(ledPin, 1);
}
void qw_led::dark(){//выключить светодиод
  digitalWrite(ledPin,0); 
}

// ===== Программа =====
const int pirPin = 2;    //вывод подключения PIR датчика
const int Trig = 9; //вывод Trig датчика HC SR04
const int Echo = 8; //вывод Echo датчика HC SR04
const int ledPin = 13;   //вывод сигнального диода

qw_HC_SR501 DA1(pirPin);// подключили HC SR501
qw_HC_SR04  DA2(Trig,Echo);// подключили HC SR04
qw_led VD1(ledPin);// подключили светодиод

void setup() {
 Serial.begin(9600); 
  /* задаем скорость общения. В нашем случае с компьютером */
}

void loop() {
  delay (500);// пауза среди опроса 0.5 сек
  if (DA1.motion_is_detected()) {  // Если обнаружили движение
      VD1.light(); // Зажгли светодиод
      Serial.println(DA2.distance_sm()); // Вывели на порт расстояние до цели
      }
  else VD1.dark(); // иначе светодиод потушен
}
Скетч использует 3 190 байт (9%) памяти устройства. Всего доступно 32 256 байт.
Глобальные переменные используют 210 байт (10%) динамической памяти, оставляя 1 838 байт для локальных переменных. Максимум: 2 048 байт.
Куда бы положить сэкономленные байты в банк на проценты?
Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

qwone пишет:

Куда бы положить сэкономленные байты в банк на проценты?

Можно свободную память использовать для распределенных вычислительных систем под расчет холодного термояда...

Stix19
Offline
Зарегистрирован: 18.07.2016

Огромное спасибо. Прямо сейчас и проверю скетч.