виснет Ethernet Shield W5500

sadman41
Offline
Зарегистрирован: 19.10.2016

Wiznet 5500 не имеет закрепленного за чипом MAC-адреса.

https://en.wikipedia.org/wiki/MAC_address
...
If the bit is 0, the address is universally administered, which is why this bit is 0 in all OUIs. If it is 1, the address is locally administered. In the example address 06-00-00-00-00-00 the first octet is 06 (hexadecimal), the binary form of which is 00000110, where the second-least-significant bit is 1. Therefore, it is a locally administered address
...

Что непонятно про IPAddress? Это объемная тема, не для двух строк.

Для Ethernet.h нужен адрес в виде класса (синтаксического сахара). Но в сущности, на низком уровне адрес - 4 бита/октета. Так что в зависимости от сферы применения нужно соотв. представление.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

sadman41 пишет:
Что непонятно про IPAddress?

Непонятно почему в каких-то примерах

IPAddress ip (192, 168, 1, 10);

а в каких-то

uint8_t ip[] = {192, 168, 1, 12};

в стандартном" примере 

//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
char server[] = "www.google.com";    // name address for Google (using DNS)
IPAddress ip(192, 168, 0, 177);
IPAddress myDns(192, 168, 0, 1);

Получается нужно делать так?

IPAddress ip (192, 168, 1, 12);
IPAddress gateway (192, 168, 1, 1);
IPAddress subnet (255, 255, 255, 0);
IPAddress server (192, 168, 1, 10);
IPAddress dns (192, 168, 1, 1);

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, захотели авторы и поместили в массив. Другие поместили адрес в экземпляр IPAddress, избежав лишней писанины.

При работе с Etherner.h все сводится к преобразованию byte[4] или uint32 в IPAddress и передаче его в begin(), connect() и т.п. Но в чип все равно уйдут 4 байта, вытащенные из IPAddress. Так написана библиотека.

4 байта/октета проще сохранить в EEPROM, передать по UART, засунуть в PROGMEM и пр. Если адрес прибит к скетчу и относительно неизменен, то можно не заморачиваться и объявлять сразу экземпляр класса.

Вобщем, нет тут однозначного правила применения - все зависит от общей идеи в алгоритме.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Значит использую IPAddress server(192, 168, 1, 42);, как Вы говорите писанины меньше.

А про POST, Disconnecting не происходит потому что в запросе нет Connection: close ?

nik182
Offline
Зарегистрирован: 04.05.2015

IP aдрес это уникальная идентификация устройства в сети. Даётся один раз, если конечно какие-нибудь отжимальщики не придут и не отнимут. Если на весь мир, то денег стоит. Но к счастью придумали частные сети и дали им IP адреса 168.192.ХХХ.ХХХ, 10.ХХХ.ХХХ.ХХХ и ещё немножко из серии 172. , но их совсем чуть чуть. Вот из из этих адресов и состоят сети пользователей за всякими роутерами с NAT и прочими. Их не видно из мира и точно такиеже могут быть у соседа. Мораль сего спича такова. Если включаешь устройство в свою локальную сеть, то должна сама(!) выбрать IP адрес из свободных в твоей сети, а не брать из примеров. Самый простой путь узнать свободный адрес - войти в панель своего роутера и посмотреть занятые. Будут например заняты до 192.168.0.105 то можно брать 192.168.0. 106 и подставлять в программу. Но это ты должна сделать сама! Выбрать адрес и подставить в программу. И маску можно подсмотреть в настройках IP адресов роутера. Адрес роутера - адрес гейта. Его тоже программа потребует.   

sadman41
Offline
Зарегистрирован: 19.10.2016

Irinka пишет:

А про POST, Disconnecting не происходит потому что в запросе нет Connection: close ?


Скорее всего не отрабатывает stop(). Зря усложнили исходник раньше времени.

Заголовок (HTTP Header) "Connection: close" - это лишь просьба к удаленной стороне закрыть сессию. Но та сторона может иметь свой взгляд на обмен данными по POST и ждать обработки (помещения в SQL DB или тп) перед реальным закрытием. Это может затянуться. Единственный способ гарантировано завершить сессию - самостоятельно перевести сокет в CLOSE, чем и занимается stop(). Хидер не помешает - он декларирует намерения, но гарантия - самостоятельное терминирование.

Из-за таких непрогнозируемых случаев поведения удаленной стороны, реализация обмена данными часто становится очень громоздкой. А тем более в рамках МК и мелкочипов.

Вот у 5500 только 8 сессий можно открыть. Если каждую секунду делать connect() и POST не дожидаясь правильного закрытия сессии, то через 8 сек система встанет раком. Потом, по таймауту какие-то сессии закроются. МК опять немножко позапрашивает и подвиснет. Аккуратно надо, вобщем, действовать.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:
Wiznet 5500 не имеет закрепленного за чипом MAC-адреса.

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

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:
Del

время жизни пакета TCP/IP  в сети  - 5 секунд

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
      client.print(F("POST /script/cat.php HTTP/1.1\r\n"));
      client.print(F("Host: 192.168.1.10\r\n"));
      client.print(F("Content-Type: application/x-www-form-urlencoded\r\n"));
      client.print(F("Content-Length: 12\r\n"));
      client.print(F("\r\n"));
      client.print(F("cat=12345678")); 
      client.stop();

Запрос не выполняется (точнее client.available() ничего не получает)

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Если останавливать клиент через 100 мс (не использую паузу) то клиент останавливается))))))))))))) 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вот такой код

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

#define PORT 80
#define  MAX_BUF 50


#define DEBUG
#ifdef DEBUG
#define SERIAL_BEGIN     Serial.begin(57600)
#define DEBUG_PRINT(x)    Serial.print (x)
#define DEBUG_PRINTLN(x)   Serial.println (x)
#define DEBUG_PRINT_T(x)   Serial.print (F(x))
#define DEBUG_PRINTLN_T(x)  Serial.println (F(x))
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINT_T(x)
#define DEBUG_PRINTLN_T(x)
#define SERIAL_BEGIN
#endif


const uint8_t mac[] = {0x03, 0x8C, 0x01, 0x12, 0x10, 0x1B};
IPAddress ip(192, 168, 1, 98);
IPAddress dns(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress server(192, 168, 1, 42);
EthernetClient client;

#define  MAX_BUF 50
char buffers[MAX_BUF];
uint8_t pos_buf;

struct MyFlags {
  bool stop_client : 1;
};
MyFlags flags;

uint32_t timer_stop_client;

void http_post() {
  if (client.connect(server, PORT)) {
    DEBUG_PRINTLN_T("Connected");
    flags.stop_client = true;
    timer_stop_client = millis();
    client.print(F("POST /script/connection.php HTTP/1.1\r\n"));
    client.print(F("Host: 192.168.1.42\r\n"));
    client.print(F("Content-Type: application/x-www-form-urlencoded\r\n"));
    client.print(F("Content-Length: 12\r\n"));
    client.print(F("\r\n"));
    client.print(F("cat=12345678"));

  } else {
    DEBUG_PRINT_T("Connection failed.");
  }
}

void buffersclear() {
  memset(buffers, 0, MAX_BUF);
  pos_buf = 0;
}

void setup() {
  Ethernet.begin(mac, ip, dns, gateway, subnet);
  SERIAL_BEGIN;
  DEBUG_PRINTLN_T("Start");

}

void loop() {


  static uint32_t timer_status;
  if (millis() - timer_status >= 500) {
    timer_status = millis();
    Serial.print("Status = ");
    Serial.print(client.connected() );
    Serial.println("");
  }




  static uint32_t timer_connection;
  if (millis() - timer_connection >= 3000) {
    timer_connection = millis();
    http_post();
  }


  if (flags.stop_client && millis() - timer_stop_client >= 500 && client.connected()) {
    flags.stop_client = false;
    client.stop();
    Serial.println("stop");
  }



  if (client.available()) {
    byte temp = client.read();
    if (temp) {
      if (pos_buf >= MAX_BUF) {
        buffersclear();
      } else {
        buffers[pos_buf] = temp;
        pos_buf++;


        if (temp == '\n' && pos_buf > 1 && buffers[pos_buf - 2] == '\r') {
          //DEBUG_PRINT("Polucheno: ");
          // DEBUG_PRINT(pos_buf);
          //DEBUG_PRINT(" Byte");
          //DEBUG_PRINTLN("");
          DEBUG_PRINT(buffers);
          buffersclear();
        }
      }
    }
  }

}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Получаю, соответственно, следующее:

Start
Status = 0
Status = 0
Status = 0
Status = 0
Status = 0
Connected
HTTP/1.1 200 OK
Date: Sun, 02 Jan 2022 11:10:11 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 12
Connection: keep-alive
Keep-Alive: timeout=120
Server: Apache
X-Content-Type-Options: nosniff

12345678OK
Status = 1
stop
Status = 0
Status = 0
Status = 0
Status = 0
Status = 0
Connected
HTTP/1.1 200 OK
Date: Sun, 02 Jan 2022 11:10:14 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 12
Connection: keep-alive
Keep-Alive: timeout=120
Server: Apache
X-Content-Type-Options: nosniff

12345678OK
Status = 1
stop

php

<?php
$cat=$_POST['cat'];
echo ($cat);
echo ("OK\r\n");
?>

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Здравствуйте.

После чего-то, может после обновлений, началась вот такая беда

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


uint8_t mac[] = {0x00, 0x85, 0x62, 0x53, 0x05, 0x9C};//1


uint8_t ip[] = {192, 168, 1, 22};
uint8_t gateway[] = {192, 168, 1, 1};
uint8_t subnet[] = {255, 255, 255, 0};
uint8_t dns[] = {192, 168, 1, 1};
uint8_t server[] = {192, 168, 1, 42};
EthernetClient client;

void setup() {
  Ethernet.begin(mac, ip, dns, gateway, subnet);

}

void loop() {
  // put your main code here, to run repeatedly:

}

При проверке скетча выдаёт ошибку, при повторной проверке скетча ошибки нет, а лог выглядит так

In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:8:0:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp: In member function 'uint16_t DNSClient::BuildRequest(const char*)':
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\utility/w5100.h:457:25: warning: result of '(256 << 8)' requires 18 bits to represent, but 'int' only has 16 bits [-Wshift-overflow=]
 #define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) )
                      ~~~^~~
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:164:18: note: in expansion of macro 'htons'
  twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
Ethernet.begin(mac, ip);

Даже если не использую DNS

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Аааа, это предупреждение ...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

Аааа, это предупреждение ...

в IDE 1.8.19 предупреждений еще больше

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

А исправлять не нужно?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

C:\Program Files (x86)\Arduino\libraries\Ethernet\src\utility\w5100.h

строчку

#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) )

заменить на

#define htons(x) ( ((((x)&0xFF)<<8)&0xFF00) | (((x)>>8)&0xFF) )

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Irinka пишет:

C:\Program Files (x86)\Arduino\libraries\Ethernet\src\utility\w5100.h

строчку

#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) )

заменить на

#define htons(x) ( ((((x)&0xFF)<<8)&0xFF00) | (((x)>>8)&0xFF) )

Вы такая дотошная прямо как ДЕВА (по знаку рождения) )))

SAB
Offline
Зарегистрирован: 27.12.2016

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

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Давно на него смотрела, заказала вот, попробовать.

А что посоветуете? Arduino IDE, Espressif IDF, Lua RTOS

SAB
Offline
Зарегистрирован: 27.12.2016

Arduino IDE самое простое для начала хватит 

sadman41
Offline
Зарегистрирован: 19.10.2016

Я бы 8266 посоветовал для начала. Он, хотя бы, 5V терпит на входе.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:
Я бы 8266 посоветовал для начала. Он, хотя бы, 5V терпит на входе.

а ESP32 нет толерантен к 5V?

sadman41
Offline
Зарегистрирован: 19.10.2016

ua6em пишет:

sadman41 пишет:
Я бы 8266 посоветовал для начала. Он, хотя бы, 5V терпит на входе.

а ESP32 нет толерантен к 5V?

Производитель такой информации не даёт (я не встречал), поэтому пока считаю, что нет.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

SAB пишет:

Arduino IDE самое простое для начала хватит 

 

sadman41 пишет:
Я бы 8266 посоветовал для начала. Он, хотя бы, 5V терпит на входе.

Вы же понимаете...что в скором времени будет куча вопросов по этим устройствам XDD

(а может раздел создадим? ммм?)

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Так, и ещё вопрос появился, я при поступлении данных в контроллер отправляю данные через W5500 на сервер и смотрю что в ответе, всё. Нужна ли для таких целей плата на W5500, или вполне хватит  ENC28J60 ? ()

sadman41
Offline
Зарегистрирован: 19.10.2016

Хватит, если нервная система хорошая и запас по памяти есть у МК.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Давным давно я попробовал это гумно (ENC) с тех пор зарекся.

с w5100-5500 все просто прекрасно. 
единственный глюк за все время наступил не далее, чем вчера. Долго ловил этот глюк, пока не обнаружил, что плата ( стоит чипом от меня) греется почти как утюг. Поменял на другую- нагрев чуть теплее пальца и никаких глюков. Причем система с греющейся платой странно вела себя с самого начала. Теперь просто небо/земля.

SAB
Offline
Зарегистрирован: 27.12.2016

sadman41 пишет:

ua6em пишет:

sadman41 пишет:
Я бы 8266 посоветовал для начала. Он, хотя бы, 5V терпит на входе.

а ESP32 нет толерантен к 5V?

Производитель такой информации не даёт (я не встречал), поэтому пока считаю, что нет.

Проверенно лично, не терпит ESP32 5 вольт по входу. Недавно подключал диспенсер (5 вльтовая логика) напрямую по COM порту к ESP32 работал некоторое время, но при очередном включении устройства ESP именно по Rx ушла в кз. Пришлось заменить на новую и поставить обыкновенный делитель килоомом в землю и 510 Ом на вход. Работает уже месяц всё норм.

VlaR
Offline
Зарегистрирован: 17.02.2016

Добрый день. 
Про soft переинициализацию w5100/w5500 никто ничего не может подсказать?

sadman41
Offline
Зарегистрирован: 19.10.2016

Переинициализировать командой можно.

VlaR
Offline
Зарегистрирован: 17.02.2016

sadman41 пишет:
Переинициализировать командой можно.

А какой?

sadman41
Offline
Зарегистрирован: 19.10.2016

Не знаю, как это поможет, но: в регистр MR записать 0x80