EN

ARDUINO – КОНТРОЛЕР СИСТЕМИ ОСВІТЛЕННЯ
З WEB-СЕРВЕРОМ НА ORANGE PI ZERO

Пропоную опис простого та недорогого пристрою для керування системою освітлення на 6 груп світла через дзвінкові (без фіксації) вимикачі з можливістю керування з комп'ютера та/або смартфона через локальну комп'ютерну мережу без зовнішнього підключення до Інтернету. Роль локального WEB-сервера, що забезпечує WEB-інтерфейс гратиме Linux мікрокомп'ютер, наприклад Orange Pi Zero, NanoPi, Raspberry Pi або будь-який інший аналогічний.

У такій схемі кожна група світла може керуватися з будь-якої кількості вимикачів, які з'єднуються паралельно, чим вирішується проблема прохідних вимикачів та забезпечується можливість дистанційного керування через мережу зі смартфона або комп'ютера.

Цей пристрій ви можете зібрати самостійно дотримуючись цієї інструкції. Передбачається, що ви маєте навички роботи з напругою 220В, макетування та програмування мікроконтролерів Arduino.

Всі компоненти, необхідні для збирання пристрою, можна придбати в інтернет-магазині, наприклад arduino.ua.
Нам знадобляться:
Arduino Nano

Мікроконтролер ARDUINO NANO
або будь-який інший подібний мікроконтролер,
наприклад ARDUINO UNO, MICRO, MINI
Микроконтроллер Orange Pi Zero



Мікрокомп'ютер Orange Pi Zero
або будь-який інший подібний, наприклад, Raspberry Pi.
Він буде виконувати роль локального WEB-сервера і необхідний
для відображення WEB-сторінки управління освітленням.
Ethernet модуль ENC28J60

Ethernet module ENC28J60
Модуль питания TSP-05

Модуль живлення TSP-05 220В - 5В 3Вт
або будь-яке інше джерело живлення 5В/300mA для Arduino
Модуль реле

Три 2-х канальні модулі реле 5В 10А з опторозв'язкою
Можна використовувати й інші,
наприклад 8-канальні модулі реле 5В 10А з опторозв'язкою
або 1-о канальні модулі реле 5В 10А з опторозв'язкою
Выключатель
Дзвінкові вимикачі:
Вимикачі, у яких клавіша пружна і вони
не мають фіксованого положення.
Для управління групою світла з кількох точок,
всі вимикачі можна з'єднувати паралельно.
Принципова схема пристрою:
Мікроконтролер ARDUINO NANO управляє силовими реле, які комутують напругу 220В для шести незалежних груп освітлення, в яких можуть використовуватися лампи будь-якого типу. Максимальна потужність, що комутується, обмежується потужністю застосовуваних реле. Релейні блоки, що пропонуються в описі, розраховані на струм до 10А при використанні ламп розжарювання, це близько 2 кВт на групу висвітлення. Якщо ви хочете забезпечити надійну та довговічну роботу цих реле, не перевищуйте потужність світильників із лампами розжарювання більше 1 кВт на групу.

Для керування з настінних вимикачів використовуються входи А0-А5. Режим управління – тригерний. Кожне наступне натискання клавіші вимикача змінює стан вихідного реле на зворотне: ВКЛ<->ВЫКЛ. Завдяки такому підходу ви можете керувати однією групою світла з будь-якої кількості точок. Для цього достатньо з'єднати необхідну кількість вимикачів паралельно. Для з'єднання вимикачів не обов'язково використовувати силовий електропровід або кабель можна використовувати будь-який сигнальний провід, наприклад FTP. Для ілюстрації такого принципу керування освітленням, наведено нижче анімована схема управління. Кнопки вимикача та кнопки смартфона клікабельні – можете клацнути на них мишкою, щоб побачити, як працює система.


Для керування силовими реле, на контролері ARDUINO NANO використовуються цифрові виходи D4, D5, D5, D7, D8, D9, які з'єднуються із відповідними входами на релейних модулях IN1, IN2.

Для живлення схеми слід використовувати джерело +5В, яке забезпечить струм не менше 250-300 мА. Якщо потужність джерела живлення буде недостатня, мережевий модуль ENC28J60 може не стабільно працювати.
Arduino – контроллер системы освещения с web-сервером на Orange Pi Zero


Алгоритм роботи програми.
Програма, яка буде завантажена в контролер ARDUINO NANO містить три основні логічні блоки, які виконуються циклічно в безкінечному циклі loop().

Перший блок програми ReadInput() відповідає за періодичне опитування стану входів щодо виявлення моменту натискання на клавішу вимикача. У момент натискання клавіші на відповідний вхід контролера подається напруга +5В що інтерпретується контролером як логічна одиниця. Відсутність напруги на вході означає логічний нуль.

Другий блок програми EthernetUpdate() обробляє GET запити з WEB-сторінок на включення і вимкнення груп світла а також передає стан (ВКЛ/ВЫКЛ) груп світла для відображення на WEB-сторінці у смартфоні або комп'ютері.

Третій блок програми SetOutput() керує виходами контролера. У цьому блоці поява логічної одиниці на вході контролера переводить стан відповідного виходу зворотний стан. Тобто, якщо вихід був у стані ВИМК, він перейде у стан ВКЛ і навпаки.

Щоб запрограмувати ARDUINO UNO вам знадобиться бібліотека UIPEthernet. В Arduino IDE 1.8.4 її можна встановити через меню «Скетч»-«Підключити бібліотеку» - "Управляти бібліотеками" - "Менеджер бібліотек" - UIPEthernet.
Також можна завантажити бібліотеку з GitHub за адресою https://github.com/UIPEthernet/UIPEthernet.

IDE Arduino 1.8.4
Нижче наведено листинг програми для контролера ARDUINO NANO.

/*
КОНТРОЛЕР ОСВІТЛЕННЯ З WEB-ІНТЕРФЕЙСОМ НА ARDUINO UNO + ENC28J60
Розробка - LIC CONTROL  http://lic.com.ua
Схема: http://lic.com.ua/article19.htm
З'єднування Arduino Nano <-> ENC28J60
    D2  <-> INT
    D3  <-> RESET
    D10 <-> CS
    D11 <-> SI (ST)
    D12 <-> SO
    D13 <-> SCK
Вхід для підключення вимикачів: A0, A1, A2, A3, A4, A5
Виходи для підключення реле: 4,5,6,7,8,9   
*/

//Закоментуйте цей рядок, якщо прошивка
//контролера не підтримує Watchdog
#include <avr/wdt.h> 
#include <UIPEthernet.h>

const int LedPin = 13;
//Вхід для підключення вимикачів
const int pins_in_count=6; 
int pins_in[pins_in_count]  = {A0,A1,A2,A3,A4,A5};

//Виходу для підключення реле, що управляють групами світла
const int pins_out_count=6; 
int pins_out[pins_out_count] = {4,5,6,7,8,9}; 

//Масив для зберігання поточного стану групи світла
int pins_state[pins_in_count]; 
//Масив для зберігання попереднього стану групи світла
int pins_old_state[pins_in_count]; 

//Уставте false для відключення виведення налагоджувальної інформації
boolean myDebug = true; 
//MAC-адрес
static uint8_t mac[6] = {0xBE, 0x9F, 0x18, 0x00, 0x00, 0x00};  
static uint16_t port = 80; 
String result="";

//Вкажіть відповідну адресу для контролера у вашій мережі 
IPAddress ip(192, 168, 100, 80); 
EthernetServer server(80);
//Вкажіть IP-адресу WEB-сервера (OrangePi, RaspberryPi)
const char server_ip[] PROGMEM = "http://192.168.100.125"; 
const char page1[] PROGMEM =
"<!DOCTYPE html>\n<html dir='ltr' lang='ru'>\n"
"<head lang='en'>\n<meta charset='UTF-8'>\n"
"<title>КЕРУВАННЯ ОСВІТЛЕННЯМ</title>\n"
"</head><body>\n"
"<div id='heder'></div>\n<div id='blank'></div>\n"
"<div id='main'><h3>Немає з'єднання з WEB сервером за адресою: @!</div>\n"
"<link rel='stylesheet' href='@/static/css/style.css' type='text/css'>\n"   
"<script src='@/static/js/jquery-3.1.1.min.js'></script>\n"
"<script type='text/javascript' src='@/static/js/index.js'> </script>\n"
"</body></html>\n";

const char page2[] PROGMEM =
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Pragma: no-cache\n"
"Connection: close\r\n\r\n";

//Відправляємо в мережу дані, що зберігаються в PROGMEM
void printProgStr(EthernetClient client, const char * str, const char * str1) {
char c,c1;
  if (!str) return;
  while ((c = pgm_read_byte(str++))) {
    if (c=='@') {     
      for (int k = 0; k < strlen_P(server_ip); k++)  {
          c =  pgm_read_byte_near(server_ip + k);
          client.print(c);
      }   
    } else 
    client.print(c); 
  }
}

//Перезапускаємо Ethernet модуль ENC28J60
void resetENC28J60() {
  digitalWrite(3, LOW);   
  delay(200);           
  digitalWrite(3, HIGH);
  delay(50); 
}

//Опитуємо стани входів на предмет
//Виявлення натискання клавіші вимикача
void ReadInput() {
  unsigned long PressTime = 0; 
  int d=0;
  for (int i=0; i<pins_in_count; i++) {
    d = digitalRead(pins_in[i]);
    if (d != pins_old_state[i]) {
      PressTime = millis();       
      while ((d != pins_old_state[i]) and ((millis()-PressTime)<50)) {
        d = digitalRead(pins_in[i]);
        delay(10);
      }
      if (not (millis()-PressTime)<50) {
        if (d<1) {
          pins_state[i] = not pins_state[i];
          if (myDebug) {
            Serial.println("RELE("+String(i)+"), STATE="+String(pins_state[i]));  
          }
        }
      }
    } 
    pins_old_state[i] = d; 
  } 
}

//Встановлюємо виходи, що керують реле
void SetOutput() {
  for (int i=0;i<pins_out_count;i++) {    
     digitalWrite(pins_out[i], pins_state[i]); 
  }   
}

//Формуємо JSON рядок стану виходів (реле)
//для передачі в WEB-браузер
String StringInput() {
  String _return = "[";
  for (int i=0; i<pins_in_count; i++) 
    _return = _return + String(int(pins_state[i]>0))+",";
  _return[_return.length()-1]=']'; 
  return _return;
}

//Початкові установки
void setup() {
  pinMode(LedPin, OUTPUT);  
  digitalWrite(LedPin, HIGH);
  //Ініціалізація входів до яких підключено клавіші вимикачів
  for (int i=0; i<pins_in_count;i++) {
    pinMode(pins_in[i], INPUT_PULLUP); 
    pins_state[i] = 0;
  }
  //Ініціалізація виходів, що керують реле
  for (int i=0;i<pins_out_count;i++) {    
     pinMode(pins_out[i], OUTPUT);  
     digitalWrite(pins_out[i], LOW); 
  }       

  resetENC28J60();  
  Ethernet.begin(mac, ip);
  server.begin();
  
  if (myDebug) {
    Serial.begin(9600);
    Serial.println("START PROGRAMM!");
    Serial.print("START SERVER AT:");
    Serial.println(Ethernet.localIP());
  }  
  
  delay(10);
  //Закоментуйте рядок нижче, якщо прошивка
   //контролера не підтримує Watchdog
  wdt_enable(WDTO_8S);   
}

//Обробка GET запитів з WEB-сторінки на вкл/викл груп світла
void EthernetUpdate() {
  EthernetClient client = server.available();
  if (client) {
    result="";
    while (client.connected()) {
      if (client.available()) {        
        char c = client.read();
        result+=c;
        if (c == '\n') { 
          if (myDebug) Serial.print("Ethernet: "+result); 
          if (result.indexOf("GET / HTTP/1.1")>=0) {
            printProgStr(client, page1, server_ip); 
          } else
          if (result.indexOf("GET /ctrl/")>=0) {
            for (int i=0; i<pins_in_count; i++) 
              if (result.indexOf("GET /ctrl/BT"+String(i))>=0) 
                pins_state[i] = int(not pins_state[i]);
            printProgStr(client, page2, server_ip);      
            client.println(StringInput());                                 
          }  
          client.flush();             
          break;
        }        
      }
    }
    delay(10);
    client.stop();
  }
}

void loop() {
  ReadInput();
  EthernetUpdate();
  SetOutput();
  //Закоментуйте рядок нижче, якщо прошивка
   //контролера не підтримує Watchdog
  wdt_reset();
}
    
    
Для налагодження не обов'язково одразу збирати всю схему. Для початку можна просто з'єднати Arduino Nano та ENC28J60 і через Arduino IDE завантажити програму в контролер Arduino Nano. (якщо вам потрібні докладні інструкції, як завантажити програму, скористайтесь пошуком у Google).

Після завантаження програми в контролер ви зможете протестувати зчитування натискань клавіш і передачу команд із WEB-браузера. Для цього в Arduino IDE відкрийте монітор порту (Меню Tools -> Serial Monitor, Інструменти -> Монітор порту) і подайте по черзі +5В на ніжки A0, A1, A2, A3, A4, A5.
В моніторі порту ви повинні побачити повідомлення, наприклад: RELE(0), STATE=1.

Для перевірки Ethernet модуля, в адресному рядку браузера введіть адресу вашого контролера, наприклад, як у лістингу програми http://192.168.100.80
Якщо ви зібрали схему правильно і модуль ENC28J60 робочий, у браузері ви побачите відповідь: Немає з'єднання з WEB сервером за адресою: http://192.168.100.125!
При цьому в моніторі порту має з'явитися повідомлення GET/HTTP/1.1
Якщо все працює нормально можна переходити до встановлення WEB сервера на мікрокомп'ютері Linux.
ВСТАНОВЛЕННЯ WEB СЕРВЕРУ НА ORANGE PI ZERO
У цьому прикладі використовується мікрокомп'ютер Orange Pi Zero, як один із найдешевших. Можуть бути використані інші мікрокомп'ютери. І тут порядок установки може бути іншим.

Спершу необхідно підготувати SD картку з образом операційної системи Linux. Для Orange Pi Zero це Armbian. Для цього заходимо на офіційний сайт розробника системи та завантажуємо останню стабільну версію. Завантажується файл-архів розміром приблизно 220Мб. Вам необхідно розпакувати його архіватором у будь-яку зручну для вас папку. В результаті ви отримаєте папку з файлами, одним із яких буде файл з розширенням .img. Це і є файл із образом операційної системи, наприклад Armbian_5.35_Orangepipc_Ubuntu_xenial_default_3.4.113.img. Тепер нам необхідно відформатувати картку microSD у файлову систему FAT32 та за допомогою програми Etcher скопіювати на неї файл із операційною системою.

Запустіть програму Etcher, натисніть на кнопку Select image та виберіть раніше завантажений та розархівований файл із образом операційної системи. Виберіть microSD карту, натисніть Flash! і чекайте на закінчення процесу запису. Після завершення процесу з'явиться повідомлення: Flash Complete! Safely ejected and ready for use, що означає, що запис пройшов успішно і можна вставити microSD карту в Orange Pi Zero.
Подайте харчування на мікрокомп'ютер. Перше завантаження зазвичай займає близько 3 хвилин. За допомогою будь-якого аналізатора мережі, наприклад Angry IP Scanner для Windows, або Fing для Android знайдіть адресу Orange Pi Zero у вашій мережі, наприклад http://192.168.100.125.

Замініть у 36 рядку лістингу програми адресу const char server_ip[] PROGMEM = "http://192.168.100.125";
на реальну адресу Orange Pi Zero у вашій мережі та перевантажте програму в контролер ARDUINO NANO.

Тепер потрібно підключитися до мікрокомп'ютера.
Найпростіше це зробити через SSH за допомогою програми PuTTY. Встановіть програму PuTTY, запустіть її, вкажіть адресу мікрокомп'ютера Orange Pi Zero у рядку Host Name: 192.168.100.125. Port:22 і натисніть Open. Відкриється вікно терміналу, де необхідно ввести ім'я користувача root і пароль 1234. Потім відповідно до запитів, які з'являться на екрані змініть пароль для root і додайте нового користувача, наприклад, pi.
Докладніше про те як це робити ви можете знайти в Google.

Про завершення початкової установки засвідчуватиме повідомлення в терміналі про необхідність перевантажити систему. Введіть
sudo reboot.
Система запросить новий пароль, введіть його. Після перезавантаження вам потрібно буде знову підключитись до мікрокомп'ютера через PuTTY. Тепер увійдіть як користувач pi зі своїм новим паролем.

Для роботи мікрокомп'ютера як WEB сервера йому необхідно встановити пакет APACHE, а для можливості Підключення до microSD контролера по мережі, потрібно встановити пакет SAMBA. Також потрібно записати css та javascript файли, що забезпечують роботу WEB сервера.

Для полегшення процесу встановлення цих пакетів та запису файлів WEB сервера скористайтесь нашим спеціальним скриптом, який завантажується командою:
sudo wget http://lic.com.ua:/dat/apache.sh
Увага! Цей скрипт створить нову конфігурацію SAMBA та APACHE. Якщо ви хочете встановити WEB сервер на ваш мікрокомп'ютер, у якого вже встановлені SAMBA та APACHE і ви хочете зберегти їх конфігурацію вам потрібно вручну виконати лише копіювання файлів WEB сервера з http://lic.com.ua:/dat/www в html каталог APACHE.

Зробіть це скрипт виконуваним:
sudo chmod +x apache.sh
І запустіть його на виконання:
sudo./apache.sh
У процесі встановлення будуть з'являтися запити на дозвіл установки пакетів, відповідайте Y та натискайте Enter. Також у вас попросять встановити паролі на доступ до мережних дисків. Введіть їх на власний розсуд. У майбутньому вони будуть потрібні вам для доступу через мережу до microSD мікрокомп'ютера Orange Pi Zero.
Якщо все пройшло успішно, то ввівши в адресному рядку браузера адресу вашого контролера ARDUINO NANO, наприклад, як у лістингу програми http://192.168.100.80, ви побачите WEB сторінку для керування освітленням.
Тепер можна закінчити складання схеми, підключивши вимикачі, релейні модулі та групи світла.

ПАМ'ЯТАЙТЕ ПРО ПРАВИЛА ТЕХНІКИ БЕЗПЕКИ, КОЛИ БУДЕТЕ ПРАЦЮВАТИ З ВИСОКОЮ НАПРУГОЮ.
ВИСОКА НАПРУГА НЕБЕЗПЕЧНА ДЛЯ ЖИТТЯ!