Управление освещением Ардуино

В этой стать я хотел бы более подробно рассмотреть проект сценарного освещения прихожей, технические аспекты подбора оборудования, написания программы для контроллера. Информация будет интересна людям занимающимся микроконтроллерами, программированием и автоматическими системами управления. Пожалуй стоит начать с электрической схемы: sheme_А3   Управление осуществляется двумя светодиодными лентами, одна на потолке ( дневной и вечерний режим), другая вдоль плинтуса(ночной режим). Для потолка была выбрана лента SMD 5050, 300 светодиодов на 5 метров ( 12V 72W). Эта светодиодная лента наиболее подходит для освещения помещения, так как имеет приятный теплый свет и достаточную яркость, обеспечивающую достаточную освещенность. Подобрать подобный цвет с помощью RGB ленты сложно, из-за преобладания в ней синего цвета и световой поток теплого цвета будет небольшим. Потолочный свет   Для ночной подсветки была выбрана лента SMD 5050 RGB, 150 светодиодов на 5 метров.Лента менее яркая чем потолочная, за счет меньшего количества светодиодов, что как раз подходит для нашего случая. Для этой ленты легко подобрать необходимый цвет и яркость, об этом поподробнее ниже. Ночной свет Для управления всей системой используется контроллер Arduino UNO. Включение потолочной лентой осуществляется с помощью реле в составе relay shield с катушкой на 5V. Ночной свет, управляется транзисторным модулем L298N ( обратите внимание на инверсию выходного сигнала в данном модуле значение 255 в программе будет выключать светодиоды). В нашем случае используется 1 из 4 каналов, управляющий синим цветом ленты. Яркость ленты установленная в программе на минимальную. При желании яркость можно еще уменьшить используя угловой профиль светильника, таким образом освещать только пол. Сейчас часто используются светильники отраженного света, не слепящие и не создающие большое количество бликов, что на мой взгляд очень удобно. Arduino for site Simplea Включение освещения происходит по двум  датчикам движения, как в дневном там и в ночном режиме. Датчик движения В корпусе одного из датчиков  установлен IR приемник, для возможности дистанционного управления с пульта. Расположения датчика над дверью показало себя вполне работоспособным, при открытии входной двери датчик включает свет еще до того как человек заходит в комнату. Второй датчик установлен рядом с зеркалом и охватывает «слепые» зоны датчика находящегося у двери. Это полезно при длительном использовании зеркала, когда человек находится спиной к датчику Pir Door и совершает небольшие движения руками, в таком случае, срабатывает датчик pir Mirror, сохраняя свет включенным. Зона охватываемые датчиками можно посмотреть на плане квартиры. Room plan   Более подробно работу системы можно посмотреть в программе.
Открыть код
#include "IRremote.h"
int calibrationTime = 10;
byte CellingLed = 9; /* Лента потолка */
byte ledB = 6; // лента пола
byte pirDoor = 5; // Датчик Движения
byte pirMirror = 4; //Датчик у Зеркала
IRrecv irrecv(2); // IR сенсор
byte dayNight = 7; // режим управления, кнопка - день/ночь
decode_results results;
byte irSignal = 0;
byte irDay;
byte irNight;
byte irAllOff;
byte buttonstate;
long unsigned int moveTime; // Время в которое принят сигнал отсутсвия движения
long unsigned int pause = 30000; // Пауза, после которой движение считается оконченным
boolean movementDetected = true; // true - движения нет
boolean moveFlag; // Сигнализирует о необходимости запомнить время начала отсутствия движения
void setup ()
{
irrecv.enableIRIn();
Serial.begin(9600);
pinMode(CellingLed,OUTPUT);
pinMode(ledB,OUTPUT);
digitalWrite(dayNight, HIGH); // включение внутренней подтяжки на входе 7
pinMode(pirDoor,INPUT);
pinMode(pirMirror,INPUT);
digitalWrite(pirDoor, LOW);
digitalWrite(pirMirror, LOW);
// Калибровка датчиков движения
Serial.print("Calibrating");
for(int i = 0; i < calibrationTime; i++)
{
Serial.print(".");
delay(1000);
}
Serial.println(" done");
Serial.println("SENSOR ACTIVE");
delay(50);
}

void loop()
{
if ( irrecv.decode( &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;results)){
delay(300);
if (results.value == 0xFF3AC5) {irSignal = 0;} /* Задание заранее считанных ИК сигналов пульта */
if (results.value == 0xFFBA45) {irSignal = 1;}

irrecv.resume();
}
// Селектор режима управления (день/ночь, IR вкл/выкл)
byte DayNightSwitch = !digitalRead(dayNight);
byte a;
byte b;
if (DayNightSwitch == LOW) {a=1;} else {a=0;}
if (irSignal == 1) {b=1;} else {b=0;}
if (a==b) {buttonstate = 1;}
else {buttonstate = 0;}
byte pirstate;
if (digitalRead(pirDoor) == HIGH || digitalRead(pirMirror) == HIGH)
{ pirstate = HIGH;}
if (digitalRead(pirDoor) == LOW &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; digitalRead(pirMirror) == LOW)
{ pirstate = LOW;}

// лента пола
if(pirstate == HIGH &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; buttonstate == 0 )
{
if(movementDetected)
{
movementDetected = false;
Serial.println("Motion detected");
delay(50);
}
moveFlag = true;
analogWrite(ledB,240);// приглушенный синий
digitalWrite(CellingLed, LOW);
}
if(pirstate == LOW &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; buttonstate == 0 )
{
if(moveFlag)
{
moveTime = millis();
moveFlag = false;
}
if(!movementDetected &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; millis() - moveTime > pause )
{
movementDetected = true;
Serial.println("Motion finished");
delay(50);
analogWrite(ledB,255);//выключение ленты
}
}
// лента потолка со счетчиком движения
if (pirstate==HIGH &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; buttonstate == 1 )
{
// установка таймера ожидания движения 5сек
if(movementDetected)
{
movementDetected = false;
Serial.println("Motion detected");
delay(50);
}
moveFlag = true;
digitalWrite(CellingLed,HIGH);
analogWrite(ledB,255);
}
if (pirstate == LOW &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; buttonstate == 1 )
{
if(moveFlag)
{
moveTime = millis();
moveFlag = false;
}
if(!movementDetected &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; millis() - moveTime > pause )
{
movementDetected = true;
Serial.println("Motion finished");
delay(50);
digitalWrite(CellingLed,LOW);
}
}
//Данные для пусконаладки
/*
Serial.print("Door");
Serial.println(digitalRead(pirDoor));
Serial.print("Mirror");
Serial.println(digitalRead(pirMirror));
Serial.print("buttonstate");
Serial.println(buttonstate);
Serial.print("pirstate");
Serial.println(pirstate);
delay(1000);
*/
}
А также код для web интерфейса
Открыть код

#include <SPI.h>
#include <Ethernet.h>
boolean newInfo = 0;
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };
IPAddress ip(192,168,1,9);
EthernetServer server(80);

int CellingLed = 9; /* Лента потолка */
int ledR = 6; // лента пола
int ledG = 3; // лента пола
int ledB = 5; // лента пола
int pir = 4; // Датчик Движения

int dayNight = 7; // режим управления, кнопка - день/ночь

int irSignal;
int irDay;
int irNight;
int irAllOff;
int buttonstate;

void setup ()
{

Ethernet.begin(mac, ip);
server.begin();
Serial.begin(9600);
pinMode(CellingLed,OUTPUT);
pinMode(ledR,OUTPUT);
pinMode(ledG,OUTPUT);
pinMode(ledB,OUTPUT);
pinMode(pir,INPUT);
digitalWrite(dayNight, HIGH); // включение внутренней подтяжки на входе 7
}
void loop()
{

//принимаем данные, посылаемые клиентом
EthernetClient client = server.available();
if(client){ //если запрос оканчивается пустой строкой
boolean currentLineIsBlank = true; //ставим метку об окончании запроса (дословно: текущая линия чиста)
while (client.connected()) { //пока есть соединение с клиентом
if (client.available()) { //если клиент активен
char c = client.read(); //считываем посылаемую информацию в переменную "с"

if(newInfo &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; c == ' '){ //если переменная новой информации = 1 и "с", в которой записан запрос, равен пустой строке
newInfo = 0; //то обнуляем переменную поступления новой информации
}

if(c == '$'){ //если переменная "с", несущая отправленный нам запрос, содержит символ $
//(все новые запросы) - "$" подразумевает разделение получаемой информации (символов)
newInfo = 1; //то пришла новая информация, ставим метку новой информации в 1
}
//Проверяем содержание URL - присутствует $1 или $2

if(newInfo == 1){ //если есть новая информация
Serial.println(c);
if(c == '1'){ //и "с" содержит 1
Serial.println("ON");
digitalWrite(CellingLed, HIGH); //то зажигаем светодиод
}

if(c == '2'){ //если "с" содержит 2
Serial.println("OFF");
digitalWrite(CellingLed, LOW); //выключаем светодиод
}
if(c == '3'){
Serial.println("OFF");
analogWrite(ledR,240);
}
if(c == '4'){
Serial.println("OFF");
analogWrite(ledR,255);
}
}
if (c == '\n') { //если "с" равен символу новой строки
currentLineIsBlank = true; //то начинаем новую строку
}
else if (c != '\r') { //иначе, если "с" не равен символу возврата курсора на начало строки
currentLineIsBlank = false; //то получаем символ на текущей строке
}

if (c == '\n' &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; currentLineIsBlank) { //выводим HTML страницу
client.println("HTTP/1.1 200 OK"); //заголовочная информация
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 30"); //автоматическое обновление каждые 30 сек
client.println();
client.println("<!DOCTYPE HTML>"); //HTML тип документа
client.println("<html>"); //открытие тега HTML
client.println("<head>");
client.print("<title>My web Server</title>"); //название страницы
client.println("</head>");
client.println("<body style='text-align: center;' >");
client.println("<div style=' font-size: 40px;'>");

client.print("<H1>My web Server</H1>");
client.print("<a href=\"/$1\"><button style=' font-size: 60px; margin: 50px 50px 0px 50px;'>On</button></a>");
client.print("<a href=\"/$2\"><button style=' font-size: 60px; margin: 50px 50px 0px 50px;'>Off</button></a>");
client.print("<a href=\"/$3\"><button style=' font-size: 60px; margin: 50px 50px 0px 50px;'>On</button></a>");
client.print("<a href=\"/$4\"><button style=' font-size: 60px; margin: 50px 50px 0px 50px;'>Off</button></a>");
// client.println("<br />");
client.println("</div>");
if (digitalRead(pir)== HIGH)
{ client.print("<span>Motion detected</span>");
}
client.println("</body>");
client.println("</html>"); //закрываем тег HTML
break; //выход
}
}
}

/*Serial.println(" Botton");
Serial.println(DayNightSwitch);
Serial.println(irSignal);
Serial.println(" BottonState");
Serial.println(buttonstate); */
delay(1);
client.stop();
}
}

Файл с кодом на яндекс диске.

Файл с кодом для веб интерфейса на яндекс диске

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *