Modbus, rs485, не хотят разговаривать
- Войдите на сайт для отправки комментариев
Пт, 17/02/2017 - 21:39
Здравствуйте.
Прошу помощи, плиз. Есть 2 arduino nano, 2 конвертера rs485, испытательный стенд передачи информации между ардуинками используя modbus. Схема соединения - из интернета. Использую библиотеки SimpleModbusSlave.h и SimpleModbusMaster.h, так же примеры этих библиотек.
master:
Код (C++):
#include <SimpleModbusMaster.h>
//////////////////// Макроопределения портов и настройки программы ///////////////////
#define baud 9600 // скоростьобмена по последовательному интерфейсу. (UART)
#define timeout 1000 // Длительность ожидание ответа (таймаут modbus)
#define polling 200 // скорость опроса по modbus
#define retry_count 10 // количесво запросов modbus до ошибки и останова обмена
#define TxEnablePin 2 // Tx/Rx пин RS485
#define LED1 13 // светодиод 1
// Общая сумма доступной памяти на master устройстве, для хранения данных
// не забудьте изменить макроопределение TOTAL_NO_OF_REGISTERS. Если из слейва
// запрашиваешь 4 регистра, то тогда в массиве reg должно быть не меньше 4х ячеек
// для хранения полученных данных.
#define TOTAL_NO_OF_REGISTERS 4
// Масив пакетов modbus
// Для добавления новых пакетов просто добавте ихсюда
// сколько вам нужно.
enum
{
PACKET1,
PACKET2,
PACKET3,
PACKET4,
TOTAL_NO_OF_PACKETS // эту строку неменять
};
// Масив пакетов модбус
Packet packets[TOTAL_NO_OF_PACKETS];
// Массив хранения содержимого принятых и передающихся регистров
unsigned int regs[TOTAL_NO_OF_REGISTERS];
void setup()
{
Serial.begin(9600);
// Настраиваем пакеты
// Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
// помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив 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_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
pinMode(LED1, OUTPUT);
} // конец void setup()
void loop()
{
modbus_update(); // запуск обмена по Modbus
Serial.println(regs[0]);
regs[2] = 255; // запись данных master-slave (slave адрес 1, регистр 2), запись константы
} // конец void loop()/*
slave:
Код (C++):
#include <SimpleModbusSlave.h>
//////////////////// Макроопределения портов и настройки программы ///////////////////
#define TxEnablePin 2 // Tx/Rx пин RS485
#define baud 9600 // скоростьобмена по последовательному интерфейсу. (UART)
#define timeout 1000 // Длительность ожидание ответа (таймаут modbus)
#define polling 200 // скорость опроса по modbus
#define retry_count 10 // количесво запросов modbus до ошибки и останова обмена
#define Slave_ID 1 // Адрес Slave устройсва
#define LED1 13 // светодиод 1
//const int buttonPin = 3; // номер входа, подключенный к кнопке
// переменные
int buttonState = 0; // переменная для хранения состояния кнопки
//////////////// Регистры вашего Slave ///////////////////
enum
{
//Просто добавьте или удалите регистры. Первый регистр начинается по адресу 0
slave_to_master_val_1, // с адресом массива 0
slave_to_master_val_2, // с адресом массива 1
master_to_slave_val_1, // с адресом массива 2
master_to_slave_val_2, // с адресом массива 3
HOLDING_REGS_SIZE // Это не удалять размер массива HOLDING_REGS.
//общее количество регистров для функции 3 и 16 разделяет тотже самый массив регистров
//т.е. то же самое адресное пространство
};
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // функции 3 и 16 массив регистров
////////////////////////////////////////////////////////////
void setup()
{
/* parameters(HardwareSerial* SerialPort,long baudrate,unsigned char byteFormat,unsigned char ID,
unsigned char transmit enable pin,unsigned int holding registers size,unsigned int* holding register array)
SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
SERIAL_8N1 option
*/
Serial.begin(9600);
modbus_configure(&Serial, baud, SERIAL_8N1, Slave_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(baud, SERIAL_8N1, 1);
pinMode(LED1, OUTPUT);
}// конец void setup()
void loop()
{
int temp;
temp=255;
modbus_update(); // запуск обмена по Modbus
holdingRegs[slave_to_master_val_1] = temp; // запись данных slave-master
// (регистр 0), значение из аналогового входа 0.
holdingRegs[slave_to_master_val_2] = temp; // запись данных slave-master
// (регистр 1), запись значения переменной temp. по нажатию кнопки.
Serial.println(holdingRegs[master_to_slave_val_2]);
}// конец void loop()
Соответственно все это хозяйство собрано на столе. Подключаю модули, поочередно смотрю serial монитор.
У мастера регистры reg0 и reg1 в мониторе выводит 0. Мастер записывает в регистры (для слейва) reg2 числовое значение 255 - в мастере в мониторе оно видно.
У слейва регистры от мастера так же равны 0. Регистры слейва принимают значение 255 - соответвенно видны в сериал.
Что хочу - число 255 передавалось в слейв и обратно.
Если не трудно покажите мою ошибку, очень нужно.
Благодарю
А почитать форум? не? Тем же полно. Вот здесь несколько дней боролись и победили.
https://www.arduino.ru/forum/programmirovanie/modbus-rtu
И да, прочитайте как правильно вставлять код. Есть спец. тема.
Читал я форум, и не один, и не одну тему. Темный лес. А ссылку, выше постом, я вообще как настольную книгу использую - из нее и брал используемые библиотеки и примеры.
Немного изменил код.
Мастер:
Слейв:
Суть: мастер передает число 20 слейву. Если это число получено, то мигаем 13 пином раз в секунду, если нет такого числа - мигает в 4 раза чаще. И в свою очередь слейв должен ответить мастеру, послав число 30. Если такое число получено\неполучено выполняется аналогичный сценарий с миганием светика.
Итог - ни мастер ни слейв ничего не шлет.
Подскажите плиз, где я не прав.
Попробовал соеднить по этой схеме: http://arrduinolab.blogspot.ru/2015/02/arduino-rs485-2.html
Ардуинки заговорили. Но мне нужен modbus.
На буржуйском форуме рекомендовали притянуть 10к резистором rx к vcc. Сделал, все так же, молчат.
В сериал слейва появляется значение 8L, в мастере - ромбики.