Датчик движения и подсветка на базе CROW MH-20 и ATTiny
- Войдите на сайт для отправки комментариев
Суть вопроса такова. Есть датчик безопасности CROW MH-20 и светодиодная лента, питающиеся от 12В. С помощью тиньки 45 хотел сделать автоматический ночник. Написал код, который с Ардуино Уно и всем остальным работает превосходно. Лента включается, контроллер ждет по циклу заданное количество времени и выключает ленту, не выключая при этом контроллер, т.е. не снимая напряжения с ноги 4.
После переноса на attiny45 код работает странно. Он проходит одну итерацию, после чего по непонятной мне причине снимает напряжение с ноги 4, которая является ключом для контроллера. Вопрос - почему?
Прилагаю логику, принципиальную схему и код прототипа.
http://funkyimg.com/view/SrMu - логика
http://funkyimg.com/view/SrMv - принципиальная схема
Код:
/* * PIR night light sensor is made from Crow MH-20 security sensor */ #include <SendOnlySoftwareSerial.h> SendOnlySoftwareSerial mySerial(0); //TX int mosfetPin = 1; // 1(pin1) - ATTiny / 4 - Arduino UNO int lightPin = A1; // A1(pin2) - ATTiny / A0 - Arduino UNO int relayPin = 3; // 3(pin3) - ATTiny / 2 - Arduino UNO int npnPin = 4; // 4(pin4) - ATTiny / 3 - Arduino UNO boolean light = false; boolean relay = false; void setup(){ pinMode(relayPin, INPUT); pinMode(lightPin, INPUT); pinMode(npnPin, OUTPUT); pinMode(mosfetPin, OUTPUT); mySerial.begin(9600); } void loop(){ //Если свет включен, снимаем напряжение с транзисторов if(analogRead(lightPin) > 300){ if(light == true) return; mySerial.println("LIGHT IS ON"); light = !light; digitalWrite(npnPin, LOW); digitalWrite(mosfetPin, LOW); } else { //Если свет выключен и флаг light был переключен в true //подаем напряжение на npn-транзистор, который работает в //ключевом режиме для датчика безопасности MH-20 if(light == true){ mySerial.println("LIGHT IS OFF"); light = !light; delay(500); digitalWrite(npnPin, HIGH); mySerial.println("ALARMING..."); //Задержка на дребезг реле MH-20 delay(3000); //MH-20 после запуска прогревается примерно минуту, ждем while(digitalRead(relayPin) == LOW){ if (analogRead(lightPin) > 300) return; delay(1000); } //После прогрева переходим в режим охраны в котором замыкается //реле датчика MH-20 mySerial.println("ALARM IS ON"); } else { //Когда обнаружено движение - реле выключается. //Подаем напряжение на полевой транзистор для светодиодной ленты if(digitalRead(relayPin) == LOW && relay == true){ mySerial.println("IS ANYBODY IN THERE?.."); relay = !relay; digitalWrite(mosfetPin, HIGH); //Ждем 30 секунд до выключения for(int i=0; i<30; i++){ if(analogRead(lightPin) > 300) return; //Если обнаружено движение, сбрасываем счетчик цикла if(digitalRead(relayPin) == LOW) i = 0; delay(1000); mySerial.println(i); } //Пока движения в периметре нет, реле включено, //напряжение с ноги полевого транзистора снято } else if (relay == false){ mySerial.println("HERE IS NOBODY ELSE.."); relay = !relay; digitalWrite(mosfetPin, LOW); } } } }
Заранее всем спасибо.
а зачем стоит return из loop - это не корректно как то?
В случае включения света прерывается выполнение программы, выполняется возврат к первому условию и снимается напряжение с базы транзистора VT1. В первой версии кода было по другому, решил, что так удобнее и понятнее. Ардуино такую конструкцию обрабатывает без затруднений.
Ау. Гуру, подскажите, в чем моя ошибка?
Спасибо.
mySerial.println(
"LIGHT IS ON"
);
light = !light;
пишите лучше light=true;
да и вообще условия скомбинировать лучше, понятнее будет и правильнее
И корова Ваша может не отпускать, проверьте=)
attiny45 - проверьте питание, может недостаточно
Спасибо за комментарий.
light = true или light = false не играет роли, разве что упрощает чтение кода.
Не совсем ясно про корову, она питается отдельной шиной в 12В. На attiny подается 5В по отдельной шине стабильно. Единственная разница между тинькой и мегой в тактовой частоте. Но я не совсем понимаю, как разница в тактовой частоте может влиять на исполнение кода.
Важно проверить, при каких условиях отваливается 4й пин. Советую проверить работу пина на простейшем скетче, может даже заново переписать код, часто помогает, а писать относительно пина. Если проблема хардварная, она всплывет=)
Корова (у меня - другой PIR сенсор) порой не сползает в LOW при отсутствии движения, может быть еще в этом проблема..
Можете пояснить, зачем такая штука используется? SendOnlySoftwareSerial
Не слышал о таком=)
используется, т.к. ног в микрухе для отладки не хватает.
Эта библиотека позволяет использовать только одну ногу для отправки сообщений в UART.
Проблема в том, что данная проблема (с пропаданием HIGH на ноге) наблюдается как на ATTiny13, так и на ATTiny45, т.е. она не является аппаратной. На Ардуино все ОК.
Переписал код. Поудалял булевы переменные, бесконечные условия и отладочный вывод SoftwareSerial.
В PROTEUS заработало, вечером на прототипе проверю.
Пришел домой, проверил. Парадокс. На ATTiny45 код работает корректно, а на ATTiny13 не хочет включать PB1 ни в какую через программу в функции _watchDog(). Eсли залить скетч с мигалкой на этой ноге, то все работает.
При этом парадоксально, но если поменять порядок использования ног в контроллере, т.е. использовать PB1 в качестве OUTPUT до использования PB4 в этом же качестве в цикле loop(), то все отрабатывает корректно.
Т.е. вместо:
Задаем переменные следующего порядка:
И изменяем коммутацию в схеме.
Не спроста все же твердят "учите матчасть, с ардуиной далеко на эмбеддед не уедешь")
Вчера, играясь с макетной платой, заметил одну особенность. В момент снятия логической 1 с ноги mosfetPin, кратковременно снимается 1 с ноги npnPin. Это можно компенсировать, установив фильтрующий конденсатор, но сама физика явления не ясна. На эмуляторе никаких скачков напряжения нет:
Некорректно подписал луч npnPin.
OFF - свет выключен, npnPin == HIGH
ON - свет включен, npnPin == LOW.