RS-485 на Ардуино
RS-485 на Ардуино
Здравствуйте!
Помогите пожалуйста! Я только начал работать с Ардуино... И передо мной стоит следующая задача... реализовать протокол связи между двумя Ардуино Мега 2560 или Уно по принципу мастер-подчиненный. Обшарил весь интернет везде описаны различные вспомагательные библиотеки и нигде практически нет комментариев на этот счет...(
Мне всего то нужно прописать чтение данных и отправку с проверкой контрольной суммы, короче говоря именно по протоколу
Помогите пожалуйста! Я только начал работать с Ардуино... И передо мной стоит следующая задача... реализовать протокол связи между двумя Ардуино Мега 2560 или Уно по принципу мастер-подчиненный. Обшарил весь интернет везде описаны различные вспомагательные библиотеки и нигде практически нет комментариев на этот счет...(
Мне всего то нужно прописать чтение данных и отправку с проверкой контрольной суммы, короче говоря именно по протоколу
- Mr.Kubikus
- Сотрудник ПАКПАК
- Сообщения: 1020
- Зарегистрирован: 22 окт 2010, 23:57
Re: RS-485 на Ардуино
Привет!
Не могли бы вы более подробно описать протокол, который вы хотите реализовать?
Давайте договоримся, что у вас есть два устройства Arduino c драйвером RS485. Ведущее устройство (мастер) обозначим как М, а подчиненное (слейв) как S. Опишите, пожалуйста:
* Какой будет характер взаимодействия устройство: команды, данные или и то и другое?
* Если команды, то сколько их будет?
* Если данные, то в какую сторону они передаются - от M к S или от S к M?
Чем подробнее вы распишите вашу задачу, тем проще будет найти решение!
Не могли бы вы более подробно описать протокол, который вы хотите реализовать?
Давайте договоримся, что у вас есть два устройства Arduino c драйвером RS485. Ведущее устройство (мастер) обозначим как М, а подчиненное (слейв) как S. Опишите, пожалуйста:
* Какой будет характер взаимодействия устройство: команды, данные или и то и другое?
* Если команды, то сколько их будет?
* Если данные, то в какую сторону они передаются - от M к S или от S к M?
Чем подробнее вы распишите вашу задачу, тем проще будет найти решение!
Re: RS-485 на Ардуино
Спасибо, что откликнулись!
Команды будут самые простые, необходимо будет через М задавать в S определенные установочные данные и после в S должна выполнятся определенная функция в зависимости от заданной с М команды (...или возможно это не команда, а так же данные??)
проще говоря я с М посылаю на S, допустим коэффициент К=1, когда он приходит на S там исходя из того, что К=1 выполняется определенная функция (если отправляем К=2, то выполняется другая функция) и так же М должен опросить S, а то ли он прислал и ту ли функцию выполняет S
О протоколе:
ModBus – открытый протокол обмена данными в малых локальных сетях. Как правило, используется для передачи данных через интерфейсы RS-232, RS-485, RS-422, в сетях TCP/IP, UDP. Благодаря своей простоте и универсальности ModBus получил широкое распространение и стал де факто стандартом в малых распределенных вычислительных системах. Практически все современные контроллеры поддерживают работу в сетях ModBus.
В сети ModBus контроллеры, как правило, соединены по топологии ”Общая шина”. Взаимодействие контроллеров происходит в соответствии с моделью master-slave (ведущий-ведомый).
В сети есть главное устройство - ведущее. А также несколько подчиненных устройств – ведомые. Обмен может быть инициирован только ведущим устройством.
Транзакция (последовательность операций при обмене данными) состоит из запроса и ответа.
Ведущее устройство может адресовать запрос любому ведомому контроллеру или инициировать широковещательное сообщение, для всех ведомых устройств одновременно.
Ведомое устройство, определив свой адрес в запросе, формирует ответ.
В запросе от ведущего устройства обязательно содержится код функции, т.е. что надо делать. Также в зависимости от функции в запросе могут содержаться данные.
В общем случае кадр запроса (от М к S) имеет следующий формаn:
Пауза
Адрес 8 бит - Содержит адрес ведомого устройства, которому предназначено сообщение от ведущего
Функция 8 бит - Поле функции сообщает адресуемому ведомому устройству, какую операцию выполнить.
Данные N * 8 бит - В поле данных содержится информация, необходимую ведомому контроллеру для выполнения заданной функции или поле содержит данные передаваемые ведомым устройством по запросу ведущего. Длина и формат поля данных зависит от кода функции. В некоторых сообщениях данные могут отсутствовать.
Контрольная сумма 16 бит - Поле контроля целостности данных сообщений. Позволяет проверять кадры на наличие ошибок. Речь идет об ошибках, появляющихся при передаче данных.
Пауза
по идее и то и другое, на начальном этапе М отправляет массив данных на S и потом М опрашивает S и проверяет те ли это данные, что он посылал, если те, то хорошо, если нет, то ошибка (это своего рода защита); потом нужно будет с М отправлять команды на S и опрашивать S, получая массив данных (в качестве защиты опять же от ошибок в пересылке)Mr.Kubikus писал(а):Какой будет характер взаимодействия устройство: команды, данные или и то и другое?
* Если команды, то сколько их будет?
* Если данные, то в какую сторону они передаются - от M к S или от S к M?
Команды будут самые простые, необходимо будет через М задавать в S определенные установочные данные и после в S должна выполнятся определенная функция в зависимости от заданной с М команды (...или возможно это не команда, а так же данные??)
проще говоря я с М посылаю на S, допустим коэффициент К=1, когда он приходит на S там исходя из того, что К=1 выполняется определенная функция (если отправляем К=2, то выполняется другая функция) и так же М должен опросить S, а то ли он прислал и ту ли функцию выполняет S
О протоколе:
ModBus – открытый протокол обмена данными в малых локальных сетях. Как правило, используется для передачи данных через интерфейсы RS-232, RS-485, RS-422, в сетях TCP/IP, UDP. Благодаря своей простоте и универсальности ModBus получил широкое распространение и стал де факто стандартом в малых распределенных вычислительных системах. Практически все современные контроллеры поддерживают работу в сетях ModBus.
В сети ModBus контроллеры, как правило, соединены по топологии ”Общая шина”. Взаимодействие контроллеров происходит в соответствии с моделью master-slave (ведущий-ведомый).
В сети есть главное устройство - ведущее. А также несколько подчиненных устройств – ведомые. Обмен может быть инициирован только ведущим устройством.
Транзакция (последовательность операций при обмене данными) состоит из запроса и ответа.
Ведущее устройство может адресовать запрос любому ведомому контроллеру или инициировать широковещательное сообщение, для всех ведомых устройств одновременно.
Ведомое устройство, определив свой адрес в запросе, формирует ответ.
В запросе от ведущего устройства обязательно содержится код функции, т.е. что надо делать. Также в зависимости от функции в запросе могут содержаться данные.
В общем случае кадр запроса (от М к S) имеет следующий формаn:
Пауза
Адрес 8 бит - Содержит адрес ведомого устройства, которому предназначено сообщение от ведущего
Функция 8 бит - Поле функции сообщает адресуемому ведомому устройству, какую операцию выполнить.
Данные N * 8 бит - В поле данных содержится информация, необходимую ведомому контроллеру для выполнения заданной функции или поле содержит данные передаваемые ведомым устройством по запросу ведущего. Длина и формат поля данных зависит от кода функции. В некоторых сообщениях данные могут отсутствовать.
Контрольная сумма 16 бит - Поле контроля целостности данных сообщений. Позволяет проверять кадры на наличие ошибок. Речь идет об ошибках, появляющихся при передаче данных.
Пауза
- Mr.Kubikus
- Сотрудник ПАКПАК
- Сообщения: 1020
- Зарегистрирован: 22 окт 2010, 23:57
Re: RS-485 на Ардуино
Вы привели описание протокола Modbus. Почему бы не использовать соответствующие библиотеки для ведущего и подчиненного устройства?
Re: RS-485 на Ардуино
Именно в том и загвоздка, что нужно обойтись без библиотек...
А как в библиотеке реализуется этот протокол не могли бы Вы объяснить по простому примеру (желательно адаптированному к моему)???
Я смотрел примеры и не очень их понял... какая команда за что отвечает...
А как в библиотеке реализуется этот протокол не могли бы Вы объяснить по простому примеру (желательно адаптированному к моему)???
Я смотрел примеры и не очень их понял... какая команда за что отвечает...
- Mr.Kubikus
- Сотрудник ПАКПАК
- Сообщения: 1020
- Зарегистрирован: 22 окт 2010, 23:57
Re: RS-485 на Ардуино
А в чём проблема с использованием библиотеки? Почему нельзя?
Re: RS-485 на Ардуино
мне было дано задание реализовать Modbus протокол для связи двух ардуино по RS-485 как мастер и слейв...
Даже если и использовать библиотеку, то пока не ясно какую и мне в последствии их пояснять нужно будет, а я найти не могу нигде как в той или иной библиотеке реализуется Modbus протокол....
Проще говоря, если даже я буду использовать библиотеку, то проблема состоит в том, что не понятно как с ней работать
Даже если и использовать библиотеку, то пока не ясно какую и мне в последствии их пояснять нужно будет, а я найти не могу нигде как в той или иной библиотеке реализуется Modbus протокол....
Проще говоря, если даже я буду использовать библиотеку, то проблема состоит в том, что не понятно как с ней работать
Re: RS-485 на Ардуино
А как в данной библиотеке передавать данные? например массив? и как выполнять, например математические функции??? Я так и не смог разобраться... Помогите пожалуйста!Mr.Kubikus писал(а):А в чём проблема с использованием библиотеки? Почему нельзя?
МАСТЕР
Код: Выделить всё
#include <SimpleModbusMaster.h>
/*
SimpleModbusMaster позволяет вам общаться с любым подчиненным устройством с использованием протокола Modbus RTU.
Для связи с ведомым вам необходимо создать пакет, который будет содержать всю информацию, необходимую для связи с ведомым.
Счетчики информации реализованы для дальнейшей диагностики.
Это переменные, уже реализованные в пакете.
Вы можете установить и очистить эти переменные по мере необходимости.
Выполняются следующие счетчики информации о модуле:
Request_ - содержит общие запросы к подчиненному
Success_requests - содержит итоговые успешные запросы
Failed_requests - общие ошибки кадра, сбои контрольной суммы и отказы буфера
Retries - содержит количество попыток
Exception_errors - содержит конкретный счетчик ответов на исключение modbus
Обычно это незаконная функция, незаконный адрес, недопустимое значение данных или разные ошибки.
И, наконец, есть переменная, называемая «connection_», которая в данный момент содержит текущий статус соединения пакета. Если true, то соединение
активный. Если false, связь будет остановлена в этом пакете до тех пор, пока программист не установит переменную соединения в true.
Причина этого заключается в том, что время, связанное с коммуникацией по протоколу Modbus.
Каждый неисправный ведомый, который не сообщает, замедляет связь на линии со значением тайм-аута. Например.
Используя тайм-аут 1500 мс, если у вас 10 подчиненных и 9 из них перестают связываться с задержкой, то нагрузка будет равна 1500 мс * 9 = 13,5 секунд!
Связь будет автоматически остановлена после истечения срока действия повтора на каждом конкретном пакете.
Вся проверка ошибок, обновление и многозадачность связи происходит в фоновом режиме.
В общем, для связи с подчиненным устройством с использованием модуля Modbus RTU вы запрашиваете информацию,
используя конкретный идентификатор подчиненного устройства, запрос функции, начальный адрес
И, наконец, данные для запроса.
Поддерживаются функции 1, 2, 3, 4, 15 и 16. В дополнение к этому вещанию (id = 0) поддерживается функция 15 и 16.
Константы предусмотрены для:
Функция 1 - READ_COIL_STATUS // чтение состояния катушки
Функция 2 - READ_INPUT_STATUS // чтение состояния ввода
Функция 3 - READ_HOLDING_REGISTERS // чтение регистров хранения
Функция 4 - READ_INPUT_REGISTERS // чтение входных регистров
Функция 15 - FORCE_MULTIPLE_COILS // Закрепление нескольких катушек
Функция 16 - PRESET_MULTIPLE_REGISTERS // задает несколько регистров
Заметка:
Буфер последовательного кольца Arduino - 64 байта или 32 регистра.
В большинстве случаев вы подключаете Arduino, используя MAX485 или аналогичный.
В запросе функции 3 или 4 мастер попытается прочитать из подчиненного устройства, и поскольку 5 байтов уже используются для ID, FUNCTION, NO OF BYTES и двух байтов CRT, мастер может запросить только 58 байтов или 29 регистров.
В запросе функции 16 мастер попытается записать в подчиненное устройство, и поскольку 9 байтов уже используются для ID, FUNCTION, ADDRESS, NO REGISTERS, NO OF BYTES и двух байтов CRT, мастер может записывать только 54 байта или 27 регистров.
Заметка:
Использование USB-последовательного преобразователя Максимальные байты, которые вы можете отправить, ограничены его внутренним буфером, который отличается между производителями.
Поскольку предполагается, что в основном вы будете использовать Arduino для подключения без использования USB для последовательного преобразователя, внутренний буфер устанавливается так же, как буфер последовательного кольца Arduino, который составляет 64 байта.
В примере будет использоваться пакет1 для чтения регистра с адреса 0 (значение adc ch0) из подчиненного устройства arduino (id = 1).
Затем он будет использовать это значение для регулировки яркости светодиода на выводе 9 с использованием PWM.
Затем он будет использовать пакет2 для записи регистра (его собственное значение adc ch0) в адрес 1 на ведомом устройства arduino (id = 1), регулирующем яркость светодиода на выводе 9 с использованием PWM.
*/
//////////////////// Информация о портах ///////////////////
#define baud 9600
#define timeout 1000
#define polling 200 // частота сканирования
// Если внутренний регистр повторных попыток пакетов совпадает с подсчитанным числом повторных попыток, связь прекращается в этом пакете.
// Чтобы снова включить пакет, вы должны установить для переменной «connection» значение true.
#define retry_count 10
// используется для переключения буфера приема/передачи на драйвер
#define TxEnablePin 2
#define LED 9
// Это самый простой способ создания новых пакетов
// Добавьте столько, сколько вы хотите. TOTAL_NO_OF_PACKETS автоматически обновляется.
enum
{
PACKET1,
PACKET2,
TOTAL_NO_OF_PACKETS //оставить эту последнюю запись
};
// Создаем массив пакетов для настройки
Packet packets[TOTAL_NO_OF_PACKETS];
// Создаем пакетный вызов для доступа к каждому пакету по отдельности.
// Это не требуется, вы можете явно получить доступ к массиву. Например. packets [PACKET1].id = 2;
// Это становится утомительным, хотя ...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];
// Данные, считываемые с ведомого arduino, будут сохранены в этом массиве, если массив инициализирован пакетом.
unsigned int readRegs [1];
// Данные, которые должны быть записаны в подчиненное устройство arduino
unsigned int writeRegs [1];
void setup ()
{
// Функция конструктора пакетов Modbus инициализирует отдельный пакет с назначенными параметрами.
// Вы всегда можете сделать это явно, используя указатели struct. Первым параметром является адрес рассматриваемого пакета.
// Фактически этот параметр в Java указывает на адрес переданного объекта.
// Он имеет следующую форму: modbus_construct (пакет, идентификатор, функция, адрес, данные, регистр)
// Для функций 1 и 2 - количество точек
// Для функций 3, 4 и 16 данных - количество регистров
// Для функции 15 данных - количество катушек
// читаем 1 регистр, начинающийся с адреса 0
modbus_construct(packet1, 1, READ_HOLDING_REGISTERS, 0, 1, readRegs);
// записываем 1 регистр, начиная с адреса 1
modbus_construct(packet2, 1, PRESET_MULTIPLE_REGISTERS, 1, 1, writeRegs);
// P.S. Записи массива регистров выше могут быть разными массивами
/* Инициализировать настройки связи:
Параметры (HardwareSerial * SerialPort,
long baud,
unsigned char byteFormat,
unsigned int timeout,
unsigned int polling,
unsigned char retry_count,
unsigned char TxEnablePin,
Packet packets,
unsigned int total_no_of_packets);
Действующие форматы байтов Modbus:
SERIAL_8N2: 1 стартовый бит, 8 бит данных, 2 стоповых бита
SERIAL_8E1: 1 бит запуска, 8 бит данных, 1 бит четности, 1 стоповый бит
SERIAL_8O1: 1 бит запуска, 8 бит данных, 1 бит четности четности, 1 стоповый бит
Очевидно, вы можете использовать SERIAL_8N1, но это не соответствует спецификациям Modbus.
Тем не менее, я протестировал параметр SERIAL_8N1 на различных коммерческих мастерах и рабах, которые, как предполагалось,
придерживались этой спецификации и всегда могли общаться ... Go figure.
Они уже определены в глобальном пространстве имен Arduino.
*/
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
pinMode(LED, OUTPUT);
}
void loop ()
{
modbus_update();
writeRegs [0] = analogRead(A0); // обновлять данные, которые должны быть записаны в arduino slave
analogWrite(LED, readRegs[0]>>2); // ограничиваем значение adc от ведомого arduino до 255
/* Вы можете проверить или изменить внутренние счетчики определенного пакета следующим образом:
packet1->requests; запросы
packet1->successful_requests; //успешные запросы;
packet1->failed_requests; //неудачные запросы
packet1->exception_errors; //ошибки исключения
packet2->requests; //запросы
packet2->successful_requests; //успешные запросы
packet2->failed_requests; //неудачные запросы
packet2->exception_errors; //ошибки исключения
*/
}
Код: Выделить всё
#include <SimpleModbusSlave.h>
/* Этот примерный код получит значение adc ch0 от мастера arduino.
Затем он будет использовать это значение для регулировки яркости светодиода на выводе 9.
Значение, полученное от ведущего устройства, будет сохранено в адресе 1 в его собственном адресном пространстве, а именно: holdRegs [].
В дополнение к этому ведомые собственные значения adc ch0 будут сохранены в адресе 0 в своем собственном адресном пространстве, удерживая Regs [] для считываемого мастера.
Мастер будет использовать это значение, чтобы изменить яркость собственного светодиода, подключенного к выходу 9.
Метод modbus_update () обновляет массив регистров holdRegs и проверяет связь.
Заметка:
Буфер последовательного кольца Arduino - 64 байта или 32 регистра.
Большую часть времени вы подключаете ардуино к мастеру через последовательный порт с помощью MAX485 или аналогичного.
В запросе функции 3 мастер попытается прочитать из вашего подчиненного устройства,
и поскольку 5 байтов уже используются для ID, FUNCTION, NO OF BYTES и двух байтов CRT, мастер может запросить только 58 байтов или 29 регистров.
В запросе функции 16 мастер попытается записать в подчиненное устройство, и поскольку 9 байтов уже используются для
ID, FUNCTION, ADDRESS, NO REGISTERS, NO OF BYTES и двух байтов CRT, мастер может записывать только 54 байта или 27 регистров.
Использование USB-последовательного преобразователя Максимальные байты, которые вы можете отправить, ограничены его внутренним буфером, который отличается между производителями.
*/
#define LED 9
// Использование команды enum позволяет использовать простой способ для добавления и удаления регистров.
// Выполнение таким образом экономит ваше # определение размера вашего регистра регистрового массива каждый раз, когда вы хотите добавить больше регистров,
// и с первого взгляда информирует вас о вашем расположении регистра подчиненных.
//////////////// регистры вашего slave ///////////////////
enum
{
// просто добавляем или удаляем регистры...
// Первый регистр начинается с адреса 0
ADC_VAL,
PWM_VAL,
HOLDING_REGS_SIZE // оставить это
// общее количество регистров для функций 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)
*/
/* Действующие форматы байтов Modbus:
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, но это не соответствует спецификациям Modbus.
Тем не менее, я протестировал параметр SERIAL_8N1 на различных коммерческих мастерах и рабах, которые, как предполагалось,
придерживались этой спецификации и всегда могли общаться ... Go figure.
Эти форматы байтов уже определены в глобальном пространстве имен Arduino.
*/
modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs);
// modbus_update_comms (baud, byteFormat, id) не требуется, но позволяет легко обновлять переменные порта и ведомый идентификатор динамически в любой функции.
modbus_update_comms(9600, SERIAL_8N2, 1);
pinMode(LED, OUTPUT);
}
void loop()
{
// modbus_update () - единственный метод, используемый в loop ().
// Он возвращает общее количество ошибок с момента запуска подчиненного устройства.
// Вам не обязательно использовать его, но он полезен для диагностики на ведущем устройстве Modbus.
modbus_update();
holdingRegs[ADC_VAL] = analogRead(A0); // обновлять данные, которые должен быть прочитан мастером для настройки PWM
analogWrite(LED, holdingRegs[PWM_VAL]>>2); // ограничиваем значение adc от мастера arduino до 255
/* Заметка:
Использование команды enum не требуется. Вы можете установить максимально допустимый размер для holdinRegs [],
указав HOLDING_REGS_SIZE с использованием константы, а затем получить доступ с помощью Regs [] по адресу «Индекс».
То есть
HoldRegs [0] = analogRead (A0);
AnalogWrite (LED, holdRegs [1] / 4);
*/
}
- Mr.Kubikus
- Сотрудник ПАКПАК
- Сообщения: 1020
- Зарегистрирован: 22 окт 2010, 23:57
Re: RS-485 на Ардуино
Привет!
Исходники, которые вы привели, очень похожи на те, которые мы обсуждали в этом топике. Там мы подробно все разобрали. Посмотрите его внимательно. Если останутся вопросы буду рад помочь.
Исходники, которые вы привели, очень похожи на те, которые мы обсуждали в этом топике. Там мы подробно все разобрали. Посмотрите его внимательно. Если останутся вопросы буду рад помочь.
Re: RS-485 на Ардуино
Я все же не могу понять как обмениваться данными...Mr.Kubikus писал(а):Если останутся вопросы буду рад помочь.
как например прочитать значение переключателя на слэйве и по его его значению включить лампочку на мастере???