нужна помощь опытных ардуинщиков ..или как победить delay

Тема в разделе "Arduino & Shields", создана пользователем sky_84, 13 сен 2014.

  1. sky_84

    sky_84 Нуб

    Добрый день. Имею вот какой вопрос :

    есть плата arduino UNO +DHT11+RIP датчик + LCD 1602 . Цель ставлю такую (несовсем обычную, скорее с целью изучения) : выводить температуру и влажность на экран + включать реле если срабатывает RIP датчик .
    есть программный код (надо сказать слепил два разных пример в один ) :
    #include <dht.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #define pirPin 2
    #define ledPin 13
    // Создаем сенсор
    DHT sensor = DHT();
    // Подключаем LCD
    LiquidCrystal_I2C lcd(0x27,16,2);

    void setup()
    {
    lcd.init();
    lcd.backlight();
    // Подключаем сенсор к 0 аналоговому порту
    sensor.attach(A0);
    // Ждем готовность сенсора
    delay(1000);

    Serial.begin(9600);
    pinMode(pirPin, INPUT);
    pinMode(ledPin,OUTPUT); // тут висит реле
    }

    void loop()
    {
    int pirVal = digitalRead(pirPin);

    //Если обнаружили движение
    if(pirVal == HIGH)
    {
    digitalWrite(ledPin, HIGH);
    Serial.print(" Motion detected ");
    delay(60000);
    }
    else
    {
    Serial.print(" No motion ");
    digitalWrite(ledPin,LOW);
    }
    // Проводим измерения
    lcd.clear();
    lcd.setCursor(0,0);
    sensor.update();

    switch (sensor.getLastError())
    {
    case DHT_ERROR_OK:
    char msg[128];
    // Если ошибок нет, то собираем данные
    sprintf(msg, "Current humidity = %d%% temperature = %dC",
    sensor.getHumidityInt(), sensor.getTemperatureInt());
    lcd.print("VL");
    lcd.setCursor(5, 0);
    lcd.print(sensor.getHumidityInt());
    lcd.setCursor(7, 0);
    lcd.print("% HOME");
    lcd.setCursor(0, 1);
    lcd.print("TEMP");
    lcd.setCursor(5, 1);
    lcd.print(sensor.getTemperatureInt());
    lcd.setCursor(7, 1);
    lcd.print("C SOKOLOV");
    break;

    }

    delay(1000);

    }

    и самое главное все работает , но не так как хотелось бы . А именно после срабатывания датчика , включается реле и как понятно из кода , все измерения температуры и влажности замирают , как и информация на экране (если сработка произошла в момент обновления то экран и вовсе пуст ) на 1000млс . Помогите победить это , с подробным объяснением . Читал различного рода статьи обхода delay но я только делаю первые шаги ,по этому не все понимаю .
    Спасибо заранее.
     
    Последнее редактирование: 13 сен 2014
  2. 9xA59kK

    9xA59kK Гик

    Скетч не тот что ты описываешь. Какой используешь выход для реле?
    Где в коде включение реле, где условие при котором оно включается?
     
    sky_84 нравится это.
  3. sky_84

    sky_84 Нуб

    Добрый день , спасибо поправил.
    define ledPin 13 реле повесил место светодиода .
     
  4. 9xA59kK

    9xA59kK Гик

    sky_84 нравится это.
  5. не очень понимаю как тут поможет millis()

    мне вот логика этого куска непонятна

    //Если обнаружили движение
    if(pirVal == HIGH)
    {
    digitalWrite(ledPin, HIGH);
    Serial.print(" Motion detected ");
    delay(60000);
    }
    else
    {
    Serial.print(" No motion ");
    digitalWrite(ledPin,LOW);
    }

    какая в этом практическая польза??
     
  6. geher

    geher Гуру

    Я полагаю, что логика такая:
    Обнаружили движение - значит, что-то зашевелилось, и, чтобы не забивать канал сигналами, на минуту останавливается обнаружение движения. Все равно сигнал подан и за минуту новый сигнал скорее всего будет продолжением старого. Когда делал сигнализацию, отсылающую СМС и делающую звонок при срабатывании, делал примерно так же.
    Но в свете постоянного вывода Serial.print(" No motion "); это становится неочевидным и бессмысленным.
     
  7. 9xA59kK

    9xA59kK Гик

    Главное понять сам принцип как заменить функцию delay. И в дальнейшем использовать самостоятельно.
    millis() - Возвращает количество миллисекунд с момента начала выполнения текущей программы на плате Arduino
    Сначала незабываем объявлявить переменные вначале программы либо в цикле
    Unsigned long currentMillis = 0;
    Unsigned long previousMillis = 0;
    int interval = 1000; // интервал 1 секунд

    ----------------------------------------------------------------------
    if(pirVal == HIGH)
    //Если обнаружили движение то
    {
    currentMillis = millis();
    //например в текущей интерации currentMillis = 2000
    //проверяем не прошел ли нужный интервал, если прошел то
    if(currentMillis - previousMillis > interval)
    {

    //Если условие выполняется а именно например if(2000 - 0 > 1000) т.е 2000 > 1000 то
    previousMillis = currentMillis; // сохраняем время последнего переключения
    digitalWrite(ledPin, HIGH); // если прошло 1 секунда то включаем Светодиод
    }
    }
     
    Последнее редактирование: 13 сен 2014
    sky_84 нравится это.
  8. 9xA59kK

    9xA59kK Гик

    Это конечно грубые цифры но надеюсь стало понятнее.
    Выше в примере не хватало фигурной скобки во втором условии- исправил
     
  9. sky_84

    sky_84 Нуб

    Спасибо , стало на много понятней .
     
  10. главное понимать что подобный "таймер" через месяц перестанет работать.
     
  11. 9xA59kK

    9xA59kK Гик

    Вовсе не перестанет, и это не тот таймер об котором вы подумали. Здесь не используются грубо говоря все 50 дней таймера. Когда таймер превысит грубо 50 дней он просто сбросится от переполнения и начнет счет заново. И в данном коде выше ничего страшного не произойдет. Просто в некоторых случаях это надо учитывать.
     
  12. и что произойдет с условием if(currentMillis - previousMillis > interval) ??
     
  13. 9xA59kK

    9xA59kK Гик

    Подумайте посчитайте и сразу все поймете.
    Именно в данном случае ничего страшного не произойдет. Ответ лежит на поверхности.
    Сразу скажу для особо пытливых умов- на этот случай тоже есть выход ,немного доработать код программы и не для ленивых ГУГЛ в помощь.
    На случай если милис не подходит - можно самому написать таймер счетчик к примеру использовать прерывание и т.п.
    Можно использовать внешний примитивный таймер из транзистора и пары конденсаторов и сопротивлений подключить на цифровой пин и счтить импульсы и т.д.
    Вообще контроллер очень гибкая штука многое можно придумать, главное иметь терпение и желание.
     
    Последнее редактирование: 13 сен 2014
    sky_84 нравится это.
  14. я какбы задал вполне конкретный вопрос, ответ на который, лежит на поверхности.
    только вот предлагается использовать миллис.
     
  15. geher

    geher Гуру

    Тут на самом деле совсем не 50 дней, а гораздо меньше. Поскольку currentMillis в данном случае int, то в него "влезет" всего чуть больше 32 секунд.
    И, как выясняется практически, данные "грабли" могут приводить практически на ровном месте к интересным спецэффектам.
     
    Пушной звер нравится это.
  16. 9xA59kK

    9xA59kK Гик

    Правильное замечание , если использовать на полную, то надо использовать другой тип переменной Unsigned long.
    http://arduino.ru/Reference/UnsignedLong
     
    Последнее редактирование: 13 сен 2014