Статьи » Разработки
Добавить статью

Ethernet shield w5100 таймер включения на веб странице

2017-01-10 в 20:08 (последнее изменение 2023-11-09 в 12:27)

Несомненно, цикл статей описывающих возможности Ethernet Shield W5100 в связке с Arduino является очень популярным. Сейчас же многие люди увлекающиеся электроникой повторяют и собирают данные устройства. А наш читатель samuray сделал иначе. Он переработал программу и дизайн странички под свои нужды. Теперь устройство выполняет функции включения реле (может быть на них что угодно) по времени.

Arduino таймер

Разберемся, на чем сейчас построено данное устройство.
Автор добавил часы реального времени DS1302 и подключил по следующей схеме:

VCC - 5V; GND - GND; CLK - 7; DAT -6; RST 5

Реле подключаем по такой схеме:
МОДУЛЬ РЕЛЕ: GND - GND; IN1 - 3; IN2 - 2; VCC - 5V
Стиль. Содержание файла my.css следующее:

Код


.form {
  width: 380px;
  height: 300px;
  border: 5px solid rgb(252, 6, 6);
border-radius: 20px;
  background: rgb(27, 26, 26);
  color: #fff;
}

td{color: #fff}

h2 {
  font-family: Arial;
  font-weight: normal;
  margin: 20px;
  text-align: center
}

.button_disabled {color: #fff; /* цвет текста */
  background: rgb(212, 75, 56);/* фон кнопки */
  border: none; /* не показывать границу */
  border-radius:5px; /* закругление углов */
  cursor: pointer /* ставим другой курсор */
  }

.button_disabled:hover {background: rgb(232, 95, 76);}/* при наведении курсора мышки */
.button_disabled:active {background: rgb(152, 15, 0);}/* при нажатии */

.button_enabled {color: #000; /* цвет текста */
  background: rgb(17,237,105); /* фон кнопки */
  border: none; /* не показывать границу */
  border-radius:5px; /* закругление углов */
  cursor: pointer /* ставим другой курсор */
  }

.button_enabled:hover { background: rgb(94,242,153); } /* при наведении курсора мышки */
.button_enabled:active { background: rgb(84,184,124); } /* при нажатии */

Код странички htm.

Код

<html>

<head>
  <meta http-equiv='content-type' content='text/html; charset=UTF-8'>
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
  <title>УПРАВЛЕНИЕ НАГРУЗКОЙ</title>
  <link type="text/css" rel="StyleSheet" href="/my.css" />

 <script>
function GetFlameState() {
nocache = "&nocache=" + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseText != null) {
var arrayOfStrings = this.responseText.split(";");

document.getElementById("flame_txt").innerHTML = arrayOfStrings[0];
document.getElementById("temp_txt").innerHTML = arrayOfStrings[1];
document.getElementById("humid_txt").innerHTML = arrayOfStrings[2];
for(var i = 1 ; i < 3 ; i++)
if(arrayOfStrings[2+i] == "1")
document.getElementById("led_"+i).setAttribute("class","button_enabled");
else
document.getElementById("led_"+i).setAttribute("class","button_disabled");
}
}
}
}
request.open("GET", "ajax_flame" + nocache, true);
request.send(null);
setTimeout('GetFlameState()', 1000);
}
function onClick(pin){
var request = new XMLHttpRequest();
request.open("GET", "\setpin?pin=" + pin, false);
request.send(null);
}
</script>

        <script>
        function time1()
        {
        var request = new XMLHttpRequest();
        var t3=document.getElementById('t1').value;
        request.open("GET", "\set?t1=" + t3, false);
        request.send(null);
        }
        </script>

        <script>
        function time2()
        {
        var request = new XMLHttpRequest();
        var t4=document.getElementById('t2').value;
        request.open("GET", "\set?t2=" + t4, false);
        request.send(null);
        }
        </script>

        <script>
        function time3()
        {
        var request = new XMLHttpRequest();
        var t6=document.getElementById('t5').value;
        request.open("GET", "\set?t3=" + t6, false);
        request.send(null);
        }
        </script>


</head>

<body onload="GetFlameState()">
  <div class="form">
    <h2>УПРАВЛЕНИЕ НАГРУЗКОЙ</h2>
    <hr noshade size="1px" color="white">
    <table align="center">
      <tr>

        <td valign="center">Время: </td>
        <td><span id="flame_txt"> 0</span> </td>
      </tr>

      <tr>

        <td valign="center">Нагрузка № 2 ВКЛ: </td>
        <td><span id="temp_txt">0</span> </td>
      </tr>

      <tr>

        <td valign="center">Нагрузка № 2 ВЫКЛ: </td>
        <td><span id="humid_txt">0</span> </td>

      </tr>
    </table>
    <br>
    <center>
      <button type="button" id="led_1" class="button_disabled" onClick="onClick(1)">Нагрузка № 1</button>
      <button type="button" id="led_2" class="button_disabled" onClick="onClick(2)">Нагрузка № 2</button>
    </center>


        <form>
            <br>
            <center>Нагрузка № 2, время: <center>
            ВКЛ:     <input id="t1" type="time" value="--:--" size="1">
            <input type="button" value="Enter" onclick="time1();">
            ВЫКЛ:     <input id="t2" type="time" value="--:--" size="1">
            <input type="button" value="Enter" onclick="time2();">
        </form>
        <form>
            <br>
            Установка времени: <input id="t5" type="time" value="--:--" size="1"> <input type="button" value="Enter" onclick="time3();">
        </form>

    </center>


</div>
    </Body>
</html>

А вот и скетч для заливки в Ардуино.

Код

// ***********************************************************************************
// Скетч использует 22320 байт (69%) памяти устройства. Всего доступно 32256 байт.
// Глобальные переменные используют 1477 байт (72%) динамической памяти, оставляя 571
байт для локальных переменных. Максимум: 2048 байт.
// ***********************************************************************************
// ПОДКЛЮЧЕНИЕ      DS1302: VCC - 5V; GND - GND; CLK - 7; DAT -6; RST 5.
//             МОДУЛЬ РЕЛЕ: GND - GND; IN1 - 3; IN2 - 2; VCC - 5V.
// ************************************************************************************
// ВКЛЮЧЕНИЕ НАГРУЗКИ СТРОГО ПО ВЫСТАВЛЕННОМУ ВРЕМЕНИ. ЕСЛИ ЭЛЕКТРОЭНЕРГИЯ ВЫКЛЮЧИТЬСЯ
В ИНТЕРВАЛ ВРЕМЕНИ - ТО ПРИ ПОДАЧИ ПИТАНИЯ НАГРУЗКА
// НЕ ВКЛЮЧИТЬСЯ.
// СДЕЛАТЬ ЗАПИСЬ УСТАНОВЛЕННОГО ИНТЕРВАЛА ВРЕМЕНИ В ЭНЕРГОНЕЗАВИСИМУЮ ПАМЯТЬ.
// СДЕЛАТЬ ТАК ЧТОБЫ В ИНЕТРВАЛ ВРЕМЕНИ НАГРУЗКА БЫЛА ВКЛЮЧЕНА В ЛЮБОМ СЛУЧАЕ.
// ************************************************************************************

String Taymer_Chas_Bkl = "21";    // ЧАС ВКЛЮЧЕНИЯ НАГРУЗКИ № 2
String Taymer_Minute_Bkl = "30";  // МИНУТЫ ВКЛЮЧЕНИЯ НАГРУЗКИ № 2
String Taymer_Chas_Bikl = "07";   // ЧАС ВЫКЛЮЧЕНИЯ НАГРУЗКИ № 2
String Taymer_Minute_Bikl = "00"; // МИНУТЫ ВЫКЛЮЧЕНИЯ НАГРУЗКИ № 2

#include <DS1302.h>
DS1302 rtc(5, 6, 7);// Init the DS1302

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

#define REQ_BUF_SZ 20

File webFile;
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 88, 55);

EthernetServer server(80);
bool pin1;
bool pin2;

void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  SD.begin(4);
  Ethernet.begin(mac, ip);
  server.begin();
  pin1 =  0;
  pin2 =  0;
  rtc.halt(false);
  rtc.writeProtect(false);
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (req_index < (REQ_BUF_SZ - 1)) {
          HTTP_req[req_index] = c; // save HTTP request character
          req_index++;
        }
        if (c == '\n' && currentLineIsBlank) {
          if (StrContains(HTTP_req, "GET / ") || StrContains(HTTP_req, "GET /index.htm")) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connnection: close");
            client.println();
            webFile = SD.open("index.htm");
          } else if (StrContains(HTTP_req, "GET /favicon.ico")) {
            webFile = SD.open("favicon.ico");
            if (webFile) {
              client.println("HTTP/1.1 200 OK");
              client.println();
            }
          } else if (StrContains(HTTP_req, "GET /temp.png")) {
            //            webFile = SD.open("temp.png");
            if (webFile) {
              client.println("HTTP/1.1 200 OK");
              client.println();
            }
          } else if (StrContains(HTTP_req, "GET /humid.png")) {
            //            webFile = SD.open("humid.png");
            if (webFile) {
              client.println("HTTP/1.1 200 OK");
              client.println();
            }
          }
          else if (StrContains(HTTP_req, "GET /flame.png")) {
            webFile = SD.open("flame.png");
            if (webFile) {
              client.println("HTTP/1.1 200 OK");
              client.println();
            }
          } else if (StrContains(HTTP_req, "GET /my.css")) {
            webFile = SD.open("my.css");
            if (webFile) {
              client.println("HTTP/1.1 200 OK");
              client.println();
            }
          } else if (StrContains(HTTP_req, "ajax_flame")) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: keep-alive");
            client.println();
//
            String Time1 = rtc.getTimeStr();
            String Chas1 = Time1.substring(2, 0); // часы
            String Minute1 = Time1.substring(3, 5); // минуты
            String Sec1 = Time1.substring(6, 8); // секунды

            // включить нагрузку 2, ЕСЛИ НАСТАЛО ВРЕМЯ ВКЛЮЧЕНИЯ
            if (Minute1.toInt() == Taymer_Minute_Bkl.toInt() & Chas1.toInt() == Taymer_Chas_Bkl.toInt()) {        
              pin2 = 1;
              digitalWrite(3, pin2);
            }
            // выключить нагрузку 2, ЕСЛИ НАСТАЛО ВРЕМЯ ВЫКЛЮЧЕНИЯ
            if (Taymer_Minute_Bikl.toInt() == Minute1.toInt() & Taymer_Chas_Bikl.toInt() == Chas1.toInt()) {  
              pin2 = 0;
              digitalWrite(3, pin2);
            }
//
            client.print(rtc.getTimeStr());
            client.print(";");
            client.print(Taymer_Chas_Bkl + ":" + Taymer_Minute_Bkl + ":00");
            client.print(";");
            client.print(Taymer_Chas_Bikl + ":" + Taymer_Minute_Bikl + ":00");
            client.print(";");
            client.print((digitalRead(2)) ? "1" : "0");
            client.print(";");
            client.print((digitalRead(3)) ? "1" : "0");
            client.print(";");
          } else if (StrContains(HTTP_req, "setpin?pin=1")) {
            pin1 = !pin1;
            digitalWrite(2, pin1);
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connnection: close");
            client.println();
          } else if (StrContains(HTTP_req, "setpin?pin=2")) {
            pin2 = !pin2;
            digitalWrite(3, pin2);
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connnection: close");
            client.println();
          }
          // прочитать и записать установленное время включения
          if (StrContains(HTTP_req, "\set?t1=")) {
            String Temp = HTTP_req;
            Taymer_Chas_Bkl = Temp.substring(12, 14);    // час включения
            Taymer_Minute_Bkl = Temp.substring(15, 17);  // минуты выключения
          }
          // прочитать и записать установленное время выключения
          if (StrContains(HTTP_req, "\set?t2=")) {
            String Temp = HTTP_req;
            Taymer_Chas_Bikl = Temp.substring(12, 14);  // час выключения
            Taymer_Minute_Bikl = Temp.substring(15, 17); // минуты выключения
          }
          // прочитать и записать время
          if (StrContains(HTTP_req, "\set?t3=")) {
            String Temp = HTTP_req;
            String Chas1 = Temp.substring(12, 14);            // час
            int H = Chas1.toInt();
            String Minute1 = Temp.substring(15, 17);          // минуты
            int M = Minute1.toInt();
            rtc.setTime(H, M, 0);            // установка времени (ЧЧ,ММ,СС) (24hr format)
          }
          //
          if (webFile) {
            while (webFile.available()) {
              client.write(webFile.read()); // send web page to client
            }
            webFile.close();
          }
          req_index = 0;
          StrClear(HTTP_req, REQ_BUF_SZ);
          break;
        }
        if (c == '\n') {
          //начинаем новую линию
          currentLineIsBlank = true;
        } else if (c != '\r') {
          //получили символ на текущей строке
          currentLineIsBlank = false;
        }
      }
    }
    // дать время веб-браузер, чтобы получить данные
    delay(1);
    // закрыть соединение:
    client.stop();
  }
// прорверка времени вкл/выкл нагрузки и вкл/выкл нагрузкку 2
            String Time1 = rtc.getTimeStr();
            String Chas1 = Time1.substring(2, 0); // часы
            String Minute1 = Time1.substring(3, 5); // минуты
            String Sec1 = Time1.substring(6, 8); // секунды
            // включить нагрузку 2, ЕСЛИ НАСТАЛО ВРЕМЯ ВКЛЮЧЕНИЯ
            if (Minute1.toInt() == Taymer_Minute_Bkl.toInt() & Chas1.toInt() == Taymer_Chas_Bkl.toInt()) {        
              pin2 = 1;
              digitalWrite(3, pin2);
            }
            // выключить нагрузку 2, ЕСЛИ НАСТАЛО ВРЕМЯ ВЫКЛЮЧЕНИЯ
            if (Taymer_Minute_Bikl.toInt() == Minute1.toInt() & Taymer_Chas_Bikl.toInt() == Chas1.toInt()) {  
              pin2 = 0;
              digitalWrite(3, pin2);
            }
//
}

void StrClear(char *str, char length)
{
  for (int i = 0; i < length; i++) {
    str[i] = 0;
  }
}

char StrContains(char *str, char *sfind)
{
  char found = 0;
  char index = 0;
  char len;
  len = strlen(str);
  if (strlen(sfind) > len) {
    return 0;
  }
  while (index < len) {
    if (str[index] == sfind[found]) {
      found++;
      if (strlen(sfind) == found) {
        return 1;
      }
    }
    else {
      found = 0;
    }
    index++;
  }
  return 0;
}

Автор так-же сделал видео работы устройства.

Здесь лежит архив с файлами для создания данного проекта включающая скетч, index.htm, my.css и картинка для браузера favicon. Скачать.

Нам очень нравится заниматься написанием материалов которые способны помогать как Вам так и другим людям. Если у вас есть чем поделиться, с удовольствием расскажем о ваших разработках.

Список электронных компонентов.

Наименование Тип Количество Магазин
Arduino UNO R3 1 Найти
Ethernet Shield W5100 1 Найти
Модуль часов реального времени DS1302 1 Найти
Модуль реле 2 канала 1 Найти
Провода Dupont Папа-Мама Провода Dupont Папа-Мама Комплект Найти
Cashback на Aliexpress

Не пропустите обновления! Подписывайтесь на нашу группу Вконтакте.
Так же у нас есть Telegram канал.
Вам понравился наш материал? Поделитесь с коллегами!

Просмотров: 9714. Оценка статьи: 5.0 из 5. Уже оценило 7 читателей

Об авторе - Администратор

More by Администратор

Всего комментариев: 8
mast90
mast90 2022-09-27 16:14
Сюда бы добавить бы пароль на вход в web интерфейс, было бы круто !!! И через интернет можно было бы проброс портов сделать и смело управлять!

типо такого:

Код
String readString;
readString.lastIndexOf(F("Authorization: Basic QWxla3NhaGVrOlp6MT1rNFU2")) > -1)

Ответ Автора: Делайте, и разместим ваш вариант проекта)
mast90
mast90 2022-07-07 17:22
Можно ссылку на библиотеку  DS1302.h, с моей что то не хочет компилится

Ответ Автора: Осталась такая https://tehnopage.ru/librares/microds3231
dim5555
dim5555 2019-02-09 08:40
Возможно ли в скечте добавить расширить число каналов управления до 24? (mega2560). Сейчас пользуюсь таким решением http://startingelectronics.org/tutorials/arduino/arduino-MEGA-24-output-web-server/. Ваш скетч очень хорош наличием датчиков , но не хватает каналов управления.

Samuray 2018-04-10 10:08
ДА. Переделать на работу от температуры можно

Алексей 2018-03-23 14:29
Здравствуйте, интересует вот такая тема, можно ли вместо времени добавить функцию регулирования и включения и отключения нагрузки по температуре?

samuray
samuray 2017-12-11 20:52
спасибо за подсказку модернизации

mainprolab
mainprolab 2017-12-09 03:24
Доброго Вам времени суток Константин.
Интересная у вас тема проверял, все работает. Чтокасается серверной части кода, то я бы ее модернизировал, воспользовавшись вот
этой библиотекой https://github.com/aterentiev/WebServer
Автор данной библиотеки, применил буфер между SDкартой и W5100. Страница (html) уходит вомного раз быстрее (особенно картинки), практически мгновенно… Собираюсь буфер
увеличить до 512 байт. Это еще ускорит загрузку страницы.

samuray
samuray 2017-01-13 10:06
В ближайшее время выложу скетч оптимизированный по памяти.

В дальнейшем скетч со следующими доработками: 
  • записью в энергонезависимую память значений включения/выключения нагрузки;
  • корректная отработка интервала времени вкл/выкл нагрузки;
  • корректировка  часов по Udp - с сервера времени;

ВНИМАНИЕ:
        Как показала сборка в едином корпусе и прогон плату реле и плату часов лучше рядом не устанавливать.
        
Плата часов и плата реле были установлены параллельно рядом, блок питания использовался на 9В 1А. При таком расположении плата часов останавливалась при включении/выключении реле. После того как плата часов была установлена на расстояние величины платы ARDUINO UNO, подвисание платы часов прекратилось.
 
Уважаемые читатели.        
Скетч опубликованный в статье рабочий, но далек от идеального программирования. Как я писал выше скетч будет дорабатываться и оптимизироваться. Если у Вас появится предложения или замечание прошу их высказывать. 
        Также в процессе прогона появились новые идеи по  модернизации, с которыми я Вас ознакомлю после сборки модернизированной конструкции. 

С уважением. И до встречи.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]