Здравствуйте. Столкнулся с проблемой по работе Arduino с внешним устройством по RS485. Мастером в моей цепи выступает некий маршрутизатор с выходом RS485. По протоколу ModbusRtu он отправляет запросы со скоростью 9600 b, 8N2, запросы отправляются командами 0x10 в 2 регистра (2,3). К ардуино так-же подключены мультиплексоры. Принцип работы простой: По модбасу пришло число(0-15), записалось в соответствующий регистр(2 или 3 - первый или второй мультиплексор) и на мультиплексоре выводится значение того порта, номер которого записался в регистр. Имею следующий код: Код (C++): #include <ModbusRtu.h> #define ID 100 // указали адрес модбас слейва int multi1; int multi2; #define EN 3 #define S0 4 #define S1 5 #define S2 6 #define S3 7 int32_t myTimer; Modbus slave(ID, 10, 1); // 100 адрес 1 -485 4- пин int8_t state = 0; unsigned long tempus; uint16_t au16data[9]; // массив регистров word Reg2; //устройство word Reg3; void setup() { Serial.begin(9600); //открываем порт slave.start(); // запуск tempus = millis() + 100; // Сохранить текущее время + 100 мс digitalWrite(13, HIGH ); //светодиод на плате pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); digitalWrite(S0, LOW); digitalWrite(S1, LOW); digitalWrite(S2, LOW); digitalWrite(S3, LOW); pinMode(EN, OUTPUT); digitalWrite(EN, LOW); } void loop() { state = slave.poll( au16data, 9 ); // Параметры: Таблица регистров для обмена информацией // Размер таблицы записей // Возвращает 0, если нет запроса данных // Возвращает от 1 до 4, если произошла ошибка связи // Возвращает больше 4, если заказ был обработан правильно /*if (state == 0) { Serial.println("Нет данных"); } */ if (state <4 && state >0) { Serial.println("ERROR"); } if (state > 4) { //Si es mayor a 4 = el pedido fué correcto tempus = millis() + 50; // Текущее время + 50 мс io_poll(); } if (millis() > tempus) digitalWrite(13, LOW );//гасим через 50 сек // Обновляем выводы Arduino с помощью платы Modbus } void io_poll(){ Reg2=au16data[2]; Reg3=au16data[3]; Serial.print("multiplexor1"); Serial.print("-"); Serial.println(Reg2); delay(100); SetMuxAddress(Reg2); delay(100); } void SetMuxAddress(int address) { digitalWrite(S0, (address >> 0) & 0x1); digitalWrite(S1, (address >> 1) & 0x1); digitalWrite(S2, (address >> 2) & 0x1); digitalWrite(S3, (address >> 2) & 0x1); } Использую Arduino Mega. Подключено все так: Маршрутизатор A - RS485 A; Маршрутизатор B - RS485 B; RS485 RO - Arduino RX(0); RS485 DI - ArduinoTX(1); RS485 DE и RE - Arduino D10; RS485 VCC - Arduino 5v; RS485 GND - Arduino GND; Данная тема так-же обсуждалась на форуме: http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/modbusrtu - можете ответить и в той ветке... Вообще до этого предпринимал изменения библиотеки, тк в ней указана скорость 19200. Думал может в этом дело и поменял значение не 9600. Но на Arduino ru сказали что дело не в этом и я вернул все в исходное положение Спасибо за любой ответ=)
откройте описание библиотеки и посмотрите, какие параметры и в каком порядке указываются в этом конструктуоре: Код (C++): Modbus slave(ID, 10, 1); // 100 адрес 1 -485 4- пин а вот это интересненько : Код (C++): //Si es mayor a 4 = el pedido fué correcto hablas espanol?
Из примера к библиотеке стоит: Код (C++): Modbus slave(ID, Serial, 0); //ID del nodo. 0 para el master, 1-247 para esclavo //Puerto serie (0 = TX: 1 - RX: 0) //Protocolo serie. 0 para RS-232 + USB (default), cualquier pin mayor a 1 para RS-485
Ссылка на библу: https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h Ссылка на пример из библы: https://github.com/smarmengol/Modbu...er/examples/advanced_slave/advanced_slave.ino
тогда я не понимаю. откуда вы взяли что Модбас запускается так: Код (C++): Modbus slave(ID, 10, 1); // 100 адрес 1 -485 4- пин когда в библиотеке четко описано так: Код (C++): Modbus(uint8_t u8id, Stream& port, uint8_t u8txenpin =0); в примеры не смотрите, они могут быть устаревшими и даже быть от другой библиотеки. Развивая библиотеку, авторы часто забывают обновить примеры. так что ситуация. что пример относится к версии 1, а библиотека давно версии 12 - не такая уж редкость. Правильное описание всегда в исходном коде
Хм. Спасибо буду разбираться. 1 - это ID; 2 - это Сериал порт, как я понял; 3 - это что? TX пин? Спасибо за оперативный ответ.
нет, неправильно Я вообще не знаю, что такое "Serial пин", в процитированной мной строчке такого нет: Код (C++): Modbus(uint8_t u8id, Stream& port, uint8_t u8txenpin =0); А пин который вы подключили к DE и RE преобразователя - это TXENpin
Купил новый RS. Все подключил. Скетч такой: Код (C++): #include <ModbusRtu.h> #define ID 100 // указали адрес модбас слейва int multi1; int multi2; #define EN 3 #define S0 4 #define S1 5 #define S2 6 #define S3 7 int32_t myTimer; Modbus slave(ID, Serial1, 10); // 100 адрес 1 -485 4- пин int8_t state = 0; unsigned long tempus; uint16_t au16data[9]; // массив регистров word Reg2; //устройство word Reg3; void setup() { Serial.begin(9600); //открываем порт Serial1.begin(9600); //открываем порт slave.start(); // запуск tempus = millis() + 100; // Сохранить текущее время + 100 мс digitalWrite(13, HIGH ); //светодиод на плате pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); digitalWrite(S0, LOW); digitalWrite(S1, LOW); digitalWrite(S2, LOW); digitalWrite(S3, LOW); pinMode(EN, OUTPUT); digitalWrite(EN, LOW); } void loop() { state = slave.poll( au16data, 9 ); // Параметры: Таблица регистров для обмена информацией // Размер таблицы записей // Возвращает 0, если нет запроса данных // Возвращает от 1 до 4, если произошла ошибка связи // Возвращает больше 4, если заказ был обработан правильно if (state == 0) { Serial.println("Нет данных"); delay(5000); } if (state <4 && state >0) { Serial.println("ERROR"); } if (state > 4) { //Si es mayor a 4 = el pedido fué correcto tempus = millis() + 50; // Текущее время + 50 мс io_poll(); } if (millis() > tempus) digitalWrite(13, LOW );//гасим через 50 сек // Обновляем выводы Arduino с помощью платы Modbus } void io_poll(){ Reg2=au16data[2]; Reg3=au16data[3]; Serial.print("multiplexor1"); Serial.print("-"); Serial.println(Reg2); delay(100); SetMuxAddress(Reg2); delay(100); } void SetMuxAddress(int address) { digitalWrite(S0, (address >> 0) & 0x1); digitalWrite(S1, (address >> 1) & 0x1); digitalWrite(S2, (address >> 2) & 0x1); digitalWrite(S3, (address >> 3) & 0x1); } В Сериал выводит нет данных. Буду проверять мастер устройство.
Код немного поменял: Код (C++): #include <ModbusRtu.h> #define ID 100 // указали адрес модбас слейва int multi1; int multi2; #define EN 3 #define S0 4 #define S1 5 #define S2 6 #define S3 7 int32_t myTimer; Modbus slave(ID, Serial1, 10); // 100 адрес 1 -485 4- пин int8_t state = 0; unsigned long tempus; uint16_t au16data[9]; // массив регистров word Reg2; //устройство word Reg3; void setup() { Serial.begin(9600); //открываем порт Serial1.begin(9600); //открываем порт slave.start(); // запуск tempus = millis() + 100; // Сохранить текущее время + 100 мс digitalWrite(13, HIGH ); //светодиод на плате pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); digitalWrite(S0, LOW); digitalWrite(S1, LOW); digitalWrite(S2, LOW); digitalWrite(S3, LOW); pinMode(EN, OUTPUT); digitalWrite(EN, LOW); } void loop() { state = slave.poll( au16data, 9 ); // Параметры: Таблица регистров для обмена информацией // Размер таблицы записей // Возвращает 0, если нет запроса данных // Возвращает от 1 до 4, если произошла ошибка связи // Возвращает больше 4, если заказ был обработан правильно /*if (state == 0) { Serial.println("Нет данных"); delay(500); } */ if (state <4 && state >0) { Serial.println("ERROR"); } if (state > 4) { //Si es mayor a 4 = el pedido fué correcto tempus = millis() + 50; // Текущее время + 50 мс io_poll(); } if (millis() > tempus) digitalWrite(13, LOW );//гасим через 50 сек // Обновляем выводы Arduino с помощью платы Modbus } void io_poll(){ Reg2=au16data[2]; Reg3=au16data[3]; Serial.print("multiplexor1"); Serial.print("-"); Serial.println(Reg2); delay(100); SetMuxAddress(Reg2); delay(100); } void SetMuxAddress(int address) { digitalWrite(S0, (address >> 0) & 0x1); digitalWrite(S1, (address >> 1) & 0x1); digitalWrite(S2, (address >> 2) & 0x1); digitalWrite(S3, (address >> 3) & 0x1); } Теперь выдает это, хотя от маршрутизатора ничего нет: Код (Text): 14:10:34.642 -> multiplexor1-0 14:10:35.800 -> multiplexor1-0 14:10:36.971 -> multiplexor1-0 14:10:38.095 -> multiplexor1-0 14:10:39.267 -> multiplexor1-0 14:10:40.431 -> multiplexor1-0 14:10:41.549 -> multiplexor1-0 14:10:42.721 -> multiplexor1-0 14:10:43.893 -> multiplexor1-0 14:10:45.017 -> multiplexor1-0 14:10:46.189 -> multiplexor1-0 14:10:47.361 -> multiplexor1-0 Это что получается? Значение State больше 4?
Все - проверил подключение - заработало! Спасибо большое! Не подскажете ,как сделать чтобы выводился только тот регистр, по которому пришла информация? А то у меня в сериал 2 регистра выводятся ! И еще - как мне отправить ответ мастеру? Вот код: Код (C++): #include <ModbusRtu.h> #define ID 100 // указали адрес модбас слейва int multi1; int multi2; #define EN 3 #define S0 4 #define S1 5 #define S2 6 #define S3 7 int32_t myTimer; Modbus slave(ID, Serial1, 10); // 100 адрес 1 -485 4- пин int8_t state = 0; unsigned long tempus; uint16_t au16data[9]; // массив регистров word Reg2; word Reg3; void setup() { Serial.begin(9600); Serial1.begin(9600); //открываем порт slave.start(); // запуск tempus = millis() + 100; digitalWrite(13, HIGH ); pinMode(S0, OUTPUT); pinMode(S1, OUTPUT); pinMode(S2, OUTPUT); pinMode(S3, OUTPUT); digitalWrite(S0, LOW); digitalWrite(S1, LOW); digitalWrite(S2, LOW); digitalWrite(S3, LOW); pinMode(EN, OUTPUT); digitalWrite(EN, LOW); } void loop() { state = slave.poll( au16data, 9 ); // Параметры: Таблица регистров для обмена информацией // Размер таблицы записей // Возвращает 0, если нет запроса данных // Возвращает от 1 до 4, если произошла ошибка связи // Возвращает больше 4, если заказ был обработан правильно /*if (state == 0) { Serial.println("Нет данных"); delay(500); } */ if (state <4 && state >0) { Serial.println("ERROR"); } if (state > 4) { //Si es mayor a 4 = el pedido fué correcto tempus = millis() + 50; // Текущее время + 50 мс } if (millis() > tempus) digitalWrite(13, LOW );//гасим через 50 сек // Обновляем выводы Arduino с помощью платы Modbus io_poll(); } void io_poll(){ // Reg2=au16data[2]; // Reg3=au16data[3]; Serial.print("multiplexor1"); Serial.print("-"); Serial.println(au16data[2]); delay(100); SetMuxAddress(au16data[2]); delay(100); Serial.print("multiplexor2"); Serial.print("-"); Serial.println(au16data[3]); delay(100); SetMuxAddress(au16data[3]); delay(100); } void SetMuxAddress(int address) { digitalWrite(S0, (address >> 0) & 0x1); digitalWrite(S1, (address >> 1) & 0x1); digitalWrite(S2, (address >> 2) & 0x1); digitalWrite(S3, (address >> 3) & 0x1); }