Помогите собрать шлюз для MD. Mqqt<->modbus rtu

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

Модератор: immortal

onestat
Сообщения: 15
Зарегистрирован: Пн фев 26, 2018 9:51 pm
Благодарил (а): 9 раз
Поблагодарили: 0

Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение onestat » Пн фев 26, 2018 9:58 pm

Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Можно на компонентах "ардуино". Или что то готовое. Пересмотрел кучу информации в Интернете, не могу собрать в голове все "до кучи".
Понял что нужно Arduino UNO + w5100 щит (это есть в наличии). Дальше не понимаю, что делать. Каким образом линия rs 485 подключится к Ардуино.
Аватара пользователя
tarasfrompir
Сообщения: 3216
Зарегистрирован: Ср мар 02, 2016 8:18 pm
Откуда: Украина Пирятин
Благодарил (а): 223 раза
Поблагодарили: 815 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение tarasfrompir » Пн фев 26, 2018 10:35 pm

Ну для этого надо преобразователь rs 485 to rs 232 а дальше это как то из дуйки дуть на мажорика... А не проще обычный преобразователь рс 485 то юсб на сервак зацепить ?
Спасибо нам ПОМОЖЕТ..!
onestat
Сообщения: 15
Зарегистрирован: Пн фев 26, 2018 9:51 pm
Благодарил (а): 9 раз
Поблагодарили: 0

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение onestat » Пн фев 26, 2018 10:45 pm

Можно напрямую в rapsberry usb вставить? Мне кажется usb не надежно.
Аватара пользователя
tarasfrompir
Сообщения: 3216
Зарегистрирован: Ср мар 02, 2016 8:18 pm
Откуда: Украина Пирятин
Благодарил (а): 223 раза
Поблагодарили: 815 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение tarasfrompir » Пн фев 26, 2018 10:49 pm

А ты хоть так хоть так получиш данные через юсб хоть с дуньки а хоть с конвертера.
Сунь в распбери - хотя где то здесь читал что тут не все так гладко с линуксом. Вроде не всегда дрова ставятся... Я купил месяц назад но до испытаний ещё не дошёл... :cry: всегда так
Спасибо нам ПОМОЖЕТ..!
onestat
Сообщения: 15
Зарегистрирован: Пн фев 26, 2018 9:51 pm
Благодарил (а): 9 раз
Поблагодарили: 0

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение onestat » Вт фев 27, 2018 12:05 am

Может кто то детально расказать ход действий?
Аватара пользователя
blackangel
Сообщения: 148
Зарегистрирован: Пт окт 21, 2016 2:00 pm
Благодарил (а): 31 раз
Поблагодарили: 13 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение blackangel » Вт фев 27, 2018 12:26 pm

У меня система в квартире работает на модбасе (что то на Ардуино, что то на ПЛК delta), ну и визуализация на RPi MD. Но у меня есть ещё замечательная штука, панель оператора weintek на ней тоже визуализация и самое главное она же шлюз с modbas rtu на modbas tcp. Наверное посоветую тоже поискать шлюз с rtu на tcp так надежнее и правильнее.смотря конечно на чем у вас MD, если на ПК то можно покурить тему скада, и сделать программный шлюз на ПК.
avp8853
Сообщения: 52
Зарегистрирован: Пт июн 09, 2017 8:39 pm
Благодарил (а): 4 раза
Поблагодарили: 1 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение avp8853 » Сб апр 07, 2018 8:48 pm

СпойлерПоказать

Код: Выделить всё

*  avp ot 11/01/2018 02:54
 */

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>   // Modbus RTU pins   D7(13),D8(15) 
#include <ModbusMaster.h>  

#define SUBSCRIBETOPIC "/modbusDetscie/termostat/#"  // топик на который подписываемся
#define PUBLISHTOPIC1 "/modbusDetscie/termostat/status" // первый публикуемый топик значения 90/165 включение/отключения термостата
#define PUBLISHTOPIC2 "/modbusDetscie/termostat/taimer" //  публикуемый топик значения 0/1 включение/отключения термостата в ручную или по таймеру
#define PUBLISHTOPIC3 "/modbusDetscie/termostat/tempDatchkPol" // публикуемый топик внешний датчик температуры пол
#define PUBLISHTOPIC4 "/modbusDetscie/termostat/tempDatchkWnech" // публикуемый топик температура в помещении 
#define PUBLISHTOPIC5 "/modbusDetscie/termostat/tempUstan" // публикуемый топик температура установленная на термостате умножить на 2
#define PUBLISHTOPIC6 "/modbusDetscie/termostat/timeM" //  публикуемый топик время в минутах на термостате
#define PUBLISHTOPIC7 "/modbusDetscie/termostat/timeH" //  публикуемый топик время в часах на термостате
#define PUBLISHTOPIC8 "/modbusDetscie/termostat/DniNedeli" //  публикуемый топик день недели с 1 до 7
#define PUBLISHTOPIC9 "/modbusDetscie/termostat/send_interval" //  публикуемый топик интервал отправки данных

#define IDDEVAIS 1            // Адрес MODBUS девайса
#define COLTOPIC 8           // Кол-во элементов для чтения и записи/передаваемых и принемаемых топиков

#define MAX485_DE_RE 12
//#define BUFFER_SIZE 120

WiFiClient espClient;
PubSubClient client_MQTT (espClient);
SoftwareSerial swSer(13, 15, false, 256);
//SoftwareSerial swSer(13, 15);
// Instantiate ModbusMaster object as slave ID 1
ModbusMaster node;

const char* ssid =        "Network_Bel";
const char* password =    "123456789";
const char* mqtt_server = "192.168.1.80";   /// example 192.168.0.19
int mqtt_port            = 1883;
unsigned int tdelay = 2 ; /// delay
  
String Holding_to_MQTT[COLTOPIC];
String MQTT_to_Holding[COLTOPIC];   // Array recepcion valores MQTT // Array reception MQTT values

unsigned int send_interval = 100;   //интервал отправки показаний на сервер по-умолчанию 100 секунд
unsigned long last_time = 0;        //текущее время для таймера
unsigned long last_time_pyat = 0;   //текущее время для таймера

unsigned int adres0Status;                  // переменная для считывания данных статуса
unsigned int adres0Status2;                 // переменная для сравнения  данных статуса
unsigned int adres4Val;
unsigned int adres5Val;
unsigned int adres6Val;
unsigned int adres7Val;

//bool val0adres;
bool time0,time1,time2,time3,time4,time5,time6,time7;

void preTransmission()
{
  digitalWrite(MAX485_DE_RE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_DE_RE, 0);
}



/*
 * 
 * Funcion que realiza la reconexion de cliente MQTT
 * Function that performs MQTT client reconnection
 * 
 * enable/habilita  client_MQTT.subscribe("MQTT_Holding_Array");
 */
void reconnect(void)
{  
  // Loop until we're reconnected  // Bucle hasta que se vuelva a conectar
  while (!client_MQTT.connected()) {  
    if (client_MQTT.connect("ESP8266ModbusDetscie")) {
       Serial.println("MQTT Online");        
      //// Topico para recibir Holding Registers desde MQTT // Topic to receive Holding Registers from MQTT --- return data in callback funtion
      client_MQTT.subscribe(SUBSCRIBETOPIC);          
    } else {
      //Serial.print("failed, rc=");
      //Serial.print(client_MQTT.state());    
    }
  }
}

void callback(char* topic, byte* payload, unsigned int length)
{	
    for (int i = 0; i < COLTOPIC; i++) {MQTT_to_Holding[i]="";}  //limpia cadenas recibidas // Cleans received strings
	//преобразуем тему(topic) и значение (payload) в строку
  payload[length] = '\0';
  String strTopic = String(topic);
  String strPayload = String((char*)payload);
  unsigned int tmp = strPayload.toInt();
  //Исследуем что "прилетело" от сервера по подписке: 
    if(strTopic == PUBLISHTOPIC1){ // значения 90/165 включение/отключения термостата 
	    if(tmp == 90 || tmp == 165){           			
			   MQTT_to_Holding[0] += String((char*)payload);   // адрес 40001
	    }			
	}	   
    else if(strTopic == PUBLISHTOPIC5){ // публикуемый топик температура установленная на термостате умножить на 2
            if(tmp > 20 && tmp < 64){
			         MQTT_to_Holding[4] += String((char*)payload);       // адрес 40005
			}
	} 
    else if(strTopic == PUBLISHTOPIC6){ // публикуемый топик время в минутах на термостате 
            if(tmp > 0 && tmp < 60){
				MQTT_to_Holding[5] += String((char*)payload);            // адрес 40006
			}
	}
    else if(strTopic == PUBLISHTOPIC7){ // публикуемый топик время в часах на термостате
            if(tmp >= 0 && tmp < 24){
				MQTT_to_Holding[6] += String((char*)payload);     // адрес 40007
			}
	}
    else if(strTopic == PUBLISHTOPIC8){ // публикуемый топик день недели с 1 до 7 на термостате
            if(tmp > 0 && tmp < 8){
				MQTT_to_Holding[7] += String((char*)payload);      // адрес 40008
			}
	}		  
    else if(strTopic == PUBLISHTOPIC9){ //Изменение интервала опроса
			if(tmp == 0) {
			    send_interval = 100;
			}else{ send_interval = strPayload.toInt();}
	} 
	   //Serial.print("topic [");
	   //Serial.print(topic); 
	   //Serial.print("-");     
	   //Serial.print(tmp);
	   //Serial.println("] ");
	   //Serial.println(chipId);   
}	

void loopPublishMQTTclientRegistr0(void)   // функция обработки 0 регистра статус
{
   bool to_MQTT0 = 0;
   bool to_TIME0 = 0;
   char  buf0[10];   
   
   if(millis() > (last_time_pyat + 20*1000)){                  // Прочитываем регистер каждые 5 секунд на предмет изменений статуса
      node.readHoldingRegisters(0, 1);                          // Адрес регистра 40001, Кол-во элементов 1  
      adres0Status = String(node.getResponseBuffer(0)).toInt();       
      node.clearResponseBuffer();                               /// Limpiar buffer modbus RTU     /// Clean modbus RTU buffer         
        if(adres0Status != adres0Status2){
		   adres0Status2 = adres0Status;
		   to_TIME0 = 1;               
	    } 
      last_time_pyat = millis();
    }   
    if(MQTT_to_Holding[0].toInt() == 90 || MQTT_to_Holding[0].toInt() == 165){
	    if(adres0Status != MQTT_to_Holding[0].toInt()){
		   node.writeSingleRegister(0, MQTT_to_Holding[0].toInt() );	
           delay(10);	
		   to_MQTT0 = 1;
	    }
    }
	if(time0 || to_MQTT0 || to_TIME0){                      // если подошло время time0 или чтото прилетело в топик или поменялось значение
       node.readHoldingRegisters(0, 1);                          // Адрес регистра 40001, Кол-во элементов 1
       adres0Status = String(node.getResponseBuffer(0)).toInt();	   
        if(adres0Status){     
          String(node.getResponseBuffer(0)).toCharArray(buf0, sizeof(buf0));   /// String a char para mensaje MQTT  /// String to char for MQTT message          
          client_MQTT.publish(PUBLISHTOPIC1,buf0);          
          time0 = 0;	
       }
       node.clearResponseBuffer();
       delay(tdelay);        
    }    
}
// публикуемый топик температура установленная на термостате
void loopPublishMQTTclientRegistr4(void) // функция обработки 4 регистра установленная температура
{
    bool to_MQTT4 = 0;
    char  buf4[10];    
       
    if(MQTT_to_Holding[4].toInt() > 30 && MQTT_to_Holding[4].toInt() < 65){
        if(adres4Val != MQTT_to_Holding[4].toInt()){
           node.writeSingleRegister(4, MQTT_to_Holding[4].toInt());
           delay(10);   
           //Serial.print("adres4Val-"); Serial.println(adres4Val);
           //Serial.print("MQTT_to_Holding[4].toInt()-"); Serial.println(MQTT_to_Holding[4].toInt());
            //MQTT_to_Holding[4] = "";
           to_MQTT4 = 1;
        }
    }    
    if(time4 || to_MQTT4){                      // если подошло время time0 или чтото прилетело в топик или поменялось значение
       node.readHoldingRegisters(4, 1);                          // Адрес регистра 40004, Кол-во элементов 1 
       adres4Val = String(node.getResponseBuffer(0)).toInt();     
        if(adres4Val){    
          String(node.getResponseBuffer(0)).toCharArray(buf4, sizeof(buf4));   /// String a char para mensaje MQTT  /// String to char for MQTT message          
          client_MQTT.publish(PUBLISHTOPIC5,buf4);       
          time4 = 0;
        }
       node.clearResponseBuffer(); 
       delay(tdelay);        
    }    
}

void loopPublishMQTTclientRegistr5(void) // функция обработки 5 регистра время минуты
{
    bool to_MQTT5 = 0;
    char  buf5[10];    
       
    if(MQTT_to_Holding[5].toInt() > 0 && MQTT_to_Holding[5].toInt() < 60){
        if(adres5Val != MQTT_to_Holding[5].toInt()){
           node.writeSingleRegister(5, MQTT_to_Holding[5].toInt());
           delay(10);   
           //Serial.print("adres5Val-"); Serial.println(adres5Val);
           //Serial.print("MQTT_to_Holding[5].toInt()-"); Serial.println(MQTT_to_Holding[5].toInt());
           to_MQTT5 = 1;
        }
    }    
    if(time5 || to_MQTT5){                      // если подошло время time0 или чтото прилетело в топик или поменялось значение
       node.readHoldingRegisters(5, 1);                          // Адрес регистра 40006, Кол-во элементов 1 
       adres5Val = String(node.getResponseBuffer(0)).toInt();     
        if(adres5Val){    
           String(node.getResponseBuffer(0)).toCharArray(buf5, sizeof(buf5));   /// String a char para mensaje MQTT  /// String to char for MQTT message           
           client_MQTT.publish(PUBLISHTOPIC6,buf5);       
           time5 = 0;
       }
       node.clearResponseBuffer(); 
       delay(tdelay);        
    }    
}

void loopPublishMQTTclientRegistr6(void) // функция обработки 6 регистра время часы
{
    bool to_MQTT6 = 0;
    char  buf6[10];    
       
    if(MQTT_to_Holding[6].toInt() > 0 && MQTT_to_Holding[6].toInt() < 24){
        if(adres6Val != MQTT_to_Holding[6].toInt()){
           node.writeSingleRegister(6, MQTT_to_Holding[6].toInt());
           delay(10);   
           //Serial.print("adres6Val-"); Serial.println(adres6Val);
           //Serial.print("MQTT_to_Holding[6].toInt()-"); Serial.println(MQTT_to_Holding[6].toInt());
           to_MQTT6 = 1;
        }
    }    
    if(time6 || to_MQTT6){                      // усли подошло время time0 или чтото прилетело в топик или поменялось значение
       node.readHoldingRegisters(6, 1);                          // Адрес регистра 40007, Кол-во элементов 1 
       adres6Val = String(node.getResponseBuffer(0)).toInt();     
        if(adres6Val){    
          String(node.getResponseBuffer(0)).toCharArray(buf6, sizeof(buf6));   /// String a char para mensaje MQTT  /// String to char for MQTT message          
          client_MQTT.publish(PUBLISHTOPIC7,buf6);       
          time6 = 0;
       }
       node.clearResponseBuffer(); 
       delay(tdelay);        
    }    
}

void loopPublishMQTTclientRegistr7(void) // функция обработки 7 регистра дни недели
{
    bool to_MQTT7 = 0;
    char  buf7[10];    
       
    if(MQTT_to_Holding[7].toInt() > 0 && MQTT_to_Holding[7].toInt() < 8){
        if(adres7Val != MQTT_to_Holding[7].toInt()){
           node.writeSingleRegister(7, MQTT_to_Holding[7].toInt());
           delay(10);            
           to_MQTT7 = 1;
        }
    }    
    if(time7 || to_MQTT7){                      // усли подошло время time0 или чтото прилетело в топик или поменялось значение
       node.readHoldingRegisters(7, 1);                          // Адрес регистра 40008, Кол-во элементов 1 
       adres7Val = String(node.getResponseBuffer(0)).toInt();     
        if(adres7Val){    
          String(node.getResponseBuffer(0)).toCharArray(buf7, sizeof(buf7));   /// String a char para mensaje MQTT  /// String to char for MQTT message          
          client_MQTT.publish(PUBLISHTOPIC8,buf7);       
          time7 = 0;
       }
       node.clearResponseBuffer(); 
       delay(tdelay);        
    }    
}

void loopPublishMQTTclient(void)
{	  
    bool to_MQTT1,to_MQTT2,to_MQTT3;
    char  buf[10];  
	
    if(time1){
       node.readHoldingRegisters(1, 1);                          // Адрес регистра 40002, Кол-во элементов 1
       //Serial.print("[1] ");
       //Serial.print(node.getResponseBuffer(0));
       String(node.getResponseBuffer(0)).toCharArray(buf, sizeof(buf));   /// String a char para mensaje MQTT  /// String to char for MQTT message       
       client_MQTT.publish(PUBLISHTOPIC2,buf);
       node.clearResponseBuffer();                               /// Limpiar buffer modbus RTU     /// Clean modbus RTU buffer       
       time1=0;  
       delay(tdelay);         
    }
	else if(time2){                                                // публикуемый топик внешний датчик температуры пол
       node.readHoldingRegisters(2, 1);                          // Адрес регистра 40003, Кол-во элементов 1 
       //Serial.print("[2] ");
       //Serial.print(node.getResponseBuffer(0));
       String(node.getResponseBuffer(0)/2).toCharArray(buf, sizeof(buf));   /// String a char para mensaje MQTT  /// String to char for MQTT message       
       client_MQTT.publish(PUBLISHTOPIC3,buf);
       node.clearResponseBuffer();                               /// Limpiar buffer modbus RTU     /// Clean modbus RTU buffer       
       time2=0;
       delay(tdelay);       
    }
	else if(time3){                                                //публикуемый топик внешний датчик температуры пол
       node.readHoldingRegisters(3, 1);                          // Адрес регистра 40004, Кол-во элементов 1
       //Serial.print("[3] ");
       //Serial.print(node.getResponseBuffer(0));
       String(node.getResponseBuffer(0)/2).toCharArray(buf, sizeof(buf));   /// String a char para mensaje MQTT  /// String to char for MQTT message       
       client_MQTT.publish(PUBLISHTOPIC4,buf);
       node.clearResponseBuffer();                               /// Limpiar buffer modbus RTU     /// Clean modbus RTU buffer       
       time3=0;
       delay(tdelay);        
    }    
}

void looplast_time(void)   // интервал публикации топиков
{
    if(millis() > (last_time + send_interval*1000)){       
       time0 = 1; time1 = 1;
       time2 = 1; time3 = 1;
       time4 = 1; time5 = 1;
       time6 = 1; time7 = 1;
	   last_time = millis();         	 
    }	
}

void setup(void)
{
   pinMode(MAX485_DE_RE, OUTPUT);
   // Init in receive mode
   digitalWrite(MAX485_DE_RE, 0);
  
   Serial.begin(9600);
   delay(100); 
   swSer.begin(9600); 
   node.begin(IDDEVAIS, swSer);
   // Callbacks allow us to configure the RS485 transceiver correctly
   node.preTransmission(preTransmission);
   node.postTransmission(postTransmission);
   delay(100);  
   WiFi.mode(WIFI_STA);   
   WiFi.begin(ssid, password);
   client_MQTT.setServer(mqtt_server, mqtt_port);
   client_MQTT.setCallback(callback);
   delay(100);  
   while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    //Serial.println("Connection Failed! Rebooting...");
   delay(5000);
   ESP.restart();
  }
  // No authentication by default
   //ArduinoOTA.setPassword((const char *)"123");
  
  ArduinoOTA.onStart([]() {
    //Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    //Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    /*
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
    */
  });
  ArduinoOTA.begin();
  //Serial.println("Ready");
  //Serial.print("IP address: ");
  //Serial.println(WiFi.localIP());
}

void loop(void)
{
	ArduinoOTA.handle();
	if (!client_MQTT.connected()) {            
         reconnect();         /// reconection MQTT
    } 
    //Проверка входящих соединений по подписке                          
      client_MQTT.loop();
   // интервал публикации топиков
     looplast_time();  	   
  // Публикуем топики
     loopPublishMQTTclient();
     loopPublishMQTTclientRegistr0();     
     loopPublishMQTTclientRegistr4();    
     loopPublishMQTTclientRegistr5();    
	 loopPublishMQTTclientRegistr6();   // функция обработки 6 регистра время часы   
     loopPublishMQTTclientRegistr7();   // функция обработки 7 регистра дни недели      
}
avp8853
Сообщения: 52
Зарегистрирован: Пт июн 09, 2017 8:39 pm
Благодарил (а): 4 раза
Поблагодарили: 1 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение avp8853 » Сб апр 07, 2018 8:51 pm

У меня так работает, единственное в библиотеку <ModbusMaster.h> нужно внести изменения
// Modbus timeout [milliseconds]
static const uint16_t ku16MBResponseTimeout = 2000; ///< Modbus timeout [milliseconds]
поменять на
// Modbus timeout [milliseconds]
static const uint16_t ku16MBResponseTimeout = 200; ///< Modbus timeout [milliseconds]
Aven
Сообщения: 529
Зарегистрирован: Сб мар 12, 2016 6:33 pm
Откуда: Ухта, Россия
Благодарил (а): 3 раза
Поблагодарили: 154 раза

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение Aven » Вс апр 08, 2018 1:34 am

есть программный шлюз mbus.
odinvolk
Сообщения: 52
Зарегистрирован: Ср май 31, 2017 3:06 am
Откуда: odinwolk@gmail.com
Благодарил (а): 191 раз
Поблагодарили: 18 раз

Re: Помогите собрать шлюз для MD. Mqqt<->modbus rtu

Сообщение odinvolk » Вс апр 08, 2018 4:01 am

посмотри здесь http://ns1.okbit.ru
Connect ---- Telegram
Яндекс.Деньги для благодарностей за помощь или нажмите кнопку "Спасибо"!!!
Ответить