Добрый день. Имею вот какой вопрос : есть плата 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 но я только делаю первые шаги ,по этому не все понимаю . Спасибо заранее.
Скетч не тот что ты описываешь. Какой используешь выход для реле? Где в коде включение реле, где условие при котором оно включается?
Использование функции millis() http://arduino.ru/tutorials/BlinkWithoutDelay Если что то не понятно спрашивай, хотя там все хорошо описано. Есть там еще версия - которая мне тоже понравилась http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-bez-delay
не очень понимаю как тут поможет millis() мне вот логика этого куска непонятна //Если обнаружили движение if(pirVal == HIGH) { digitalWrite(ledPin, HIGH); Serial.print(" Motion detected "); delay(60000); } else { Serial.print(" No motion "); digitalWrite(ledPin,LOW); } какая в этом практическая польза??
Я полагаю, что логика такая: Обнаружили движение - значит, что-то зашевелилось, и, чтобы не забивать канал сигналами, на минуту останавливается обнаружение движения. Все равно сигнал подан и за минуту новый сигнал скорее всего будет продолжением старого. Когда делал сигнализацию, отсылающую СМС и делающую звонок при срабатывании, делал примерно так же. Но в свете постоянного вывода Serial.print(" No motion "); это становится неочевидным и бессмысленным.
Главное понять сам принцип как заменить функцию 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 секунда то включаем Светодиод } }
Это конечно грубые цифры но надеюсь стало понятнее. Выше в примере не хватало фигурной скобки во втором условии- исправил
Вовсе не перестанет, и это не тот таймер об котором вы подумали. Здесь не используются грубо говоря все 50 дней таймера. Когда таймер превысит грубо 50 дней он просто сбросится от переполнения и начнет счет заново. И в данном коде выше ничего страшного не произойдет. Просто в некоторых случаях это надо учитывать.
Подумайте посчитайте и сразу все поймете. Именно в данном случае ничего страшного не произойдет. Ответ лежит на поверхности. Сразу скажу для особо пытливых умов- на этот случай тоже есть выход ,немного доработать код программы и не для ленивых ГУГЛ в помощь. На случай если милис не подходит - можно самому написать таймер счетчик к примеру использовать прерывание и т.п. Можно использовать внешний примитивный таймер из транзистора и пары конденсаторов и сопротивлений подключить на цифровой пин и счтить импульсы и т.д. Вообще контроллер очень гибкая штука многое можно придумать, главное иметь терпение и желание.
я какбы задал вполне конкретный вопрос, ответ на который, лежит на поверхности. только вот предлагается использовать миллис.
Тут на самом деле совсем не 50 дней, а гораздо меньше. Поскольку currentMillis в данном случае int, то в него "влезет" всего чуть больше 32 секунд. И, как выясняется практически, данные "грабли" могут приводить практически на ровном месте к интересным спецэффектам.
Правильное замечание , если использовать на полную, то надо использовать другой тип переменной Unsigned long. http://arduino.ru/Reference/UnsignedLong