Фоторезистор плюс PIR
- Войдите на сайт для отправки комментариев
Здраствуйте. Пытаюсь собрать датчик движения на Arduino Nano, фоторезистор, PIR HC-SR501 и реле для ардуино.
Цель сделать что бы реле включалось только когда темно, в сети нашел скетчи примеры для работы с реле, PIR и фоторезистор и все это как смог объеденил воедино. Впринципе получился работоспособный скетч, но работает не много не так как хотелось бы. Сейчас он работает так: Считывает показания с PIR и если есть движение, то проверяется темно ли и если темно то включается реле, но если станет светло реле тут же отключается. И так может бесконечно пока идет сигнал движения с датчика движения.
А вот как переделать что бы сначало проверялось темно ли, а потом в зависимости от показаний PIR включалось реле, не могу...
Хотелось бы что бы когда темно реле включалось от показаний PIR и если станет светло не отключалось пока идет сигнал с датчика движения.
int ledPin = 13; // инициализируем пин для светодиода
int ldr = 0; // фоторезистора
int inputPin = 2; // инициализируем пин для получения сигнала от пироэлектрического датчика движения
int relePin = 4;
int pirState = LOW; // начинаем работу программы, предполагая, что движения нет
int releState = LOW;
int val = 0; // переменная для чтения состояния пина
void setup() {
pinMode(ledPin, OUTPUT); // объявляем светодиод в качестве OUTPUT
pinMode(inputPin, INPUT); // объявляем датчик в качестве INPUT
pinMode(relePin, OUTPUT);
Serial.begin(9600);
}
void loop(){
val = digitalRead(inputPin) ; // считываем значение с датчика
if (val == HIGH && (analogRead(ldr) < 300)) { // проверяем, соответствует ли считанное значение HIGH
digitalWrite(ledPin, HIGH); // включаем светодиод
digitalWrite(relePin, LOW);
delay (1000);
if (pirState == LOW) {
// мы только что включили
Serial.println("Motion detected!");
// мы выводим на серийный монитор изменение, а не состояние
pirState = HIGH;
}
} else {
digitalWrite(ledPin, LOW); // выключаем светодиод
digitalWrite(relePin, HIGH);
if (pirState == HIGH){
// мы только что его выключили
Serial.println("Motion ended!");
// мы выводим на серийный монитор изменение, а не состояние
pirState = LOW;
}
}
}
В программировании полный ноль((
Спасибо всем.
Хотелось бы что бы когда темно реле включалось от показаний PIR и если станет светло не отключалось пока идет сигнал с датчика движения.
Сами поняли чего написали ? я нет, растолкуйте.
Здраствуйте. Пытаюсь собрать датчик движения на Arduino Nano, фоторезистор, PIR HC-SR501 и реле для ардуино.
Пытался понять, что делает твое устройство, но не понял.
Я делал похожее устройство, которе сейчас исправно работает, вот ссылка http://arduino.ru/forum/programmirovanie/khochu-posmotret-vo-chto-prevratyat-moi-kod-professionaly.
Код я потом дописывал по советам бывалых, но на работоспособность еще не проверял. Прилагаю измененный код:
#include <LiquidCrystal.h> //дисплей использовался только для выяснения % освещенности на месте, чтоб не таскать с собой бук. Когда нужный процент освещенности найден, то можно удалить все упоминания об экране. #include <EEPROM.h> #define buttonPin 12 //пин датчика движения #define ledPin 11 //пин подключения светодиодной ленты #define lightMeterPin A0 //пин подключения датчика освещенности - фоторезистор, х/з что за марка, какой-то валялся #define persentLight EEPROM.read(1) //чтоб каждый раз не писать этот еепром. #define potentiometr A1 //подстроечник для настройки предела освещенности. используется для настройки уровня освещенности для включения ленты. #define buttonValuePin 3 //пин кнопки для записи мануального значения освещенности в память устройства. можно и без нее, но я классную кнопку выпаял из старого сидюка, и мне захотелось её израсходовать. #define step_delay 8 //замедление циклов зажигания и затухания ленты. #define max_val 200 //максимальное значение яркости ленты. byte lightLevel = 0; //переменная со значением уровня яркости ленты. LiquidCrystal lcd(9, 8, 7, 6, 5, 4); byte persentLightVal = persentLight; //=================================================================================================================================================================================================================== void setup() { if (persentLightVal > 100) { //если нас не устраивает значение сохраненного уровня минимальной освещенности, то записываем дефолтное значение. EEPROM.write(1, byte(25)); //если значение освещенности в памяти больше 100%, то пишем в память значение 25. } { //описываем типы пинов pinMode (buttonPin, INPUT); //датчик движения - вход pinMode (ledPin, OUTPUT); //лента - выход //digitalWrite(ledPin, LOW); // подстраховаться и отключить подсветку при загрузке устройства. pinMode (lightMeterPin, INPUT); //датчик освещенности - вход pinMode(A1, INPUT); //подстроечный резистор для настройки минимального уровня освещенности. pinMode(buttonValuePin, INPUT); //кнопка для записи в память значения минимальной освещенности. } { //занимаемся ерундой, пока тупит датчик движения. время протупления извещателя - 70 секунд (моему датчику движения необходимо 65 секунд, чтоб загрузиться) uint32_t old_m = millis(); const uint32_t start_time = old_m; boolean sostoyanie = false; while (start_time + 70000 > millis()) { if (old_m + 2000 < millis()) { old_m = millis(); analogWrite(ledPin, max_val * sostoyanie); sostoyanie = !sostoyanie; } } digitalWrite(ledPin, LOW); } { // пишем названия полей на ЛЦД lcd.begin(20, 4); lcd.setCursor(0, 0); lcd.print("Fotoresist."); //значение АЦП с фоторезистора/значение минимальной освещенности lcd.setCursor(0, 1); lcd.print("DD relay"); //статус датчика движения lcd.setCursor(0, 2); lcd.print("Value"); //отсчет секунд с момента старта платы. Просто была строчка на экране лишняя. lcd.setCursor(0, 3); lcd.print("Manual val."); //значение АЦП с подстроечника установки уровня минимальной освещенности. } } void loop() { //объявление переменных более правильным способом //======== <a data-cke-saved-href="http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-2-staticheskie-peremennye" href="http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-2-staticheskie-peremennye" rel="nofollow">http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-2-staticheskie-peremennye</a> ======== static byte manualValue; //значение подстроечника для записи в память приведенное к % static uint32_t timer1 = 0; //таймер для параметра timeToLive static boolean powerOn = false; //параметр 1-лента включена, 2 - лента выключена static uint32_t timeToLive = 5000; //время, которое должна прогореть лента, до проверки условий выхода из цыкла static boolean napravlenie = false; //переменная для определения включения/выключения ленты. if (digitalRead(buttonPin) == LOW && lightMeter() <= persentLightVal && powerOn == false && lightLevel >= 0) { //проверка условий для включения ленты napravlenie = true; powerOn = true; timer1 = millis(); //по нему отсчитывать жизненный цикл включенной ленты } if (napravlenie == true && lightLevel < max_val) { //плавно зажигаем ленту vmestoFor(napravlenie); } if (millis() >= timer1 + timeToLive - 2000 && millis < timer1 + timeToLive && lightMeter() <= persentLightVal && digitalRead(buttonPin) == LOW) { //продлеваем TTL ввиду того, что люди еще шевелятся, а освещенность недостаточная. timer1 = millis(); } if (powerOn == true && timer1 + timeToLive <= millis() && (lightMeter() > persentLightVal || digitalRead(buttonPin) == HIGH) && lightLevel > 0) { //проверка условий для выключения ленты. napravlenie = false; powerOn = false; } if (napravlenie == false && lightLevel > 0) { //плавно гасим ленту vmestoFor(napravlenie); } { //обработка уровня минимальной освещенности. manualValue = map(analogRead(potentiometr), 0, 1024, 1, 100); //значение в % с подстроечника, которым мы будем регулировать минимальный уровень освещенности. if (digitalRead (buttonValuePin) == HIGH) { //записываем значение минимального уровня освещенности в еепром, если мы нажали спец.кнопочку. if (persentLightVal != manualValue) { //заись нового уровня освещенности в память EEPROM.write(1, manualValue); persentLightVal = EEPROM.read(1); } } } { //вот с этого места выводим всякую инфу на экран. после настройки можно все это отключить. lcd.setCursor(12, 2); lcd.print(lightLevel); lcd.print (" "); static uint32_t timer2 = 0; //используется для экрана, чтоб изображение не мельтешило. если от экрана отказываться, то спокойно можно удалять. if (timer2 + 500 <= millis()) { lcd.setCursor(12, 0); //АЦП фоторезистор lcd.print(" "); lcd.setCursor(12, 0); lcd.print(lightMeter()); lcd.print("/"); lcd.print(persentLightVal); timer2 = millis(); lcd.setCursor(12, 3); lcd.print(manualValue); lcd.print(" "); lcd.setCursor(12, 1); if (digitalRead(buttonPin) == HIGH) { lcd.print("ON "); } else { lcd.print("OFF"); } } } } byte lightMeter () { //функция для определения уровня освещенности в относительных единицах byte persents = map(analogRead(lightMeterPin), 0, 1024, 1, 100); //byte(analogRead(lightMeterPin) / (1024 / 100)); //не уверен, что в байте это значение считается правильно, но в данной конструкции это не играет существенной роли. return persents; } byte vmestoFor (boolean napravlenie) {//функция замены цикла ФОР. тру - вверх, фолс - вниз static byte val = 0; static uint32_t om = millis(); uint32_t nm = millis(); if (nm - om > step_delay) { om = nm; if (napravlenie == true) {// направление вверх val++; } if (napravlenie == false) {//направление вниз val--; } lightLevel = val; } analogWrite(ledPin, val); }Все, что связано с экраном можешь спокойно удалять, просто моя плата или ее хозяин не умеет с монитором порта общаться.
Есть одна бага (я так изначально не задумывал), которую я считаю фичей: если у тебя начинает гаснуть лента, но датчик движения в это время сработал, то она снова набирает яркость. Знаю как это устранить, но мне так больше нравится.
реле воткнешь в нужную часть кода.
Я имею ввиду следующие. Когда при показаниях фоторезистора темно реле включалось от показаний датчика движения, сигнал движения идет например 15 секунд и если в этом промежуток времени станет светло надо что бы реле не отключалась.
Определил - темно+сработка датчика. Следующее определение темно-светло после выключения света.
Или - запрещено определять темно-светло пока включен свет.
Так вот как это в коде написать я не могу додуматься
digitalRead (pinSvet); вставляем в if и смотрим, надо проверять на темно-светло или нет.
Задача совершенно элементарная: у нас два внешних условия:
- движение / нет движения,
- светло / темно.
И одно внутреннее состояние:
- свет горит / не горит.
Очевидно, что изменение внутреннего состояния нужно синхронмизировать с изменением внешнего, а для этого его нужно хранить в переменной.
Очевидно, что есть 4-х внешних комбинации:
1. движение, светло.
2. движение, темно.
3. нет движения, светло.
4. нет движения, темно.
это дает 12 возможных переходов (расписывать лень).
остается лишь посадить на нужные переходы нужные варианты реакции, а остальные игнорировать.
Все это пишется в одну строчку. Точнее, в две: одну на включение и одну на выключение.
Задача действительно элементарная - впаять фоторезистор в предназначенное для него место в SR-501. После этого он(PIR-сенсор) будет выдавать сигнал об обнаружении движения только в темноте. У меня таким образом работает ночная подсветка на Tiny13 и светодиодах.
Я не спорю что элементарная, но для меня это сложно, можете сказать какую строчку добавить что бы что бы включение и выключение реле работало только когда темно.
Я так понимаю надо перед строкой 23 добавить строчку которая бы проверяла темно ли или нет, и если темно то выполняла строки ниже, светло пропускала
Тут нужно не добавлять строчку, а переписывать все с нуля.
Мне кажется, в этом и есть Ваша проблема: Вы сами не знаете, что Вам нужно.
По логике, как Вы описали, оно в принципе никогда не сможет выключиться, т.к. при включенном свете никогда не будет темно.
Ну да проще унизить автора чем, какая цель тогда этого форума. мне надо что бы ночью ардуино включало свет когда движение есть, а когда день не реагировало. Спасибо всем за помощь.
Есть свет - обесточили датчик движения, нет - запитали. И ардуины не нужно.
Насколько знаю, на самой плате датчика движения есть места, где не установленны радиодетали, что бы учитывать наличие освещения. И снова ардуина не нужна.
"// начинаем работу программы, предполагая, что движения нет" -//начинайте работу программы выяснив, если ли свет. И только убедившись, что его нет, идти дальше . Думаю будет попроще.1
Ардуино нужно что бы реле включать, на прямую от датчика не работает
Поправьте грамматику постом выше, читается весело.
Кто напрямую от датчика не работает?
Почитайте о назначении вывода 9 в микросхеме этого датчика.
Кто напрямую от датчика не работает?
Реле для ардуино не работает на прямую от датчика PIR.
А в ардуино можно разделить void loop на две части? Что бы когда первая часть была "верна" выполнялась вторая часть.
Для этого можно применить оператор IF.
Не уверен, что нельзя заставить реле для ардуины, работать не от ардуины.
А в ардуино можно разделить void loop на две части? Что бы когда первая часть была "верна" выполнялась вторая часть.
УПС, а функции уже отменили?
Я не знаю языка совсем, есть статьи по функциям хорошие?
добавил if (analogRead (ldr)<300) перед всем, да вроде бы как надо, темно появилось движение реле включилось и пока идет сигнал с датчика движения не тухнет, но когда сигнал с PIR пропал потухнет только когда станет темно. А если реле будет вкл свет, то получается никогда он не потухнет
Прожиточный минимум здесь
Значит меняйте логику работы. Ищите движение и после его обнаружения проверяйте наличие света. Или датчик света выносите подальше от лампы, что бы не засвечивался.
А язык, хотя бы примитивно, изучить придётся. Как же иначе ардуиной командовать?
Изучайте, задача не кажется сложной.
у меня в шапке как раз такая логика как Вы написали, но в даном случае если становится светло реле сразу отклчается. И в итоге будет свет включился фоторезистор засветился, свет выключился стало темно и опять свет вкл и так пока идет сигнал с PIR
Кстати. Если включили свет, то можно и не заниматься проверкой его величины, пока свет включен. Вот когда погасите лампу, лишь когда начинайте снова проверять уровень освещённости.
А разве свет включают не на какой то промежуток времени (дойти до двери)?
Вот именно это я и хочу узнать как сделать) функцией воспользоваться нужно какой либо?
Длительность сигнала с RIP можно регулировать (подстроечным резистором). Сделайте сигнал коротким, а время свечения продолжительнее.
"Какую либо" функцию Вы напишите сами, когда освоите, хотя бы, пять...семь операторов.
Не научившись ходить, бегать не научишься.
данной базы хватит? http://arduino.ru/Reference
данной базы хватит? http://arduino.ru/Reference
Этого достаточно для тех, кто умеет программировать, но этого совершенно недостаточно, чтобы научиться программировать.
Поищите как: http://boteon.com/upload/files/b89a840d561f471188d443b8e68b308b.pdf
http://boteon.com/upload/files/9656deb6c0b61d212f3a19909c2cc029.pdf
Спасибо
Попробовал исправить Ваш код. Проверяйте:
#define ledPin 13 // инициализируем пин для светодиода #define ldr 0 // фоторезистора #define inputPin 2 // инициализируем пин для получения сигнала от пироэлектрического датчика движения #define relePin 4 int pirState = LOW; // начинаем работу программы, предполагая, что движения нет int releState = LOW; unsigned long time = 0; int val = 0; // переменная для чтения состояния пина void setup() { pinMode(ledPin, OUTPUT); // объявляем светодиод в качестве OUTPUT pinMode(inputPin, INPUT); // объявляем датчик в качестве INPUT pinMode(relePin, OUTPUT); Serial.begin(9600); } void loop(){ val = digitalRead(inputPin) ; // считываем значение с датчика if (val == HIGH && (analogRead(ldr) < 300)) { // проверяем, соответствует ли считанное значение HIGH digitalWrite(ledPin, HIGH); // включаем светодиод digitalWrite(relePin, LOW); time = millis(); pirState = 1; } if (val == HIGH) time = millis(); if(pirState == 1 && millis()- time >= 1000){ digitalWrite(ledPin, LOW); // выключаем светодиод digitalWrite(relePin, HIGH); pirState = 0; } if (pirState)Serial.println("Motion ended!"); else Serial.println("Motion detected!"); }Реле для ардуино не работает на прямую от датчика PIR.
Неправда, работает.
Свою мечту я осуществил как смог, да может тупо, не красиво, не правильно, но как смог так и сделал и работает так как я и хотел.
Вот что у меня получилось.
/* Делаем датчик движения */ int ledPin = 13; // инициализируем пин для светодиода int ldr = 0; // пин фоторезистора int inputPin = 2; // инициализируем пин для получения сигнала от пироэлектрического датчика движения int relePin = 4; // пин реле int pirState = LOW; // начинаем работу программы, предполагая, что движения нет int releState = LOW; int val = 0; // переменная для чтения состояния пина void setup() { pinMode(ledPin, OUTPUT); // объявляем светодиод в качестве OUTPUT pinMode(inputPin, INPUT); // объявляем датчик в качестве INPUT pinMode(relePin, OUTPUT); // объявляем реле в качестве OUTPUT Serial.begin(9600); } void loop() { if (analogRead (ldr)>300) // проверяет темно ли? { digitalWrite(relePin, HIGH); // если светло то реле выключено } else if (digitalRead(inputPin) == HIGH) // если темно проверяет есть ли сигнал с PIR { while (digitalRead(inputPin) == HIGH) { // если есть выполняет цикл void releon releon(); } } else { digitalWrite(relePin, HIGH); // если нет сигнала реле оф } } void releon() { digitalWrite(relePin, LOW); // цикл реле он }Спасибо всем кто помог идиоту т.е. мне)
И подскажите пожалуйста как прятать под спойлер)
Когда вставляете код, вкладка "дополнительно", "свернуть".