Чудит ардуинка

yden
Offline
Зарегистрирован: 30.01.2016

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

Подскажите пожалуйста по коду. Ардуино нано с шилдом на  ENC28J60.  Стоит в бане (предбанник, герметичный корпус). Общается с mqtt сервером, подключены 2 датчика ds18b20, кнопка (выключатель) и релюшка. Китай. Реле рулит светом 220.

Роль: с определенной периодичностью посылать по mqtt температуру с двух мест, дергать релюшкой.

Не хочет нормально работать. После перезагрузки корректно реагирует на нажатие выключателя, посылает темепературу. Но без какой-то системы прекращает слать температуру, на выключатель тоже раза в 5-10 реагирует. Может так же без системно дернуть релюшкой и выключить свет, т.е живет своей жизнью. Может день нормально проработать, а может через 10 минут закапризничать.

Менял шилд, ардуинку, блок питания, отключал ds18b20. Думал может расстояние витой пары для шилда велико (20 метров), рядом с ардуинкой поставил свитч - не помогло. 

Может что в коде не верно. Но этот код - клон такой же системы, управляющей светом в доме, но без температуры - без проблем работает.

#include <UIPEthernet.h>
#include <Bounce2.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PubSubClient.h>

// =======================================================================
// Конфигурация устройства MQTT:
uint8_t mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE2 };
uint8_t myIP[4] = {192, 168, 1, 72};
uint8_t myDNS[4] = {192, 168, 1, 1};
uint8_t myGW[4] = {192, 168, 1, 1};
uint8_t myMASK[4] = {255, 255, 255, 0};

const char *mqtt_server = "192.168.1.70"; // Имя сервера MQTT
const int mqtt_port = 1883; // Порт для подключения к серверу MQTT
const char *mqtt_user = "yunin"; // Логи от сервер
const char *mqtt_pass = "yunindenis"; // Пароль от сервера

EthernetClient ethClient;
PubSubClient clientMqtt(ethClient);

// =======================================================================
//ds18b20
OneWire oneWire(4); // вход датчиков 18b20
DallasTemperature ds(&oneWire);
DeviceAddress ds_t_out = {0x28, 0xFF, 0x9A, 0x28, 0x72, 0x16, 0x04, 0xA9};
DeviceAddress ds_t_banya = {0x28, 0xFF, 0x91, 0x5C, 0x72, 0x16, 0x05, 0x21};
//DeviceAddress ds_t_banya = {0x28, 0xFF, 0x33, 0xD0, 0x72, 0x16, 0x05, 0x5A};

int t_out;
int t_out_old = 0;
int t_banya;
int t_banya_old = 0;

byte i = 0;

boolean flag_light_banya = false;

char buff[15];

//выходы нагрузки
const byte outPin1 = 5; // свет предбанник

//кнопки
const byte inButton1 = 6; //вход кнопка 

boolean buttonState = false; //состояние выключателя

//создаем объект класса Bounce. Указываем пин, к которому подключена кнопка, и время дребезга в мс.
Bounce debouncer1 = Bounce();

//подсчет времени
//опрос датчиков
long previousMillis_sensor = 0;  // храним время последнего опроса датчиков
long interval_sensor = 60000;     //интервал

//mqtt broker
long previousMillis_mqtt_connect = 0;  // храним время последнего подключения
long interval_mqtt_connect = 60000;     //интервал
unsigned long currentMillis_mqtt_connect = 0;

// =======================================================================
// Функция получения данных от сервера
void callback(char* topic, byte* payload, unsigned int length)
{
  //--------------------------------------------------------------------------------------
  //свет баня
  if (String(topic) == "ihouse/svet/banya")
  {
    if ((char)payload[0] == '1') flag_light_banya = true;
    if ((char)payload[0] == '0') flag_light_banya = false;
    digitalWrite(outPin1, flag_light_banya);
  }
}

// =======================================================================
void mqtt_reconnect()
{
  unsigned long currentMillis_mqtt_connect = millis();

  // подключаемся к MQTT серверу
  if (currentMillis_mqtt_connect - previousMillis_mqtt_connect >= interval_mqtt_connect)
  {
    String clientId = "nanobanya-";
    clientId += String(random(0xffff), HEX);
    if (clientMqtt.connect(clientId.c_str(), mqtt_user, mqtt_pass))
    {
      //подписываемся по топики
      clientMqtt.subscribe("ihouse/svet/banya");
      clientMqtt.loop();
    }
    previousMillis_mqtt_connect = currentMillis_mqtt_connect;
  }
}

// =======================================================================
void setup()
{
  Ethernet.begin(mac, myIP, myDNS, myGW, myMASK);
  delay(10);

  clientMqtt.setServer(mqtt_server, mqtt_port);
  clientMqtt.setCallback(callback);
  delay(10);

  ds.begin();

  //для релюшек
  pinMode(outPin1, OUTPUT);
  digitalWrite(outPin1, LOW);

  pinMode(inButton1, INPUT_PULLUP);

  debouncer1.attach(inButton1);
  debouncer1.interval(5);
}

//--------------------------------------------------------------------------------------
void loop()
{
  unsigned long currentMillis_sensor = millis();

  //--------------------------------------------------------------------------------------
  if (!clientMqtt.connected())
  {
    mqtt_reconnect();
  }

  //--------------------------------------------------------------------------------------
  //проверка состояния кнопки1 - предбанник
  if (debouncer1.update())
  {
    //факт нажатия
    if (debouncer1.fell())
    {
      flag_light_banya = !flag_light_banya;
      digitalWrite(outPin1, flag_light_banya);
    }

    //факт отпускания
    if (debouncer1.rose())
    {
      itoa(flag_light_banya, buff, 10);
      clientMqtt.publish("ihouse/svet/banya", buff);
      clientMqtt.publish("ihouse/svet/banya/button", "1");
    }
  }

  //--------------------------------------------------------------------------------------
  //температура
  if (currentMillis_sensor - previousMillis_sensor > interval_sensor)
  {
    previousMillis_sensor = currentMillis_sensor;
    i++;
  }

  //dallas подготовка
  if (i == 1)
  {
    ds.requestTemperatures(); // считываем температуру с датчиков
  }

  //dallas считывание
  if (i == 2)
  {
    if (ds.getTempC(ds_t_out) <= 50) t_out = ds.getTempC(ds_t_out) - 3;
    if (ds.getTempC(ds_t_banya) <= 80) t_banya = ds.getTempC(ds_t_banya);
    i = 0;

    if (t_out != t_out_old)
    {
      itoa(t_out, buff, 10);
      clientMqtt.publish("ihouse/climat/out/temp", buff);
      t_out_old = t_out;
    }

    if (t_banya != t_banya_old)
    {
      itoa(t_banya, buff, 10);
      clientMqtt.publish("ihouse/climat/banya/temp", buff);
      t_banya_old = t_banya;
    }
  }
  
  clientMqtt.loop();
}

благодарю

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

абясни, что у тебя со 152 строки происходит? 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

В коде есть логические бонбы, ищи тогда сам. 

yden
Offline
Зарегистрирован: 30.01.2016

Семен, извините, не мог следить за темой - работа.

Со 152 строки идет подготовка и считывание показаний с ds18b20. Натыкался на мнение, что этот датчик чуть тормознутый. ему нужно дать паузу между подготовкой и непосредственно считыванием. Вот со 152 строки сначала готовим данные, потом их считываем.

Ну чтобы не долбить mqtt одинаковыми значениями температуры, запоминаю значение, при следующем цикле считывания проверяю, если температура изменилась - послать в mqtt.

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну теперь смотрим, что происходит на самом деле

когда i==1

void loop()
{
..
.
.
.
  //--------------------------------------------------------------------------------------
  //температура
  if (currentMillis_sensor - previousMillis_sensor > interval_sensor)  // проверяем, если previousMillis больше interval_sensor
  {
    previousMillis_sensor = currentMillis_sensor;   // запоминаем и делаем i==2
    i++;
  }

//  а если времени прошло меньше, похрен, сёравно пляшем,  выдаем опять команду на конверсию
//  это происходит каждый loop

  if (i == 1)
  {
    ds.requestTemperatures(); // считываем температуру с датчиков
  }

.
.
.
}

дальше продолжать7

yden
Offline
Зарегистрирован: 30.01.2016

DetSimen пишет:

Ну теперь смотрим, что происходит на самом деле

когда i==1

void loop()
{
..
.
.
.
  //--------------------------------------------------------------------------------------
  //температура
  if (currentMillis_sensor - previousMillis_sensor > interval_sensor)  // проверяем, если previousMillis больше interval_sensor
  {
    previousMillis_sensor = currentMillis_sensor;   // запоминаем и делаем i==2
    i++;
  }

//  а если времени прошло меньше, похрен, сёравно пляшем,  выдаем опять команду на конверсию
//  это происходит каждый loop

  if (i == 1)
  {
    ds.requestTemperatures(); // считываем температуру с датчиков
  }

.
.
.
}

дальше продолжать7

Семен, там комментарии неверны. Надо так:

ds.requestTemperatures(); // подготавливаем температуру с датчиков

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Дед тебе пишет, что пока (currentMillis_sensor - previousMillis_sensor > interval_sensor) ардуина будет долбить ежемиллисекундно в шину командами на конверсию. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

yden пишет:

Семен, там комментарии неверны. 

мои - верны. Потомушо это я их написал. 

за твои -нинаю. 

 

yden
Offline
Зарегистрирован: 30.01.2016

sadman41 пишет:

Дед тебе пишет, что пока (currentMillis_sensor - previousMillis_sensor > interval_sensor) ардуина будет долбить ежемиллисекундно в шину командами на конверсию. 

Она выполнив это новое значение previousMillis_sensor принимает:

previousMillis_sensor = currentMillis_sensor;

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

yden пишет:

sadman41 пишет:

Дед тебе пишет, что пока (currentMillis_sensor - previousMillis_sensor > interval_sensor) ардуина будет долбить ежемиллисекундно в шину командами на конверсию. 

Она выполнив это новое значение previousMillis_sensor принимает:

previousMillis_sensor = currentMillis_sensor;

А, ну ладно, тогда. Няхай. 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

yden пишет:

Она выполнив это новое значение previousMillis_sensor принимает:

Ок, чудите с ардуинкой дальше.

astwo
Offline
Зарегистрирован: 10.07.2019

Смотрим строки 055 и059 и не наблюдаем unsigned безнаковой. Для использования millis() это грубая ошибка.

astwo
Offline
Зарегистрирован: 10.07.2019

Враги поставили } на 156 строку.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

astwo пишет:
Враги поставили } на 156 строку.

вот теперь как бы это Дениске обьяснить? 

yden
Offline
Зарегистрирован: 30.01.2016

astwo пишет:
Смотрим строки 055 и059 и не наблюдаем unsigned безнаковой. Для использования millis() это грубая ошибка.

 

можно поподробнее. не знаю это.

сенк

yden
Offline
Зарегистрирован: 30.01.2016

DetSimen пишет:

astwo пишет:
Враги поставили } на 156 строку.

вот теперь как бы это Дениске обьяснить? 

семен, я не считаю себя правым. реально не пойму косяка.

gfx125
Offline
Зарегистрирован: 27.05.2017

yden пишет:

DetSimen пишет:

astwo пишет:
Враги поставили } на 156 строку.

вот теперь как бы это Дениске обьяснить? 

семен, я не считаю себя правым. реально не пойму косяка.

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

#include <OneWire.h>
#include <DallasTemperature.h>
#include <PubSubClient.h>

// =======================================================================
//ds18b20
OneWire oneWire(4); // вход датчиков 18b20
DallasTemperature ds(&oneWire);
DeviceAddress ds_t_out = {0x28, 0xFF, 0x9A, 0x28, 0x72, 0x16, 0x04, 0xA9};
DeviceAddress ds_t_banya = {0x28, 0xFF, 0x91, 0x5C, 0x72, 0x16, 0x05, 0x21};
//DeviceAddress ds_t_banya = {0x28, 0xFF, 0x33, 0xD0, 0x72, 0x16, 0x05, 0x5A};

int t_out;
int t_out_old = 0;
int t_banya;
int t_banya_old = 0;

byte i = 0;

boolean flag_light_banya = false;

char buff[15];

//выходы нагрузки
const byte outPin1 = 5; // свет предбанник

//кнопки
const byte inButton1 = 6; //вход кнопка 

boolean buttonState = false; //состояние выключателя

//подсчет времени
//опрос датчиков
long previousMillis_sensor = 0;  // храним время последнего опроса датчиков
long interval_sensor = 10000;     //интервал

//mqtt broker
long previousMillis_mqtt_connect = 0;  // храним время последнего подключения
long interval_mqtt_connect = 60000;     //интервал
unsigned long currentMillis_mqtt_connect = 0;


void setup()
{
 Serial.begin(9600);
  ds.begin();

  //для релюшек
  pinMode(outPin1, OUTPUT);
  digitalWrite(outPin1, LOW);

  pinMode(inButton1, INPUT_PULLUP);

}

//--------------------------------------------------------------------------------------
void loop()
{
  unsigned long currentMillis_sensor = millis();

  //--------------------------------------------------------------------------------------
  //температура
  if (currentMillis_sensor - previousMillis_sensor > interval_sensor)
  {
    previousMillis_sensor = currentMillis_sensor;
    i++;Serial.println("ogidaem");
  }
  //dallas подготовка
  if (i == 1)
  {Serial.println("gotovim datcheg");
    ds.requestTemperatures(); // считываем температуру с датчиков
  }

  //dallas считывание
  if (i == 2)
  {Serial.println("chitaem temp");
    if (ds.getTempC(ds_t_out) <= 50) t_out = ds.getTempC(ds_t_out) - 3;
    if (ds.getTempC(ds_t_banya) <= 80) t_banya = ds.getTempC(ds_t_banya);
    i = 0;
      }
  
//}
}

а потом запустите его же, но с закомментированной строкой 67 и раскомментированной 82

yden
Offline
Зарегистрирован: 30.01.2016

Все, мужики, понял. Дэбил иваныч. Долбил ардуинку подготовкой датчика.

 

спасибо всем.

yden
Offline
Зарегистрирован: 30.01.2016

А как с этим зверем быть:  unsigned безнаковой

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

long у всего, что хранит интервалы, замени на uint32_t

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

yden пишет:

Все, мужики, понял. 

спасибо всем.

Да ты еще погоди, этот касяк не последний. 

yden
Offline
Зарегистрирован: 30.01.2016

DetSimen пишет:

yden пишет:

Все, мужики, понял. 

спасибо всем.

Да ты еще погоди, этот касяк не последний. 

 

весь во внимании

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ты пока это исправь, проверь и доложи. 

yden
Offline
Зарегистрирован: 30.01.2016

DetSimen пишет:

ты пока это исправь, проверь и доложи. 

у меня таким же шаблоном еще несколько контроллеров работает. везде исправил. пока фурычит.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

и long на uint32_t  исправил?

yden
Offline
Зарегистрирован: 30.01.2016

DetSimen пишет:

и long на uint32_t  исправил?

да

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ну, значить, падаждём. 

astwo
Offline
Зарегистрирован: 10.07.2019

Анекдот. Один случайный человек наблюдал такую картину. Сидит программист за компьютером а потом как вскочет и махая руками с матом начал резво круги возле компьютера наварачивать. О-как выганятся баги из программ. Я тоже кричать и бегать. Пойду в программисты.