Глючит датчик движения (или я...)

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Всем привет, помогите разобраться.

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

Идея такова: поставил бесконтактный выключатель на основе сонара, кнопку сенсорную (ее не особо и нужно, но уже была дырка от прошлой щелкалки, соответственно не придумал ничего лучше, как продублировать включение/выключение ленты ею и закрыть дыркО заодно :)). Еще установил в укромном местечке датчик освещения и датчик движения. Идея в том, чтобы когда темно, и датчик движения ловит заходящего на кухню человека - лента включается на минимальную яркость и светится около 30 секунд. За это время человек либо включит нормальный свет кнопкой/сонаром, либо попил водички и утопал - через 30 секунд система, не улавливающая сигнала с датчика движения, погаснет.

Материалы таковы: Nano, сонар, кнопка, мини-датчик движения, датчик освещенности, мосфет.

#include <Ultrasonic.h>
Ultrasonic ultrasonic(6, 7);

byte pir_sens = 2;
byte led = 3;
byte button = 4;
byte light_sens = 5;

boolean led_flag = 0;
boolean but_flag = 0;

unsigned long timer;
byte delaytime = 2;
byte bright = 4;

void setup() {
  pinMode(pir_sens, INPUT);
  pinMode(led, OUTPUT);
  pinMode(button, INPUT);
  pinMode(light_sens, INPUT);
}

void loop() {
  boolean light_count = digitalRead(light_sens);
  boolean pir_count = digitalRead(pir_sens);

  if (digitalRead(button) == HIGH && led_flag == 0 && but_flag == 0) {
    for (int i = 0; i <= 255; i++) {
      analogWrite(led, i);
      delay(delaytime);
      but_flag = 1;
      led_flag = 1;
    }
  }
  if (ultrasonic.Ranging(CM) < 3 && led_flag == 0) {
    for (int i = 0; i <= 255; i++) {
      analogWrite(led, i);
      delay(delaytime);
      led_flag = 1;
    }
  }
  if (digitalRead(button) == HIGH && but_flag == 0 && led_flag == 1) {
    for (int i = 255; i >= 0; i--) {
      analogWrite(led, i);
      delay(delaytime);
      but_flag = 1;
      led_flag = 0;
    }
  }
  if (ultrasonic.Ranging(CM) < 3 && led_flag == 1) {
    for (int i = 255; i >= 0; i--) {
      analogWrite(led, i);
      delay(delaytime);
      led_flag = 0;
    }
  }
  if (digitalRead(button) == LOW && but_flag == 1) {
    but_flag = 0;
  }
  if (light_count == 1 && led_flag == 0 && pir_count == HIGH) {
    analogWrite(led, bright);
    timer = millis();
  }
  if (led_flag == 0 && pir_count == LOW && (millis() - timer) > 7000) {
    digitalWrite(led, LOW);
  }
  if (light_count == 0 && led_flag == 0) {
    digitalWrite(led, LOW);
  }
}

Система прекрасно и стабильно работает на кнопке/сонаре, но вот когда приходит ночь и активируется датчик света - иногда наблюдаю самовольные срабатывания датчика... Он расположен так, чтобы ловить пересекшего порог кухни человека, во время самовольных срабатываний однозначно никаких движений в зоне его действия не было.

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

Ну и два вопроса, кои особо не мешают, но работают некорректно и хотелось бы для себя их на будущее прояснить:

1. Расстояние, которое возвращает сонар (в цифровом эквиваленте, проверил через монитор порта) почему-то в 3-3.5 раз меньше реального. Именно потому в коде и стоит цифра 3 (в реальности это 10-11 см). Склоняюсь к тому, что это по причине библиотек для SR-04, а установлен SRF-05 (или нет?))

2. Millis()..... Почему-то в данном случае при выставленной задержке в 70 секунд (плюс пару секунд задержка выключения самого датчика движения), отключение происходит через 34-36 секунд. Опять-же некритично, но хотелось бы иметь возможность выставлять точные значения.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

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

KindMan
Offline
Зарегистрирован: 19.12.2018

А схема подключения? Вы все ноги МК, с датчиками, притянули к общему проводу через резистор?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Эммммм... Не ругайся насяльника))))

Я собрал все VCC на одну клемму WAGO, все GND на вторую (включительно с питанием дуинки), запитал все это дело от DC-DC, коя подключена к 12В блоку питания (от него питается лента), ну а сигнальные раскидал по ногам.

Плоха, да?...

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

Mishka-LV пишет:

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

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

Вывод: убрать датчик освещенности.

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Так без него же будет света легкая включаться при любом освещении... Нафига она мне днем? Датчик без фоторезистора

KindMan
Offline
Зарегистрирован: 19.12.2018

Ааа, тут всё из модулей… ну там должна быть подтяжка по идее.
По коду конечно много можно говорить, поэтому только про millis - где у вас 70 секунд? Там 7.
Датчик освещения, после того как свет загорелся, меняет свое состояние на low?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Там 7000 миллисекунд, вроде если память не изменяет - в одной секунде их 100, соответственно 7000 есть таки 70 секунд, а 700 - будет 7, нет? :)

С ним вообще что-то странное происходит. Замеры тестером показывали, что при срабатывании там появлялось 1.6 вольта, в состоянии покоя - 4.97. Инвертирование ничего не дало, система отказалась работать. Подтяжка внутреннего резистора дала зацикленное срабатывание...

Ой, это выше я написал про датчик движения.

Датчик освещения - да, меняет. Ибо его освещает лента. Именно поэтому его состояние не учитывается при отключении «легкой подсветки»

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

Mishka-LV пишет:

Так без него же будет света легкая включаться при любом освещении... Нафига она мне днем? Датчик без фоторезистора

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

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

Теперь по поводу датчика, дающего ложные срабатывания (кстати, сонар и датчик движения - это разныке датчики, который у Вас?): тут возможны, минимум, 4 варианта:

1. Реально ему есть от чего срабатывать: комар, муха, бабочка, колышущаяся от ветра занавеска...

2. Срабатывает он не от собственного эха, а от постороннего звука.

3. Он срабатывает от внешней помехи, вероятно, по питанию.

4. Просто ошибка измерения расстояния (вне зависимости от причины).

Четвертый вариант устраняется либо существенно ослабляется повторным измерением. Второй - тоже.

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

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

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Сонар у меня только на безконтактном принудительном включении основного света, а датчик движение - вот такой :)

 HC-SR505 https://s.click.aliexpress.com/e/YGWZxdO

1. Исключено. Не от чего срабатывать, ничего не летает и не колышится.

2. Вроде тоже исключено, хотя не до конца

3. Рассматриваем

4. Исключено, хотя я вот уже думаю и сюда сонар приспособить, может не будет глюки ловить...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Mishka-LV пишет:

Там 7000 миллисекунд, вроде если память не изменяет - в одной секунде их 100, соответственно 7000 есть таки 70 секунд, а 700 - будет 7

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

срочна в гугал, смотреть смысл приставки "милли"

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Упс упс упс таки да, лошара йа :)

Тогда вообще фигня у мну с датчиком получается... Чо он 36 секунд задержки дает???(((

Или таки в коде чойта зарыто?((

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Усе пацаны, расходимся... Датчик бракованный оказался, хорошо что купил их 2 или 3 :)

Опробовал без учета датчика освещенности - все как часики, правда код немного подправил и добавил еще флажок на сам датчик движения, чтоб не мигал если человек находится в его поле. Кому интересно - скину готовый код финальный в личку или сами докиньте 3 команды :)

Всем спасибо, кто принял посильное участие :)

Если есть поправки/оптимизация к коду - делитесь, буду благодарен.

P.S. При задержке в 7000 в миллисе - все равно выключается через 26-28 секунд, без задержки (чистая задержка датчика) - 7-8 сек. Как добиться точности в коде так и не додумался, буду благодарен за идеи. Пробовал ставить задержку 12000, чтобы обойти чистое время задержки датчика, время угасания меняется на 48 секунд. Где-то не хватает мне знаний...

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Опять происходит трабла, мне совершенно непонятная. Сломал всю голову.

Дело вот в чем - стоит на бесконтактное включение подсветки кухни сонар (HC SR-05). Выставлено расстояние для срабатывания - не более 15 см. Так вот, если я включаю выдачу расстояния в порт (Serial.println(ultrasonic.read(CM))) в loop'е, все работает четко. Но если я комментирую эту комманду, то сонар начинает работать практически на любом расстоянии... Как сие победить?(((

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

А Вы кто по профессии, если не секрет?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

sadman41 пишет:

А Вы кто по профессии, если не секрет?

По профессии архитектор, занимаюсь установкой и продажей светодиодных лент. 

А шо?)

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

Ну так.

Вот врач по фамилии пациента может установить заболевание? А вы по описанию прохожим фасада здания сумеете установить точную причину обрушения крыши?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

sadman41 пишет:

Ну так.

Вот врач по фамилии пациента может установить заболевание? А вы по описанию прохожим фасада здания сумеете установить точную причину обрушения крыши?

Понял, ага, затупил)))

Вот:


#include <Ultrasonic.h>
Ultrasonic Ultrasonic(6, 7);

byte pir_sens = 2;
byte led = 3;
byte button = 4;
byte light_sens = 5;

boolean led_flag = 0;
boolean but_flag = 0;
boolean pir_flag = 0;
boolean pir_light = 0;

unsigned long timer;
unsigned long far;

unsigned long distance = 3;     //ораничение расстояния, при котором срабатывает сонар
unsigned long pir_timer = 30;   //время свечения после срабатывания датчика движения, секунд (мин. 7)
unsigned long delaytime = 1;    //плавность включения/выключения подсветки (основная)
unsigned long delaytimepir = 8; // плавность включения/выключения подсветки (датчик)
int bright = 10;                // ограничение яркости подсветки (датчик)


void setup() {
  pinMode(pir_sens, INPUT);
  pinMode(led, OUTPUT);
  pinMode(button, INPUT);
  pinMode(light_sens, INPUT);
  //Serial.begin(9600);
}

void loop() {

  boolean light_count = digitalRead(light_sens);
  boolean pir_count = digitalRead(pir_sens);
  far = Ultrasonic.distanceRead();
  //Serial.println(far);

  if (digitalRead(button) == HIGH && led_flag == 0 && but_flag == 0 && pir_light == 0) {
    shut_ON();
  }
  if (digitalRead(button) == HIGH && led_flag == 0 && but_flag == 0 && pir_light == 1) {
    shut_ON_after_pir();
  }
  if (far < distance && led_flag == 0 && but_flag == 0 && pir_light == 0) {
    shut_ON();
  }
  if (far < distance && led_flag == 0 && but_flag == 0 && pir_light == 1) {
    shut_ON_after_pir();
  }
  if (digitalRead(button) == HIGH && but_flag == 0 && led_flag == 1) {
    shut_OFF();
  }
  if (far < distance && led_flag == 1 && but_flag == 0) {
    shut_OFF();
  }
  if (digitalRead(button) == LOW && but_flag == 1) {
    but_flag = 0;
  }
  if (light_count == 1 && led_flag == 0 && pir_count == HIGH && pir_light == 0 && pir_flag == 0) {
    pir_light_ON();
    timer = millis();
  }
  if (led_flag == 0 && pir_count == HIGH && pir_light == 1 && millis() - timer > 6000) {
    timer = millis();
  }
  if (led_flag == 0 && pir_count == LOW && pir_flag == 1 && pir_light == 1 && (millis() - timer) > pir_timer * 250) {
    pir_light_OFF();
  }
  if (light_count == 0 && led_flag == 0 && pir_light == 1) {
    pir_light_OFF();
  }
}

void shut_ON() {
  int i = 0;
  while (i <= 255) {
    if (millis() - timer > delaytime) {
      i++;
      timer = millis();
      if (i > 255) break;
    }
    analogWrite(led, i);
  }
  but_flag = 1;
  led_flag = 1;
}

void shut_OFF() {
  int i = 255;
  while (i >= 0) {
    if (millis() - timer > delaytime) {
      i--;
      timer = millis();
      if (i < 0) break;
    }
    analogWrite(led, i);
  }
  but_flag = 0;
  led_flag = 0;
}

void pir_light_ON () {
  int i = 0;
  while (i <= bright) {
    if (millis() - timer > delaytimepir) {
      i++;
      timer = millis();
      if (i > bright) break;
    }
    analogWrite(led, i);
  }
  pir_flag = 1;
  pir_light = 1;
}

void pir_light_OFF() {
  int i = bright;
  while (i >= 0) {
    if (millis() - timer > delaytimepir) {
      i--;
      timer = millis();
      if (i < 0) break;
    }
    analogWrite(led, i);
  }
  pir_flag = 0;
  pir_light = 0;
}

void shut_ON_after_pir() {
  int i = bright;
  while (i <= 255) {
    if (millis() - timer > delaytime) {
      i++;
      timer = millis();
      if (i > 255) break;
    }
    analogWrite(led, i);
  }
  but_flag = 1;
  led_flag = 1;
  pir_flag = 0;
  pir_light = 0;
}

 

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

На строку #37 поставьте delay(100); - заработает?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

sadman41 пишет:

На строку #37 поставьте delay(100); - заработает?

Таки да, спасибо огромное. Delay нужен для стабилизации сонара?

Правда я уменьшил Delay до 15, ибо тормозило включение (импульс то там 10 мкс же вроде)

Еще такой вопрос, если разбираетесь - у меня сонар почему-то выдает расстояние в 3 раза меньше реального. Как бы не проблема дописать «*3» в коде (чтобы выставлять реальные расстояния, а не на глазок), но с чего он так себя ведет, не подскажите?

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

Mishka-LV пишет:

sadman41 пишет:

На строку #37 поставьте delay(100); - заработает?

Таки да, спасибо огромное. Delay нужен для стабилизации сонара?

По 05 даташитов не читал, но на 04 (https://www.mouser.com/ds/2/813/HCSR04-1022824.pdf) изложено следующее: "we suggest to use over 60ms measurement cycle, in order to prevent trigger signal to the echo signal"

Т.е. необходимо либо дилеем, либо как-то иначе обеспечить паузу между замерами для того, чтобы успокоилось эхо.  

Mishka-LV пишет:
Еще такой вопрос, если разбираетесь - у меня сонар почему-то выдает расстояние в 3 раза меньше реального. Как бы не проблема дописать «*3» в коде (чтобы выставлять реальные расстояния, а не на глазок), но с чего он так себя ведет, не подскажите?

Может библиотека в инчах каких-нить отдаёт расстояние... надо ей внутрь смотреть - во что она pulseIn пересчитывает.

 

 

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

Mishka-LV пишет:

я уменьшил Delay до 15

Цитата:

у меня сонар почему-то выдает расстояние в 3 раза меньше реального.

Как Вы думаете, связаны ли между собой эти два факта?

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

Учитывая, что от изменения delay, показания датчика не меняются, связи не нахожу :)

Грешу пока на саму плату, ибо у людей с ею бывали проблемы (по крайней мене на Serial.begin когда 9600 бод выставляешь, в мониторе порта нужно ставить 2400, чтобы не было кракозябров)

Плата сия:

https://s.click.aliexpress.com/e/JdefkiU

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

Госсподи, и тут вавгад. Надо в правила включить пункт: если увидел на плате слово Wavgat - сразу напиши об этом, а не трахай мозги окружающим с описанием псевдобагов.

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

А посоветуйте тогда адекватные платы... Оригинал не потяну, а такие чтоб хорошие копии :)

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

Любые китайские платы, но с оригинальным микроконтроллером Atmel Atmega328P, НЕ wavgat. 
Хотя брак конечно везде попадается, но у wavgat проблема в другом - там стоит совсем другой микроконтроллер, с закосом под оригинальный.

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

Адекватность товаров с алиэкспресса - понятие субъективное. Просто смотрите на картинки - если на МК написано ATmel, то есть какой-то шанс получить плату с таким же контроллером, который стоит на официальных Arduino. В противном случае - Вы получаете частично совместимый и мимикрирующий под продукцию ATmel чип. В каком месте он совместим, а в каком нет - доподлинно известно только тем, кто на китайском документацию читать умеет.

Оригинал: https://store.arduino.cc/usa/arduino-nano -> TECH SPECS -> Microcontroller: ATmega328

Пример #1: МК ATmel MEGA328P - эквивалент 

Пример #2: МК Wavgat AVGA328P - НЕ эквивалент 

 

Mishka-LV
Offline
Зарегистрирован: 30.05.2017

https://s.click.aliexpress.com/e/bF436ca8

Заказал такие, спасибо за науку!)