Arduino UNO (NANO) + W5500 + 8 Realy

Scainet-001

✩✩✩✩✩✩✩
10 Мар 2022
3
1
Всем привет. Ищу того кто оптимизирует код чтобы он работал на Arduino UNO или NANO. Оригинал кода взят с
https://randomnerdtutorials.com/arduino-ethernet-web-server-with-relay/
Сам методом копипаста модифицировал скетч на 7 реле, но не хватает памяти для 8.
C++:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 30);
EthernetServer server(80);

String relay1State = "Off";
String relay2State = "Off";
String relay3State = "Off";
String relay4State = "Off";
String relay5State = "Off";
String relay6State = "Off";
String relay7State = "Off";
String relay8State = "Off";
const int relay1 = 2;
const int relay2 = 3;
const int relay3 = 4;
const int relay4 = 5;
const int relay5 = 6;
const int relay6 = 7;
const int relay7 = 8;
const int relay8 = 9;


char linebuf[10];
int charcount=0;

void setup() {

  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, HIGH);
  pinMode(relay2, OUTPUT);
  digitalWrite(relay2, HIGH);
  pinMode(relay3, OUTPUT);
  digitalWrite(relay3, HIGH);
  pinMode(relay4, OUTPUT);
  digitalWrite(relay4, HIGH);
  pinMode(relay5, OUTPUT);
  digitalWrite(relay5, HIGH);
  pinMode(relay6, OUTPUT);
  digitalWrite(relay6, HIGH);
  pinMode(relay7, OUTPUT);
  digitalWrite(relay7, HIGH);
  pinMode(relay8, OUTPUT);
  digitalWrite(relay8, HIGH);
 
  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void dashboardPage(EthernetClient &client) {
  client.println("<!DOCTYPE HTML><html><head>");
  client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");                                                             
  client.println("<h3>Arduino Web Server - <a href=\"/\">Refresh</a></h3>");
  client.println("<h4>Relay 1 - State: " + relay1State + "</h4>");
  if(relay1State == "Off"){
    client.println("<a href=\"/relay1on\"><button>ON</button></a>");
  }
  else if(relay1State == "On"){
    client.println("<a href=\"/relay1off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 2 - State: " + relay2State + "</h4>");
  if(relay2State == "Off"){
    client.println("<a href=\"/relay2on\"><button>ON</button></a>");
  }
  else if(relay2State == "On"){
    client.println("<a href=\"/relay2off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 3 - State: " + relay3State + "</h4>");
  if(relay3State == "Off"){
    client.println("<a href=\"/relay3on\"><button>ON</button></a>");
  }
  else if(relay3State == "On"){
    client.println("<a href=\"/relay3off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 4 - State: " + relay4State + "</h4>");
  if(relay4State == "Off"){
    client.println("<a href=\"/relay4on\"><button>ON</button></a>");
  }
  else if(relay4State == "On"){
    client.println("<a href=\"/relay4off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 5 - State: " + relay5State + "</h4>");
  if(relay5State == "Off"){
    client.println("<a href=\"/relay5on\"><button>ON</button></a>");
  }
  else if(relay5State == "On"){
    client.println("<a href=\"/relay5off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 6 - State: " + relay6State + "</h4>");
  if(relay6State == "Off"){
    client.println("<a href=\"/relay6on\"><button>ON</button></a>");
  }
  else if(relay6State == "On"){
    client.println("<a href=\"/relay6off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 7 - State: " + relay7State + "</h4>");
  if(relay7State == "Off"){
    client.println("<a href=\"/relay7on\"><button>ON</button></a>");
  }
  else if(relay7State == "On"){
    client.println("<a href=\"/relay7off\"><button>OFF</button></a>");                                                                   
  }
  client.println("<h4>Relay 8 - State: " + relay8State + "</h4>");
  if(relay8State == "Off"){
    client.println("<a href=\"/relay8on\"><button>ON</button></a>");
  }
  else if(relay8State == "On"){
    client.println("<a href=\"/relay8off\"><button>OFF</button></a>");                                                                   
  }
  client.println("</body></html>");
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    memset(linebuf,0,sizeof(linebuf));
    charcount=0;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
       char c = client.read();
       //read char by char HTTP request
        linebuf[charcount]=c;
        if (charcount<sizeof(linebuf)-1) charcount++;
        // 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) {
          dashboardPage(client);
          break;
        }
        if (c == '\n') {
          if (strstr(linebuf,"GET /relay1off") > 0){
            digitalWrite(relay1, HIGH);
            relay1State = "Off";
          }
          else if (strstr(linebuf,"GET /relay1on") > 0){
            digitalWrite(relay1, LOW);
            relay1State = "On";
          }
          if (strstr(linebuf,"GET /relay2off") > 0){
            digitalWrite(relay2, HIGH);
            relay2State = "Off";
          }
          else if (strstr(linebuf,"GET /relay2on") > 0){
            digitalWrite(relay2, LOW);
            relay2State = "On";
          }
          if (strstr(linebuf,"GET /relay3off") > 0){
            digitalWrite(relay3, HIGH);
            relay3State = "Off";
          }
          else if (strstr(linebuf,"GET /relay3on") > 0){
            digitalWrite(relay3, LOW);
            relay3State = "On";
          }
          if (strstr(linebuf,"GET /relay4off") > 0){
            digitalWrite(relay4, HIGH);
            relay4State = "Off";
          }
          else if (strstr(linebuf,"GET /relay4on") > 0){
            digitalWrite(relay4, LOW);
            relay4State = "On";
          }
          if (strstr(linebuf,"GET /relay5off") > 0){
            digitalWrite(relay5, HIGH);
            relay5State = "Off";
          }
          else if (strstr(linebuf,"GET /relay5on") > 0){
            digitalWrite(relay5, LOW);
            relay5State = "On";
          }
          if (strstr(linebuf,"GET /relay6off") > 0){
            digitalWrite(relay6, HIGH);
            relay6State = "Off";
          }
          else if (strstr(linebuf,"GET /relay6on") > 0){
            digitalWrite(relay6, LOW);
            relay6State = "On";
          }
          if (strstr(linebuf,"GET /relay7off") > 0){
            digitalWrite(relay7, HIGH);
            relay7State = "Off";
          }
          else if (strstr(linebuf,"GET /relay7on") > 0){
            digitalWrite(relay7, LOW);
            relay7State = "On";
          }
          if (strstr(linebuf,"GET /relay8off") > 0){
            digitalWrite(relay8, HIGH);
            relay8State = "Off";
          }
          else if (strstr(linebuf,"GET /relay8on") > 0){
            digitalWrite(relay8, LOW);
            relay8State = "On";
          }
          // you're starting a new line
          currentLineIsBlank = true;
          memset(linebuf,0,sizeof(linebuf));
          charcount=0;         
          }
        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 disonnected");
  }
}
Весь софт что я заказываю выкладываю на своём канале так что если нужно прорекламирую канал или группу исполнителя и софт будет доступен всем бесплатно. Но я не прошу сделать задаром просто нужен тот кто сделает за разумную цену.
из железа Arduino UNO и NANO CH340 и FTDI модуль W5500 маленький без карты памяти.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,301
Москва
В пол глаза посмотрел.
Получается много свободной пзу, мало озу.
Значит 1-ое что надо сделать все текстовые константы вместо "On" записать как F("On") Это прилично освободит озу.
Изменив таким образом 4 строки (56-59) я освободил ~10% Озу. Работа механическая и умения программировать не требует. Могут быть затыки , где идет сложение строк - просто пока пропустить эти места.

2-ое. Не хранить состояние реде в строках. Ну что за боред ? Хранить состояние 8 реле можно в 1-ом байте. Каждый бит либо 0 либо 1. 0-выключено , 1 включено. И если нужен текст - написать маленькую функцию. 8 реле по 4 байта на строку (off+0) это 32 байта вместо 1-го. Не много. но курочка по зернышку.
 
  • Лойс +1
Реакции: Boroda22

Scainet-001

✩✩✩✩✩✩✩
10 Мар 2022
3
1
рабочий скетч
C++:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 30);
EthernetServer server(80);

bool relayState[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};

#define relay1  2
#define relay2  3
#define relay3  4
#define relay4  5
#define relay5  6
#define relay6  7
#define relay7  8
#define relay8  9


char linebuf[80];
int charcount = 0;

void setup() {

  pinMode(relay1, OUTPUT);
  digitalWrite(relay1, HIGH);
  pinMode(relay2, OUTPUT);
  digitalWrite(relay2, HIGH);
  pinMode(relay3, OUTPUT);
  digitalWrite(relay3, HIGH);
  pinMode(relay4, OUTPUT);
  digitalWrite(relay4, HIGH);
  pinMode(relay5, OUTPUT);
  digitalWrite(relay5, HIGH);
  pinMode(relay6, OUTPUT);
  digitalWrite(relay6, HIGH);
  pinMode(relay7, OUTPUT);
  digitalWrite(relay7, HIGH);
  pinMode(relay8, OUTPUT);
  digitalWrite(relay8, HIGH);

  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void dashboardPage(EthernetClient &client) {
  client.println("<!DOCTYPE HTML><html><head>");
  client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");
  client.println("<h3>Arduino Web Server - <a href=\"/\">Refresh</a></h3>");
  for (byte i = 1; i < 9; i++) {
    client.println("<h4>Relay " + String(i) + " - State: ");
    if (relayState[i] == 0) {
      client.println("Off</h4><a href=\"/relay" + String(i) + "on\"><button>ON</button></a>");
    }
    else if (relayState[i] == 1) {
      client.println("On</h4><a href=\"/relay" + String(i) + "off\"><button>OFF</button></a>");
    }
  }
  client.println("</body></html>");
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    memset(linebuf, 0, sizeof(linebuf));
    charcount = 0;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //read char by char HTTP request
        linebuf[charcount] = c;
        if (charcount < sizeof(linebuf) - 1) charcount++;
        // 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) {
          dashboardPage(client);
          break;
        }
        if (c == '\n') {
          if (strstr(linebuf, "GET /relay1off") > 0) {
            digitalWrite(relay1, HIGH);
            relayState[1] = 0;
          }
          else if (strstr(linebuf, "GET /relay1on") > 0) {
            digitalWrite(relay1, LOW);
            relayState[1] = 1;
          }
          if (strstr(linebuf, "GET /relay2off") > 0) {
            digitalWrite(relay2, HIGH);
            relayState[2] = 0;
          }
          else if (strstr(linebuf, "GET /relay2on") > 0) {
            digitalWrite(relay2, LOW);
            relayState[2] = 1;
          }
          if (strstr(linebuf, "GET /relay3off") > 0) {
            digitalWrite(relay3, HIGH);
            relayState[3] = 0;
          }
          else if (strstr(linebuf, "GET /relay3on") > 0) {
            digitalWrite(relay3, LOW);
            relayState[3] = 1;
          }
          if (strstr(linebuf, "GET /relay4off") > 0) {
            digitalWrite(relay4, HIGH);
            relayState[4] = 0;
          }
          else if (strstr(linebuf, "GET /relay4on") > 0) {
            digitalWrite(relay4, LOW);
            relayState[4] = 1;
          }
          if (strstr(linebuf, "GET /relay5off") > 0) {
            digitalWrite(relay5, HIGH);
            relayState[5] = 0;
          }
          else if (strstr(linebuf, "GET /relay5on") > 0) {
            digitalWrite(relay5, LOW);
            relayState[5] = 1;
          }
          if (strstr(linebuf, "GET /relay6off") > 0) {
            digitalWrite(relay6, HIGH);
            relayState[6] = 0;
          }
          else if (strstr(linebuf, "GET /relay6on") > 0) {
            digitalWrite(relay6, LOW);
            relayState[6] = 1;
          }
          if (strstr(linebuf, "GET /relay7off") > 0) {
            digitalWrite(relay7, HIGH);
            relayState[7] = 0;
          }
          else if (strstr(linebuf, "GET /relay7on") > 0) {
            digitalWrite(relay7, LOW);
            relayState[7] = 1;
          }
          if (strstr(linebuf, "GET /relay8off") > 0) {
            digitalWrite(relay8, HIGH);
            relayState[8] = 0;
          }
          else if (strstr(linebuf, "GET /relay8on") > 0) {
            digitalWrite(relay8, LOW);
            relayState[8] = 1;
          }
          // you're starting a new line
          currentLineIsBlank = true;
          memset(linebuf, 0, sizeof(linebuf));
          charcount = 0;
        }
        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 disonnected");
  }
}
Спасибо IamNikolay за помощь
 

Levvarrr

✩✩✩✩✩✩✩
16 Мар 2022
2
1
Привет! Попробуй этот код. Сократил и уменьшил в размере.
C++:
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 30);
EthernetServer server(80);

bool relayState[8] = {0, 0, 0, 0, 0, 0, 0, 0};
byte relay[8] = {2, 3, 4, 5, 6, 7, 8, 9};

char linebuf[80];
int charcount = 0;

void setup() {

  for (byte i = 0; i < 8; i++)
  {
    pinMode(relay[i], OUTPUT);
    digitalWrite(relay[i], HIGH);
  }

  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void dashboardPage(EthernetClient &client) {
  client.println("<!DOCTYPE HTML><html><head>");
  client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");
  client.println("<h3>Arduino Web Server - <a href=\"/\">Refresh</a></h3>");
  for (byte i = 0; i < 8; i++) {
    client.println("<h4>Relay " + String(i) + " - State: ");
    if (relayState[i] == 0) {
      client.println("Off</h4><a href=\"/relayon=" + String(i) + "><button>ON</button></a>");
    }
    else if (relayState[i] == 1) {
      client.println("On</h4><a href=\"/relayoff=" + String(i) + "><button>OFF</button></a>");
    }
  }
  client.println("</body></html>");
}

void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    memset(linebuf, 0, sizeof(linebuf));
    charcount = 0;
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //read char by char HTTP request
        linebuf[charcount] = c;
        if (charcount < sizeof(linebuf) - 1) charcount++;
        // 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) {
          dashboardPage(client);
          break;
        }
        if (c == '\n')
        {
          byte temp = 0;
          sscanf((char *)linebuf, "%*[^0-9]%d", &temp);

          if (strstr(linebuf, "GET /relay1off") > 0) {
            digitalWrite(relay[temp], HIGH);
            relayState[temp] = 0;
          }
          if (strstr(linebuf, "GET /relay1on") > 0) {
            digitalWrite(relay[temp], LOW);
            relayState[temp] = 1;
          }
          // you're starting a new line
          currentLineIsBlank = true;
          memset(linebuf, 0, sizeof(linebuf));
          charcount = 0;
        }
        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 disonnected");
  }
}
C++:
 

Scainet-001

✩✩✩✩✩✩✩
10 Мар 2022
3
1
@Levvarrr, привет
веб сервер отрисовывает кнопки под номерами 0 2 4 6 ну как бы вот так :rolleyes:
 

Levvarrr

✩✩✩✩✩✩✩
16 Мар 2022
2
1
Эх.... Пришлось проверять. Напрягаться :)
Нашел у себя W5500.
Все работало правильно. Кавычек не хватало. + еще подправил код в одном месте и выкинул еще лишнюю хрень.
C++:
#include <SPI.h>
#include <Ethernet2.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 21);
EthernetServer server(80);

bool relayState[8] = {0, 0, 0, 0, 0, 0, 0, 0};
byte relay[8] = {2, 3, 4, 5, 6, 7, 8, 9};

char linebuf[80];
int charcount = 0;

void setup() {

  for (byte i = 0; i < 8; i++)
  {
    pinMode(relay[i], OUTPUT);
    digitalWrite(relay[i], HIGH);
  }

  Serial.begin(9600);

  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void dashboardPage(EthernetClient &client) {
  client.println("<!DOCTYPE HTML><html><head>");
  client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");
  client.println("<h3>Arduino Web Server - <a href=\"/\">Refresh</a></h3>");
  for (byte i = 0; i < 8; i++) {
    client.println("<h4>Relay " + String(i) + " - State: ");
    if (relayState[i] == 0) {
      client.println("Off</h4><a href=\"/relayon=" + String(i) + "\"><button>ON</button></a>");
    }
    else if (relayState[i] == 1) {
      client.println("On</h4><a href=\"/relayoff=" + String(i) + "\"><button>OFF</button></a>");
    }
  }
  client.println("</body></html>");
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    memset(linebuf, 0, sizeof(linebuf));
    charcount = 0;
    boolean currentLineIsBlank = true;

    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        linebuf[charcount] = c;
        if (charcount < sizeof(linebuf) - 1) charcount++;

        if (c == '\n')
        {
          byte temp = 0;
          sscanf((char *)linebuf, "%*[^0-9]%d", &temp);

          if (strstr(linebuf, "relayoff") > 0)
          {
            digitalWrite(relay[temp], HIGH);
            relayState[temp] = 0;
          }
          if (strstr(linebuf, "relayon") > 0)
          {
            digitalWrite(relay[temp], LOW);
            relayState[temp] = 1;
          }
          dashboardPage(client);
          break;
        }

      }
    }
    delay(1);
    client.stop();
  }
}
Как я понял из комментария на ютубе. Ты хочешь еще и кнопки прикрутить к этому делу. И при нажатии кнопки не только срабатывало реле, но и обновлялась страничка в браузере.
Это все реализуемо. НО я сомневаюсь что у тебя это получится. (Ведь изначально ты даже циклами не пользовался для упрощения кода).
Для реализации подобной задумки требуется знание HTML,JS и CSS что бы все приукрасить.
Для начало посмотри цикл этих роликов:
В них есть все для старта.
Еще проблема в отсутствии места на МК. На мегу328 в принципе все это залезть сможет. Но желательно писать код уже на С.
ЗЫ: Подправь IP и Библу Ethernet
 
Изменено:
  • Лойс +1
Реакции: Boroda22