Здравствуйте. Прошу помощи, плиз. Есть 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 передавалось в слейв и обратно. Если не трудно покажите мою ошибку, очень нужно. Благодарю
Немного изменил код. Мастер: Код (C++): /* Пример будет использовать packet1, чтобы считать регистр из адреса 0 (значение adc ch0) от arduino раба (id=1). Это будет тогда использовать это значение, чтобы скорректировать яркость из вовлеченного контакт 9 использований PWM. Это будет тогда использовать packet2, чтобы записать регистр (его собственное значение adc ch0), чтобы адресоваться 1 на arduino рабе (id=1) корректировка яркости вовлеченного контакт 9 использований PWM. */ #include <SimpleModbusMaster.h> //////////////////// Макроопределения портов и настройки программы /////////////////// #define baud 9600 // скоростьобмена по последовательному интерфейсу. (UART) #define timeout 1000 // Длительность ожидание ответа (таймаут modbus) #define polling 300 // скорость опроса по 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] = 20; // запись данных master-slave (slave адрес 1, регистр 2), запись константы regs[3] = 20; if (regs[0] == 30) { digitalWrite(LED1, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED1, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } else { digitalWrite(LED1, HIGH); // turn the LED on (HIGH is the voltage level) delay(250); // wait for a second digitalWrite(LED1, LOW); // turn the LED off by making the voltage LOW delay(250); } } // конец void loop()/* Слейв: Код (C++): #include <SimpleModbusSlave.h> //////////////////// Макроопределения портов и настройки программы /////////////////// #define TxEnablePin 2 // Tx/Rx пин RS485 #define baud 9600 // скоростьобмена по последовательному интерфейсу. (UART) #define timeout 1000 // Длительность ожидание ответа (таймаут modbus) #define polling 300 // скорость опроса по 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); digitalWrite(LED1, LOW); }// конец void setup() void loop() { int temp; temp=30; 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. по нажатию кнопки. if (holdingRegs[master_to_slave_val_2] == 20) { digitalWrite(LED1, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED1, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } else { digitalWrite(LED1, HIGH); // turn the LED on (HIGH is the voltage level) delay(250); // wait for a second digitalWrite(LED1, LOW); // turn the LED off by making the voltage LOW delay(250); } //Serial.println(holdingRegs[master_to_slave_val_2]); }// конец void loop() Суть: мастер передает число 20 слейву. Если это число получено, то мигаем 13 пином раз в секунду, если нет такого числа - мигает в 4 раза чаще. И в свою очередь слейв должен ответить мастеру, послав число 30. Если такое число получено\неполучено выполняется аналогичный сценарий с миганием светика. Итог - ни мастер ни слейв ничего не шлет. Подскажите плиз, где я не прав.
Попробовал соеднить по этой схеме: http://arrduinolab.blogspot.ru/2015/02/arduino-rs485-2.html Ардуинки заговорили. Но мне нужен modbus. На буржуйском форуме рекомендовали притянуть 10к резистором rx к vcc. Сделал, все так же, молчат. В сериал слейва появляется значение 8L, в мастере - ромбики.