ARDUINO Зависает Arduino Nano + Ethernet

max2242

✩✩✩✩✩✩✩
27 Фев 2020
5
0
Всем привет!
Сделал на ардуине термодатчик с подключением по локальной сети. Смотрим за температурой в помещении, данные с датчика забирает Zabbix, хранит у себя, выводит к нам на монитор настенный - красота. Но иногда (закономерности вывести не удалось) это чудо техники зависает. На пинги не отвечает, температуру не показывает. Индикатор на ардуине горит. Пробовал запитывать с USB-порта компа, пробовал с 2-амперной зарядки от телефона - результат один. Может зависнуть раз в 2 недели, может 2 раза в день, а потом еще неделями работать без проблем.

Arduino Nano с алиэкспресса (WAVGAT), на нее бутербродом одет шилд ENC28J60, датчик DS18B20, подтянут резистором 4.7 кОм.

Скетч странный, сразу скажу. Это первый проект и я не нашел ничего лучше, чем крутить на ардуине веб-сервер и забирать данные по HTTP. Сисадмин, чоуш ))))) Частично сам, частично копипаст с какого-то похожего проекта в инете.



C++:
#include <OneWire.h>
#include <UIPEthernet.h>

byte mac[] = { 0xDE, 0x05, 0xB6, 0x27, 0x39, 0x19 }; // random MAC
byte ip[] = { 10, 10, 0, 102 }; // IP address in local network
String readString = String(20);
byte addr[8];

OneWire ds(4);                   // пин датчика
EthernetServer server(80);       // тут порт куда подключаться браузером

void setup()
{
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  ds.search(addr);
}

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 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) {
          // отправляет стд ответ браузеру
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();

          byte data[2]; // Место для значения температуры

          ds.reset(); // Начинаем взаимодействие со сброса всех предыдущих команд и параметров
          ds.write(0xCC); // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
          ds.write(0x44); // Даем датчику DS18b20 команду измерить температуру. Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память

          delay(3000); // датчик меряет 1 секунду, но я поставил 3 - не могу понять почему зависает раз в пару суток

          ds.reset(); // Теперь готовимся получить значение измеренной температуры
          ds.write(0xCC);
          ds.write(0xBE); // Просим передать нам значение регистров со значением температуры
          // Получаем и считываем ответ
          data[0] = ds.read(); // Читаем младший байт значения температуры
          data[1] = ds.read(); // А теперь старший
          // Формируем итоговое значение:
          //    - сперва "склеиваем" значение,
          //    - затем умножаем его на коэффициент, соответсвующий разрешающей способности (для 12 бит по умолчанию - это 0,0625)
          float temperature =  ((data[1] << 8) | data[0]) * 0.0625;
            // ниже светодиод самой ардуины, использовал при отладке, в финальной версии оставил
          if (temperature >= 32) {
            digitalWrite(LED_BUILTIN, HIGH);
          } else {
            digitalWrite(LED_BUILTIN, LOW);
          }
            // формируем саму веб-страницу с цифрами температуры
          client.print(temperature);
          break;
        }
        if (c == '\n') {
          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(10);
    // close the connection:
    client.stop();
  }
}
Когда этот Франкенштейн работает - любой кто заходит в браузере по http://10.10.0.102 видит температуру с датчика. Сначала я подозревал что сервер мониторинга слишком часто опрашивает ардуину на предмет температуры, и увеличил задержку до 3 минут. Не помогло.

Есть подозрение что что-то с питанием и неплохо бы кормить ее не через USB, а подпаяв БП прямо на ардуину, но решил сперва спросить специалистов.

Всем спасибо!
 

PiratFox

★★★✩✩✩✩
13 Фев 2020
614
136
Харьков
@max2242, насчёт питания подозрение правильное. Шилд ENC28J60 в пике может потреблять ток больший, чем отдаст USB. А когда 2-х амперную зарядку подключали, конденсатор по питанию вешали?
 

Fleshdeck

★★★✩✩✩✩
19 Янв 2019
307
156
Киев
@max2242, я когда делал умный дом тоже использовал Arduino Nano и ENC28J60, у меня оно зависало стабильно каждых 3-4 дня, я проблему не искал, просто перешел на Arduino Mega 2560 и за пол года ни единого сбоя не было
 

max2242

✩✩✩✩✩✩✩
27 Фев 2020
5
0
Огромное спасибо всем ответившим! Попробую запитать ардуину в пины V-in и GND от нормального блока питания (например, от нетбука), задействовав тем самым ее встроенный линейный стабилизатор. Конденсатор параллельно ставить или это уже избыточная мера? Паять LC-фильтр пока некогда, хотя идея кажется здравой.
 

PiratFox

★★★✩✩✩✩
13 Фев 2020
614
136
Харьков
Попробую запитать ардуину в пины V-in и GND
В V-in 5 вольт подавать смысла мало, будет просадка напряжения на встроенном линейном стабилизаторе. И больше 12 вольт подавать туда КРАЙНЕ нежелательно: ардуину можно сжечь. И да, конденсаторы по питанию лишними не будут.
 
Последнее редактирование:

max2242

✩✩✩✩✩✩✩
27 Фев 2020
5
0
@PiratFox, имел в виду эту схему (с гайда Алекса):




На работе куча зарядок от ноутов и прочих адаптеров, думаю подобрать что-то в районе 11-12 вольт, как для маленьких ноутов. Обычно в ноутбучных ЗУ нормальные преобразователи и фильтры.
 

PiratFox

★★★✩✩✩✩
13 Фев 2020
614
136
Харьков
думаю подобрать что-то в районе 11-12 вольт, как для маленьких ноутов.
Вот это тоже здравая идея.
Обычно в ноутбучных ЗУ нормальные преобразователи и фильтры.
В большинстве случаев - да. А вообще, не помешает осциллографом посмотреть качество питающего напряжения.
 
Последнее редактирование:

kostyamat

★★★★★★★
29 Окт 2019
2,157
1,209
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
А такое применение класса вообще законно? Удивительно что это вообще работает!
Вы бы вынесли его над setup типа так
EthernetClient client;
Вот пример для вашей же библиотеки https://github.com/UIPEthernet/UIPEthernet/blob/master/examples/TcpClient/TcpClient.ino
Сравните - шо не так?!

А вместо if (client) так
if (server.available())

Во вторых - а почему вы не используете стандартную библиотеку для ds18b20?
https://www.arduinolibraries.info/libraries/dallas-temperature

В третьих - а что делает ваш клиент, пока у вас delay(3000) не бомбит ли езернет повторными запросами по тайм-аут ответа сервера? Может у вас шилд вешается, а не ардуино, у него вроде свой контроллер и прошивка, которой это может сильно не нравится.
Может все таки лучше тик-так флаг завести? Тик - запросили данные с датчика, ответили клиенту взвели таймер (записали в переменную значение millis()), вернулись в начало loop, и проверяем if (millis() - тайм-аут => 3000) {
bool tikTok = false;
читаем данные с датчика
}
 
Последнее редактирование:

maks.dav

✩✩✩✩✩✩✩
1 Апр 2020
3
0
@Fleshdeck, может сохранились библиотеки для enc28j60 + mqtt??
Использовал Mega+enc28j60 c библиотеками UIPEthernet + PubSubClient последних версий с гитхаба - зависает сам контроллер каждые несколько часов (циклы while для переподключения убраны)
Может поможете??
 

Fleshdeck

★★★✩✩✩✩
19 Янв 2019
307
156
Киев
@maks.dav, вот моя библиотека UIPEthernet, так как я использовал Blynk, эта библиотека нужна лишь для его корректной работы, как себя поведет с mqtt не знаю.
 

Вложения