#1 Re: Апаратні питання » Отучаем кота пакостить. » 2016-12-13 10:11:43

Спасибо, что отозвались.
Идея с ультразвуковым датчиком - это вариант.
В моём случае будут правда срабатывания на людей, потому что стена находится в прихожей у входной двери, но по крайней мере хоть какой-то вариант. Да и включать его можно перед выходом из дома, потому что этот хитрец царапает когда хозяев нет дома.

#2 Апаратні питання » Отучаем кота пакостить. » 2016-12-12 20:00:31

z0ri
відповідей: 7

Добрый день всем посетителям, постояльцам форума и гостям.
Есть кот(животное такое), который дерёт обои на определённой стене.
Появилась идея сделать некий ошейник, который будет либо звуком его отпугивать, либо ещё каким-то стособом, но идея в том, что когда кот подходит к этой стене, его что-то пугало или делало немного больно (маленький разряд тока smile ну или ещё не придумал).
Как реализовать момент определения, что кот подошёл к месту, где он обычно дерёт стену когтями. Причём в этом месте ходят хозяева квартиры, поэтому срабатываний на них быть не должно.
Дряпает он во время отсутствия хозяев дома, поэтому наказывать его по приходу домой бесполезно, ибо не поймёт за что.
Вот не знаю, какие модули использовать, чтобы знать, что кот подошёл к стене?
То есть загвоздка в самом зарождении проекта.
Может есть у кого-то идеи/мысли по этому поводу?
Спасибо.

#3 Проекти » Несчастное жалюзи » 2016-05-26 16:19:06

z0ri
відповідей: 3

Здравствуйте, уважаемые форумчане.
Хочется управлять открытием и закрытием жалюзи, но до сих пор не могу даже логически придумать как реализовать хотелки.
Есть Arduino UNO/MEGA. На неё кладём слой шилда на базе w5100. Далее подключил драйвер шагового двигателя tb6560, ну и сам двигатель nema17(4 провода у него, может вращаться по часовой и против часовой стрелки). Перечисленные компоненты уже приобретены.

Хотелки:
1) GET запросом открывать или закрывать жалюзи (основная хотелка)
2) Физической кнопкой открывать или закрывать жалюзи
3) Открывать или закрывать жалюзи с помощью ИК передатчика и приёмника

Нюансы:
0) управление жалюзи через ИК (это скорее всего финальная часть)
1) надо иметь возможность через web открывать/закрывать НЕ полностью жалюзи (например на 1/10 часть, на 6/10 части)
2) закрывать полностью одним GET запросов, открывать другим. (Уже реализовано. Для защиты от повторного раскручивания жалюзи на случай повторного случайного нажатия на кнопку я на флеш карте создаю файлики, которыми фиксирую текущее состояние жалюзи на случай перезагрузки Ардуино)
3) иметь возможность открывать/закрывать вручную
4) хочется физическую кнопку у окна, которая будет откр и закр жалюзи
5) Ситуация: Закрыл я жалюзи полностью GET-запросом(в принципе можно считать уже реализовано), далее я открыл жалюзи вручную. Получается, что у меня на флэш карте будет зафиксировано предыдущее положение жалюзи, а не текущее.
6) Ситуация такая же, но уже не просто я вручную открыл, а при открытии жалюзи квартира была обесточена. То есть по большому счёту, надо знать всегда в каком положении(на сколько открыты или закрыты) жалюзи, как при ежедневной работе так и сразу же после перезагрузки Ардуино.

Была идея считать обороты двигателя, но в случае с ситуацией №6 это не поможет.
Идея считать расстояние от окна до жалюзи, датчик расстояния расположить на подоконнике и так узнавать что они полностью закрыты. Тогда остаются непонятными проблемы с неполным открытием/закрытием.
Зависеть от освещённости вокруг тоже не хочется, это к слову о фоторезисторе.

Может у кого-то в голове выстроилась логика программы, а может какие-то модули ещё докупить надо?
Хочется предвидеть максимум ситуаций, которые с большой долей вероятности могут произойти.
Заранее благодарен.

#4 Програмування Arduino » ПДУ даёт разные сигналы хаотично » 2016-04-26 18:48:41

z0ri
відповідей: 2

Здравствуйте.
Столкнулся с такой непонятно для меня особенность, не знаю как добиться стабильности.
Использую шилд с w5100 на Arduino. подключен ИК приёмник 38 Hz. По нажатию на кнопку ПДУ должен отправляться GET запрос на другую Arduino с шилд w5100. Всё вроде бы хорошо и отправляется, но вот нажатия кнопок на ПДУ ИК приёмник распознаёт не всегда точно. Жму одну и ту же кнопку на ПДУ и в мониторе порта вижу:

20DF8877
20DF8877
20DF
20DF887
20DF8877
20DF8877
20DF8877
20DF8877
20DF8877
20DF8877
2ADE08A3
20DF8877
2ADE08A3
2ADE08A3
20DF
20DF8877
20DF8877

То есть вроде бы в основном выпадает 20DF8877, но часто идёт другой сигнал.
Пульты пробовал разные (4-е штуки). От ТВ LG, Samsung, Toshiba и от ресивера GI.
Пробовал использовать не готовый китайский модуль с ИК приёмником, а сам паял схемку.
Использую библиотеку IRremote.
Наверно есть смысл показать вывод в порт после нажатия на кнопку, например, 2 на ПДУ от ТВ LG:

Encoding  : NEC
Code      : 20DF48B7 (32 bits)
Timing[67]: 
     +8900, -4450     + 550, - 550     + 550, - 550     + 600, -1650
     + 550, - 550     + 550, - 550     + 550, - 550     + 550, - 550
     + 550, - 550     + 550, -1650     + 600, -1650     + 550, - 550
     + 550, -1650     + 550, -1700     + 550, -1700     + 500, -1700
     + 550, -1700     + 550, - 550     + 550, -1650     + 550, - 550
     + 550, - 550     + 550, -1700     + 550, - 550     + 550, - 550
     + 550, - 550     + 550, -1650     + 550, - 550     + 550, -1700
     + 550, -1650     + 550, - 600     + 500, -1700     + 500, -1750
     + 450, -1750     + 500
unsigned int  rawData[67] = {8900,4450, 550,550, 550,550, 600,1650, 550,550, 550,550, 550,550, 550,550, 550,550, 550,1650, 600,1650, 550,550, 550,1650, 550,1700, 550,1700, 500,1700, 550,1700, 550,550, 550,1650, 550,550, 550,550, 550,1700, 550,550, 550,550, 550,550, 550,1650, 550,550, 550,1700, 550,1650, 550,600, 500,1700, 500,1750, 450,1750, 500};  // NEC 20DF48B7
unsigned int  data = 0x20DF48B7;

На просторах интернета прочёл, что у NEC тоже 38 Hz.
Подскажите, люди добрые, как добиться стабильность в этом мире? В мире Arduino + IR.

#5 Re: Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-03-15 17:09:11

Selest пише:

Я так понимаю что записи состояния в память нет ( на случай пропадания питания ) ?

Нет, состояние в память не записывается, данный функционал для реализации моей идеи не нужен, а скорее даже вреден.

#6 Re: Апаратні питання » W5100 греется » 2016-02-27 11:06:12

Может показалось, но при питании от БП на 5V (не от usb) греться чип w5100 стал немного меньше, по крайней мере палец руки держать на нём могу.
Решил одеть радиатор на наго, благо был подходящего размера, заметил что некоторые ножки спаяны вместе.
Так и должно быть?
(картинки кликабельны)
mini_01.jpgmini_02.jpg

#7 Апаратні питання » W5100 греется » 2016-02-26 21:06:21

z0ri
відповідей: 2

Доброго времени суток всем жильцам этого прекрасного форума.

Вопрос в общем-то в заголовке темы. Чип w5100 на шилде для Arduino сильно греется, прям с трудом на нём палец можно удержать.
Использую Arduino UNO, питание идёт от USB ноутбука.

Как такой сильный длительный нагрев повлияет на работу шилда (пока он работает замечательно и уже на протяжении нескольких недель) ?
Как с этим явлением борятся? Не уж то Радиатор ?
И может есть отзывы людей пробовавших поиграться с w5500 или 5200 ? Они такие же горячие ?
Спасибо.

#8 Re: Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-02-16 17:17:21

Итого получился такой код, думаю на нём и остановлюсь (по крайней мере это работает, выкладываю, на случай, если кому понадобится):

#include <Ethernet.h>


// задаем константы
const int ledPin =  6;     // номер выхода светодиода
const int buttonPin = 2;    // номер входа, подключенный к кнопке
const int Relay1 = 5;       // к 5-ому пину подключено IN1 реле
 
// переменные
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки
boolean ledOn = false;         // Текущее состояние светодиода (включен/выключен)
boolean Relay1On = true;        // Текущее состояние реле

String readString = String(30);


// объявляем переменную MY_IP со значением 10.36.1.52
#define MY_IP "10.36.1.52"
// указываем настройки сетевого интерфейса и порт веб-сервера
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 36, 1, 52);
EthernetServer server(80);


void setup() {
  delay(500);
  
/*
 * без строки "digitalWrite(Relay1, HIGH);" перед "pinMode" при включении
 * ардуины будет происходить кратковременное переключение реле,
 * а значит кратковременно подастся питание, что нам категорически
 * не надо!
 */
  digitalWrite(Relay1, HIGH);
  
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);
  // инициализируем пин, подключенный к реле, как выход
  pinMode(Relay1, OUTPUT);


// стартуем сетевой интерфейс
Ethernet.begin(mac, ip);
server.begin();


Serial.begin(9600);
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last){
  boolean current = digitalRead(buttonPin);    // Считать состояние кнопки
  if (last != current)                         // Если изменилось ...
  {
  delay(5);                                    // ждём 5 мс
  current = digitalRead(buttonPin);            // Считываем состояние кнопки
  return current;                              // Возвращаем состояние кнопки
  }
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
//    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
//        Serial.write(c);

if (readString.length() < 30) {
readString.concat( c); }
Serial.print( c);
        
//if (c == '\n' && currentLineIsBlank) {
if (c == '\n') {
//Проверяем включили ли реле и светодиод?
//Level=1 - включен
//Level=0 - выключен
if(readString.indexOf("Level=1") >=0) {
//Включаем реле
digitalWrite(Relay1, LOW);
Relay1On = false;
//Включаем светодиод
digitalWrite(ledPin, HIGH);
ledOn = true;

}else if(readString.indexOf("Level=0") >=0){
//Выключаем реле
digitalWrite(Relay1, HIGH);
Relay1On = true;
//Выключаем светодиод
digitalWrite(ledPin, LOW);
ledOn = false;
}
 

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");  // the connection will be closed after completion of the response
//client.println("Refresh: 5");  // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' /> ");
client.println("<head><meta http-equiv=\"refresh\" content=\"5;URL=http://"MY_IP"/\"></head>");
client.println(F("<body>"));
client.println(F("<center><head><title>Relay Control</title></head>"));

if (Relay1On){
client.println("<form method=get name=LED><input type=radio name=Level value=1 CHECKED>Включить");
client.println("<input type=radio name=Level value=0>Выключить");
client.println("<input type=submit value=Применить></form>");
client.println("<font size=’5′>Состояние реле: ");
client.println("<font size=’5′>Выкл.");
client.println("<br></br>");
}else{
client.println("<form method=get name=LED><input type=radio name=Level value=1>Включить");
client.println("<input type=radio name=Level value=0 CHECKED>Выключить");
client.println("<input type=submit value=Применить></form>");
client.println("<font size=’5′>Состояние реле: ");
client.println("<font size=’5′>Вкл");
client.println("<br></br>");
}

//client.print(F("<input type=button value='Main Light ON' onmousedown=location.href='/?LED_on'>"));
//client.println(F("<input type=button value='Main Light OFF' onmousedown=location.href='/?LED_off'><br/><br/>"));
client.println("<a href=\"/?Level=1\"\">Turn On Light</a><br />");
client.println("<a href=\"/?Level=0\"\">Turn Off Light</a><br />");
client.println(F("</center></body>"));
client.println("</html>");
readString="";
//останавливаем web-client
client.stop();
          }
        }
      }
    }

// часть кода для кнопки, реле и светодиода
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условия для светодиода на пине 6)
{
  ledOn = !ledOn;
}
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условие для реле)
{
  Relay1On = !Relay1On;
}
lastButton = currentButton;
digitalWrite(ledPin, ledOn);                         // Изменить статус состояния светодиода
digitalWrite(Relay1, Relay1On);                         // Изменить статус состояния реле

}

Переключать реле можно как тактовой кнопкой, так и через веб-интерфейс. Светодиод на пине 6 - индикация состояния реле.
Спасибо всем отозвавшимся и неравнодушным.
P.S.: Эксперименты продолжаются ...

#9 Re: Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-02-14 18:41:05

Дописался до следующего кода:

#include <Ethernet.h>

// задаем константы
const int ledPin =  6;     // номер выхода светодиода
const int buttonPin = 2;    // номер входа, подключенный к кнопке
const int Relay1 = 5;       // к 5-ому пину подключено IN1 реле
 
// переменные
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки
boolean ledOn = false;         // Текущее состояние светодиода (включен/выключен)
boolean Relay1On = true;        // Текущее состояние реле

String readString = String(30);


// объявляем переменную MY_IP со значением 10.36.1.52
#define MY_IP "10.36.1.52"
// указываем настройки сетевого интерфейса и порт веб-сервера
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 36, 1, 52);
EthernetServer server(80);


void setup() {
  delay(500);
  
/*
 * без строки "digitalWrite(Relay1, HIGH);" перед "pinMode" при включении
 * ардуины будет происходить кратковременное переключение реле,
 * а значит кратковременно подастся питание, что нам категорически
 * не надо!
 */
  digitalWrite(Relay1, HIGH);
  
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);
  // инициализируем пин, подключенный к реле, как выход
  pinMode(Relay1, OUTPUT);


// стартуем сетевой интерфейс
Ethernet.begin(mac, ip);
server.begin();


Serial.begin(9600);
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last){
  boolean current = digitalRead(buttonPin);    // Считать состояние кнопки
  if (last != current)                         // Если изменилось ...
  {
  delay(5);                                    // ждём 5 мс
  current = digitalRead(buttonPin);            // Считываем состояние кнопки
  return current;                              // Возвращаем состояние кнопки
  }
}




void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
//    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
//        Serial.write(c);

if (readString.length() < 30) {
readString.concat( c); }
Serial.print( c);
        
//        if (c == '\n' && currentLineIsBlank) {
if (c == '\n') {

        //Level=1 - включить реле
        //Level=0 - выключить реле
if(readString.indexOf("Level=1") >=0) {
//Включаем светодиод
digitalWrite(Relay1, LOW);
Relay1On = false;

ledOn = !ledOn;

}else if(readString.indexOf("Level=0") >=0){
//Выключаем светодиод
digitalWrite(Relay1, HIGH);
Relay1On = true;

ledOn = !ledOn;
}

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' /> ");
client.println("<head><meta http-equiv=\"refresh\" content=\"5;URL=http://"MY_IP"/\"></head>");
client.println(F("<body>"));
client.println(F("<center><head><title>Relay Control</title></head>"));

if (Relay1On){

digitalWrite(ledPin, ledOn);

client.println("<form method=get name=LED><input type=radio name=Level value=1 CHECKED>Включить");
client.println("<input type=radio name=Level value=0>Выключить");
client.println("<input type=submit value=Применить></form>");
client.println("<font size=’5′>Состояние реле: ");
client.println("<font size=’5′>Выкл.");
client.println("<br></br>");
}else{

client.println("<form method=get name=LED><input type=radio name=Level value=1>Включить");
client.println("<input type=radio name=Level value=0 CHECKED>Выключить");
client.println("<input type=submit value=Применить></form>");
client.println("<font size=’5′>Состояние реле: ");
client.println("<font size=’5′>Вкл");
client.println("<br></br>");
}

client.println("<a href=\"/?Level=1\"\">Turn On Light</a><br />");
client.println("<a href=\"/?Level=0\"\">Turn Off Light</a><br />");
client.println(F("</center></body>"));
client.println("</html>");
readString="";
//останавливаем web-client
client.stop();
          }
        }
      }
    }


// часть кода для кнопки, реле и светодиода
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условия для светодиода на пине 6)
{
  ledOn = !ledOn;
}
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условие для реле)
{
  Relay1On = !Relay1On;
}
lastButton = currentButton;
digitalWrite(ledPin, ledOn);                         // Изменить статус состояния светодиода
digitalWrite(Relay1, Relay1On);                         // Изменить статус состояния реле

}

Он даже работает (удивительно "не причёсанный" код).
Однако есть одна неприятность.
Нажимая в браузере включить, реле переключается и светодиод на пин№ 6 включается Нажимаем в браузере выключить - реле разъединяет контакты и светодиод гаснет. Всё хорошо казалось бы. Нажимаем включить, опять переключается реле, включается светодиод, НО нажав включить повторно, реле остаётся в том же состоянии (что логично и так и должно быть) , а светодиод гаснет. То есть точность индикации состояния реле теряется. А это печально.

#10 Re: Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-02-13 01:19:47

Йожэг пише:

В предыдущем скетче для другого сетевого модуля определение того, какая ссылка была нажата, сделано так:

    if (strstr((char *)Ethernet::buffer + pos, "GET /?ON") != 0) {
      setRelayState(true);
    } else if(strstr((char *)Ethernet::buffer + pos, "GET /?OFF") != 0) {

Т.е. просто ищем в буфере приёма запрос с "/?ON" или "/?OFF". А в этом новом скетче где определение ссылки адреса с командой внутри?

Вот это одни из тех строчек, что ввели в ступор. То есть ссылки вывести удалось,

client.println("<a href=\"/?LED_on\"\">Relay On</a><br />");
client.println("<a href=\"/?LED_off\"\">Relay Off</a><br />");

но этого мало. Строки про которую Вы говорите, в текущем скетче, я так понял, нету.
На просторах интернета я находил такой вариант, вроде бы даже рабочий. До секции setup:

String readString;

В секцию loop:

if (readString.length() < 100)
{
readString = readString + c;
}

и

if(readString.indexOf("/?LED_on") > 0) digitalWrite(Relay1, LOW);
if(readString.indexOf("/?LED_off") > 0) digitalWrite(Relay1, HIGH);
readString = "";

Но пока собрать матрёшку не получается.

#11 Re: Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-02-12 23:43:01

Продолжается бой... Буду дописывать прогресс сюда, а вось кому пригодится.
Дописался до следующего кода:

#include <Ethernet.h>


// задаем константы
const int ledPin =  6;     // номер выхода светодиода
const int buttonPin = 2;    // номер входа, подключенный к кнопке
const int Relay1 = 5;       // к 5-ому пину подключено реле
 
// переменные
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки
boolean ledOn = false;
boolean Relay1On = true;


// объявляем переменную MY_IP со значением 10.36.1.52
#define MY_IP "10.36.1.52"
// указываем настройки сетевого интерфейса и порт веб-сервера
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 36, 1, 52);
EthernetServer server(80);


void setup() {
  delay(500);
  
/*
 * без строки "digitalWrite(Relay1, HIGH);" перед "pinMode" при включении
 * ардуины будет происходить кратковременное переключение реле,
 * а значит кратковременно подастся питание, что нам категорически
 * не надо!
 */
  digitalWrite(Relay1, HIGH);
  
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);
  // инициализируем пин, подключенный к реле, как выход
  pinMode(Relay1, OUTPUT);


// стартуем сетевой интерфейс
Ethernet.begin(mac, ip);
server.begin();

}

/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last){
  boolean current = digitalRead(buttonPin);    // Считать состояние кнопки
  if (last != current)                         // Если изменилось ...
  {
  delay(5);                                    // ждём 5 мс
  current = digitalRead(buttonPin);            // Считываем состояние кнопки
  return current;                              // Возвращаем состояние кнопки
  }
}


void loop() {
  EthernetClient client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n' && currentLineIsBlank) {


client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");  // the connection will be closed after completion of the response
client.println("Refresh: 5");  // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println(F("<body>"));
client.println(F("<center><head><title>Relay Control</title></head>"));
//client.print(F("<input type=button value='Relay ON' onmousedown=location.href='/?LED_on'>"));
//client.println(F("<input type=button value='Relay OFF' onmousedown=location.href='/?LED_off'><br/><br/>"));
client.println("<a href=\"/?LED_on\"\">Relay On</a><br />");
client.println("<a href=\"/?LED_off\"\">Relay Off</a><br />");
client.println(F("</center></body>"));
client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Ethernet.maintain();
  }


// часть кода для кнопки, реле и светодиода
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условия для светодиода на пине 6)
{
  ledOn = !ledOn;
}
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие (условие для реле)
{
  Relay1On = !Relay1On;
}
lastButton = currentButton;
digitalWrite(ledPin, ledOn);                         // Изменить статус состояния светодиода
digitalWrite(Relay1, Relay1On);                         // Изменить статус состояния реле
}

Из уже рабочего функционала:
Работает тактовая кнопка на контакте №2, то есть кнопка может переключать реле(контакт №5) и попутно включает/выключает светодиод на контакте №2
На веб интерфейс выведено 2-е ссылки для управления реле, но они не работают. Статус (состояние реле) тоже не известно, а очень хочется.

В одном из своих топиков я писал о нестабильной работе сетевого модуля mini enc28j60. Могу с уверенностью сказать, что у меня модуль на w5100 работает очень хорошо, разрывов нет вообще, пинг хороший.

По поводу того, что кнопка работала не стабильно из поста выше. Заметил странную закономерность. Если сетевой шилд одеть сверху - то кнопка не стабильна, из 10 раз может 3-4 раза не сработать. Если шилд соединяю проводами и задействую только те контакты, которые нужны для сетевого интерфейса, а кнопку подключаю непосредственно к ардуино, то кнопка работает прекрасно. Кнопка подключена через резистор.

Помогите с кодом, а то как доходит до определения статуса и управления через веб, так всё....приплыли.
Заранее благодарен

#12 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-02-09 23:54:39

Продолжил тему управления нагрузкой через веб-интерфейс здесь, но уже используя Ethernet Shield W5100.

#13 Програмування Arduino » Управление реле через arduino, Ethernet Shield W5100 и кнопки » 2016-02-09 23:51:48

z0ri
відповідей: 11

Подобную тему уже поднимал на этом форуме и хорошие люди подсказали решение. Но так как модуль локальной сети уже другой, то решил открыть новую тему. Модуль другой, библиотека другая, тех характеристики и возможности другие, по логике и тема другая.
Схема абсолютно идентична описанной в теме выше, только реле решил повесить на пин 5, так как пишут, что 4-ый пин Arduino UNO нужен для работы флэш накопителя. Реле тоже сменил на твердотельное OMRON G3MB-202P, но на код это повлиять не должно.
Попытался адаптировать код из поста под Ethernet Shield W5100, попытался объединить это со стандартным примером WebServer, но у меня как всегда...каша.
Получилось вот что:

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

// для кнопки и светодиода и реле
#define BUTTON_PIN 2
#define LED_PIN 6
#define RELAY_PIN 5
#define MY_IP "10.36.1.52"
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
byte gateway[] = {10, 36, 1, 7};
byte subnet[] = {255,255,255,0};
IPAddress ip(10, 36, 1, 52);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// статус(состояние) для реле:
boolean relayStatus;
char* relayLabel;

// для кнопки надо:
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  // инициируем подключение к локальной сети
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());


  // настройка входов/выходов для реле, светодиода и кнопки
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);

  // включение реле
  setRelayState(true);


}

/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last) {
  boolean current = digitalRead(BUTTON_PIN);   // Считать состояние кнопки
  if (last != current) {                       // Если изменилось ...
    delay(50);                                  // ждём 5 мс
    current = digitalRead(BUTTON_PIN);         // Считываем состояние кнопки
    return current;                            // Возвращаем состояние кнопки
  }
}

void setRelayState(boolean relayOn) {
  digitalWrite(RELAY_PIN, relayOn);
  digitalWrite(LED_PIN, !relayOn);
  relayStatus = relayOn;
  if (relayOn) {
    relayLabel = "ON";
  } else {
    relayLabel = "OFF";
  }
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {

          
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html\r\nPragma: no-cache\r\n\r\n");
//          client.println("Content-Type: text/html; charset=UTF-8");
//          client.println("Connection: close");  // the connection will be closed after completion of the response
//          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
client.println("<head><meta http-equiv=\"refresh\" content=\"5;URL=http://"MY_IP"/\"></head>\n");
client.println("<body>\n<center>Relay is $S</center>\n");
client.println("<a href=\"http://"MY_IP"/?ON\" rel=\"nofollow\">Turn On</a><br></br>\n");
client.println("<a href=\"http://"MY_IP"/?OFF\" rel=\"nofollow\">Turn Off</a><br></br>\n");
client.println("<a href=\"http://"MY_IP"/\" rel=\"nofollow\">Check Status</a><br></br>\n");
client.println("</body>\n</html>\n"),relayLabel;


          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
    Ethernet.maintain();
  }

  // реакция на нажатие кнопки для реле
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH) { // если нажатие
    setRelayState(!relayStatus);
  }
  lastButton = currentButton;
}

Кнопка работает, светодиод включается с кнопки, реле тоже переключается, но вот с веб-интерфейсом беда. Получилось только вывести ссылки на странице, но они не работают. То есть, переход по ссылке происходит, но реле не переключается и светодиод не включается. Да и уверен, что начудил я с кОдом.
А задача всё та же:
Надо, чтобы управлять реле можно было с кнопки или с веб интерфейса, при этом надо знать о текущем его состоянии, не зависимо от того переключил я реле с физической кнопки или через веб-интерфейс Надо чтобы информацию о состоянии реле я знал через веб интерфейс Ethernet Shield W5100 на arduino.

И ещё заметил следующую странность. Кнопка вроде бы работает, но не всегда. Иногда, раз этак 1 из 10 не срабатывает, причём повторно нажав её, она нормально отрабатывается. Подключена она одним концом в 5V W5100, а вторым через резистор в gnd и в пин 2. При этом до установки шилда на Ардуину я таких проблем не испытывал.

Буду благодарен за помощь.

#14 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-16 20:45:17

Продолжаю следить за этой темой форума.
Как только прийдет ко мне модуль w5100, я его опробую, то напишу про стабильность.
Пробовали с товарищами поиграться с электричеством и получилось, что подав на  arduino uno 7v ситуация со стабильностью не изменилась, а подав уже 9v, стал греться кусок платы между входом питания и usb, но сутки проработало (может быть это совпадение). Подавали питание именно в гнездо для питания.
Вот думаю для подобных исследований отдельную тему на форуме создать или не надо, а то вроде бы не по теме уже.

P.s. Йожэг, ещё раз спасибо.

#15 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-12 20:39:15

Йожэг пише:

Упс, забыл сохранить состояние в глобальной переменной, т.е. надо в конце тела функции setRelayState(..) дописать "  relayStatus = relayOn;"

Случилось чудо. Магия. Оно работает именно так как надо (подправил совсе чуть-чуть скетч под себя).
Загружается Ардуина, реле не переключается, светодиод не горит. Жму кнопку, диод загорается, реле переключается. Статус можно посмотреть на веб интерфейсе. Переключать релюшку тоже можно через веб-интерфейс, с сохранением возможности посмотреть текущее состояние реле.

Йожэг, огромнейшее спасибо, сам бы я не решил задачу.

Из минусов: как то не стабильно работает сетевой модуль mini enc28j60, как мне кажется. Бывает перезальёшь скетч, а сеть не поднимается и хост Ардуины не пингуется, тогда как реле и кнопка работают, потом через какое то время сам оживает. Бывает, что оживает после нескольких перезагрузок. Бывает, что сутки нормально работает. А может виноваты руки. В общем заказал модуль ethernet shield w5100 в надежде на большую стабильность, а то как-то не серьезно.

Ещё раз огромное спасибо!!!

#16 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-11 20:12:55

Йожэг пише:

Та это не форум, это я упростил:

#include <EtherCard.h>

// разъем CS из модуля сети подключаем к 10-му пину на ардуино
#define CS 10
#define REQUEST_RATE 5000

// входы и выходы
#define BUTTON_PIN 2
#define RELAY_PIN 4
#define LED_PIN 6

// настройки сетевого интерфейса
#define MY_IP "192.168.0.55"
static byte myip[] = { 192,168,0,55 };
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte gwip[] = { 192,168,0,1 };
static byte dnsip[] = { 8,8,8,8 };
static byte hisport[] = { 80 };

byte Ethernet::buffer[700];

boolean relayStatus;
char* relayLabel;

// для кнопки
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки


void setup () {
  // инициируем подключение к локальной сети
  delay(300); 
  if (ether.begin(sizeof Ethernet::buffer, mymac, CS) == 0)
    Serial.println(F("Failed to access Ethernet controller"));
  ether.staticSetup(myip);

  // настройка входов/выходов
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);

  // включение реле
  setRelayState(true);
}

/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last) {
  boolean current = digitalRead(BUTTON_PIN);   // Считать состояние кнопки
  if (last != current) {                       // Если изменилось ...
    delay(5);                                  // ждём 5 мс
    current = digitalRead(BUTTON_PIN);         // Считываем состояние кнопки
    return current;                            // Возвращаем состояние кнопки
  }
}

void setRelayState(boolean relayOn) {
  digitalWrite(RELAY_PIN, relayOn);
  digitalWrite(LED_PIN, relayOn);
  if (relayOn) {
    relayLabel = "ON";
  } else {
    relayLabel = "OFF";
  }
}

void loop () {
  // управление по локальной сети
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  if (pos) {
    if (strstr((char *)Ethernet::buffer + pos, "GET /?ON") != 0) {
      setRelayState(true);
    } else if(strstr((char *)Ethernet::buffer + pos, "GET /?OFF") != 0) {
      setRelayState(false);
    }
    // выдать веб-интерфейс
    BufferFiller bfill = ether.tcpOffset();
    bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
      "Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"
      "<html>\n<head><meta http-equiv=\"refresh\" content=\"5;URL=http://"
      MY_IP
      "/\"></head>\n<body>\n<center>Relay is $S</center>\n"
      "<a href=\"http://"
      MY_IP
      "/?OFF\" rel=\"nofollow\">Turn Off</a><br></br>\n"
      "<a href=\"http://"
      MY_IP
      "/?ON\" rel=\"nofollow\">Turn On</a><br></br>\n"
      "<a href=\"http://"
      MY_IP
      "/\" rel=\"nofollow\">Check Status</a><br>\n"
      "</body>\n</html>\n"
      ), relayLabel);
      ether.httpServerReply(bfill.position());
  }

  // реакция на нажатие кнопки для реле
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH) { // если нажатие
    setRelayState(!relayStatus);
  }
  lastButton = currentButton;
}

Начались рабочие будни.
Опробовал скетч, огромнейшее спасибо, что не бросили в одиночестве с проблемой.
Со скетчем выше кнопка не работает вообще. То есть я могу управлять релюшкой с веб-интерфейса, а кнопка мёртвая, её нажатие не переключает реле и не меняет состояние нажатия на кнопку на веб-интерфейсе.

#17 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-10 23:26:53

Йожэг пише:

Только relayLabel формировать не в привязке к каким-то дополнительным условиям, а по значению relayStatus.

Запутался. roll
Добавленную Вами строку кода:

"<a href=\"http://адрес/\" rel=\"nofollow\">Check Status</a>"

форум исправил так, как ему захотелось.
строка
), relayLabel, linkLabel, linkLabel);
сократилась до:
), relayLabel);
Вот все различия, которые я смог проследить.
Сразу извиняюсь за нулевые знания в написании под Ардуину, если бы знал где подсмотреть этот кусок кода, возможно и не тревожил бы никого.

#18 Re: Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-10 22:39:38

Йожэг пише:
z0ri пише:

Надо чтобы информация о состоянии реле я знал через веб интерфейс модуля enc28j60 на arduino. Может кто знает как решить задачу?

В коде есть состояние реле (boolean relayStatus), вот его-то и надо выводить на веб-страничку как состояние реле. Разве не?

Возможно. Как ?

#19 Програмування Arduino » Управление реле через arduino, enc28j60 и кнопки » 2016-01-10 21:31:51

z0ri
відповідей: 39

Здравствуйте, уважаемые посетители и администраторы форума.

Совсем недавно начал играться с Ардуино и появился вопрос, который не знаю как решить. Опишу всё максимально подробно.

Есть в наличии: 1) Arduino Uno, 2) модуль сети mini enc28j60(в перспективе хочу заменить), 3) плата с двумя реле srd-05vdc-sl-c (использую только одно реле. В перспективе хочу заменить), кнопка тактовая без фиксации.

С горем пополам спустя несколько дней накидал такой скетч:

#include <EtherCard.h>

// разъем CS из модуля сети подключаем к 10-му пину на ардуино
#define CS 10
#define RELAY_PIN 4
#define REQUEST_RATE 5000

// настройки сетевого интерфейса
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 10,36,1,52 };
static byte gwip[] = { 10,36,1,7 };
static byte dnsip[] = { 10,36,1,7 };
static byte hisport[] = { 80 };

char* on  = "ON";
char* off = "OFF";
boolean relayStatus;
char* relayLabel;
char* linkLabel;

byte Ethernet::buffer[700];


// --- begin для кнопки
// задаём константы
const int buttonPin = 2;     // номер входа, подключенный к кнопке
// переменные
boolean lastButton = LOW;      // Переменная для сохранения предыдущего состояния кнопки
boolean currentButton = LOW;   // Переменная для сохранения текущего состояния кнопки
// --- end конец для кнопки

// --- begin для светодиода
const int ledPin =  6;     // номер выхода светодиода на Arduino
boolean ledOn = false;         // Текущее состояние светодиода (включен/выключен)
// --- end для светодиода


void setup () {
// begin  инициируем подключение к локальной сети
  delay(300); 
  if (ether.begin(sizeof Ethernet::buffer, mymac, CS) == 0)
    Serial.println(F("Failed to access Ethernet controller"));
  ether.staticSetup(myip);
// end  инициируем подключение к сети

// --- begin для реле
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH); 
  // если надо чтобы при обновлении
  // страницы в браузере реле сразу включалось
  // надо вместо true поставить false
  relayStatus = true;
  relayLabel = off;
  linkLabel = on;
// --- end для реле


// --- begin для кнопки
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);
// --- end для кнопки

// --- begin для светодиода на 6-ом пине
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);
// --- end для светодиода

}


// --- begin сглаживание кнопки
/*
 * функция сглаживания дребезга
 * принимает в качестве аргумента предыдущее состояние кнопки
 * и выдаёт фактическое.
 */
boolean debounce(boolean last)
{
  boolean current = digitalRead(buttonPin);    // Считать состояние кнопки
  if (last != current)                         // Если изменилось ...
{
  delay(5);                                    // ждём 5 мс
  current = digitalRead(buttonPin);            // Считываем состояние кнопки
  return current;                              // Возвращаем состояние кнопки
}
}
// --- end сглаживание кнопки


void loop () {
// --- begin управление по локальной сети
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
 
  if(pos) {    
    if(strstr((char *)Ethernet::buffer + pos, "GET /?ON") != 0) {
      relayStatus = false;
      relayLabel = on;
      linkLabel = off;
    } else if(strstr((char *)Ethernet::buffer + pos, "GET /?OFF") != 0) {
      relayStatus = true;
      relayLabel = off;
      linkLabel = on;
    }
    digitalWrite(RELAY_PIN, relayStatus);

    BufferFiller bfill = ether.tcpOffset();
    bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
      "Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"
      "<html><head></head><body>"
      "<div style='font:bold 14px verdana;text-align:center'>Relay is $S</div>"
      "<a href='<a href="http://10.36.1.52/?OFF" rel="nofollow">http://10.36.1.52/?OFF</a>'>Выключить</a>"
      "<br></br>"
      "<a href='<a href="http://10.36.1.52/?ON" rel="nofollow">http://10.36.1.52/?ON</a>'>Включить</a>"
      
      "</div></div></body></html>"
      ), relayLabel, linkLabel, linkLabel);
     
      ether.httpServerReply(bfill.position());
    }
// --- end управление по локальной сети

// --- begin реакция на нажатие кнопки для реле
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)   // Если нажатие
{
relayStatus = !relayStatus;
ledOn = !ledOn;
}
lastButton = currentButton;
digitalWrite(RELAY_PIN, relayStatus);                 // Изменить статус состояния реле
digitalWrite(ledPin, ledOn);                         // Изменить статус состояния светодиода
// --- end реакция на нажатие кнопки для реле


  }

Что делает скетч:
С кнопки можно включить реле и выключить (кнопку постоянно держать нажатой для этого не нужно-это важный момент). Релюшку так же можно переключать через веб интерфейс. Если я щёлкаю релюшкой через веб-интерфейс, то отрисовывается состояние реле (OFF или ON). Могу переключить реле физической кнопкой, а выключить через web и наоборот. Всё вобщем так, как и надо было. На светодиод на пину №6 можно внимание не обращать - это "муки творчества" :-)

Что должно получиться и не получается сделать:
Надо, чтобы переключая реле, я знал о текущем его состоянии, не зависимо от того переключил я реле с физической кнопки или через веб-интерфейс. Надо чтобы информация о состоянии реле я знал через веб интерфейс модуля enc28j60 на arduino.

Может кто знает как решить задачу?

Заранее благодарен.

Підвал форуму