Modbus + RS485 = связь в одну сторону

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

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

Прошу помощи сообщества, плиз. Уже не один день бьюсь. Modbus RTU и RS485.

Суть: собрал стенд из 2 нано - мастер и слейв. Соединены они через конвертер max485 ttl rs485. К мастеру подключены часы, к слейву - tm1637.

Мастер должен передать значения часы и минуты, слейв должен вывести их на экран и передать мастеру случайное 0 или 1, мастер в зависимости от того какое рандомное число пришло от слейва зажечь или погасить 13 пин.

Что имею: обе ардуинки разговаривают. Но связь односторонняя. Мастер инициирует передачу. От слейва приходит рандомное число, на которое мастер реагирует 13 пином. Но время не уходит слейву. Причем если после перезагрузки мастера отключить управляющий пин конвертера на стороне мастера, то время на слейв улетает и отображается на экране, но далее соответственно передача останавливается.

Что-то в библиотеке или в коде, что не переключает режимы tx\rx. Другой библиотекой и кодом пробовал - идет.

В чем может быть загвоздка, подскажите полиз.

Библиотеки: SimpleModbusMasterV2rev2_lib.zip и SimpleModbusSlaveV10_lib.zip

Благодарю.

Мастер:

#include <SimpleModbusMaster.h>
#include <iarduino_RTC.h>

iarduino_RTC time(RTC_DS3231);

//////////////////// Макроопределения портов и настройки программы  ///////////////////
#define baud        9600 // скоростьобмена по последовательному интерфейсу. (UART)
#define timeout     1000 // Длительность ожидание ответа (таймаут modbus)
#define polling     100  // скорость опроса по modbus
#define retry_count 10   // количесво запросов modbus до ошибки и останова обмена
#define TxEnablePin 4    // Tx/Rx пин RS485
#define LED1        13    // светодиод 1

#define TOTAL_NO_OF_REGISTERS 4

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  TOTAL_NO_OF_PACKETS // эту строку неменять
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
  time.begin();
// Настраиваем пакеты
// Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
// помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg
 
// Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0); // чтение данных slave-master (slave адрес 1, регистр 0)
modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 1, 1, 1); // чтение данных slave-master (slave адрес 1, регистр 1)
// Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 2, 1, 2); // запись данных master-slave (slave адрес 1, регистр 2)
modbus_construct(&packets[PACKET4], 1, PRESET_MULTIPLE_REGISTERS, 3, 1, 3); // запись данных master-slave (slave адрес 1, регистр 3)
// инициализируем протокол модбус
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 
pinMode(LED1, OUTPUT);

} // конец void setup()

void loop()
{
  time.gettime();
  
  modbus_update(); // запуск обмена по Modbus

  regs[2] = time.hours; // запись данных master-slave (slave адрес 1, регистр 2), запись константы
  regs[3] = time.minutes;
  
  if (regs[0] == 1)
 {
  digitalWrite(LED1, HIGH);   
 }
 else
 {
  digitalWrite(LED1, LOW);
 }
  
} // конец void loop()/*
   

Слейв:

#include <SimpleModbusSlave.h>
#include "TM1637.h"

#define CLK 6           // CLK -> pin D6
#define DIO 5           // DIO -> pin D5
TM1637 tm1637(CLK, DIO); // Семи сегментный индикатор, модуль на TM1637
#define brightness 7  // яркость индикатора, от 0 до 1

int8_t TimeDisp[4];

//////////////////// Макроопределения портов и настройки программы  ///////////////////
#define TxEnablePin  4	   // Tx/Rx пин RS485
#define baud         9600  // скоростьобмена по последовательному интерфейсу. (UART)
#define Slave_ID     1     // Адрес Slave устройсва
#define LED1         13    // светодиод 1

//////////////// Регистры вашего Slave ///////////////////
enum
{
  //Просто добавьте или удалите регистры. Первый регистр начинается по адресу 0
  reg_0,          //  с адресом массива 0
  reg_1,          //  с адресом массива 1
  reg_2,          //  с адресом массива 2
  reg_3,          //  с адресом массива 3
  HOLDING_REGS_SIZE // Это не удалять размер массива HOLDING_REGS.
  //общее количество регистров для функции 3 и 16 разделяет тотже самый массив регистров
  //т.е. то же самое адресное пространство
};
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // функции 3 и 16 массив регистров
////////////////////////////////////////////////////////////

void setup()
{
  tm1637.init();           // инициализируем индикатор
  tm1637.set(brightness);  // включаем подсветку индикатора
  tm1637.point(POINT_ON);  // включаем точки

  modbus_configure(&Serial, baud, SERIAL_8N2, Slave_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(9600, SERIAL_8N2, 1);

  pinMode(LED1, OUTPUT);
  
}// конец void setup()

void loop()
{

  modbus_update(); // запуск обмена по Modbus

  holdingRegs[reg_0] = random(2); 
  holdingRegs[reg_1] = 3; 
  
  if (holdingRegs[reg_2] == 0)
  {
    digitalWrite(LED1, LOW);
  }
  else
  {
    digitalWrite(LED1, HIGH);
  }

  TimeDisp[0] = holdingRegs[reg_2];
  TimeDisp[1] = holdingRegs[reg_2];
  TimeDisp[2] = holdingRegs[reg_3] / 10;
  TimeDisp[3] = holdingRegs[reg_3] % 10;

  tm1637.display(TimeDisp); // воводим на индикатор

}// конец 




/*
   Использование enum инструкции не обязательно. Вы могли установить допустимый максимум
   размер для holdinRegs [], определяя HOLDING_REGS_SIZE, используя константу и затем доступ
   holdingRegs[] обращением по "Index" массива.
   holdingRegs[0] = analogRead(A0);
   analogWrite(LED, holdingRegs[1]/4);
   holdingRegs[ADC_VAL] = 250;                // данные об обновлении, которые будут прочитаны владельцем, чтобы приспособить PWM ШИМ
   analogWrite(LED, holdingRegs[PWM_VAL]>>2); // ограничьте АЦП arduino значением 255
   holdingRegs[ADC_VAL] = holdingRegs[PWM_VAL];
*/

 

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

Заговорили.

Поменял конвертер.