конфигурацию переменных вытащил в loop а потом функцией modbus_update(); он обновляет регистры и опрашивает. есть уменя плк-150 .время будет сконфигурирую и попробую .о результатах сообщю. вообще у меня есть сами микросхемы max485,хочу прямо через нее пробовать а не заказывать отдельный шилд. Делал в свое время модуль вводы вывода на ардуино slave и дискретные и аналоговые входа. все работало и с этой микросхемой,там обвязка минимальная!
Делюсь своим рабочим примером. ПОкажу только несколько строк касаемых модбас:
#include <ModbusRtu.h>
....
uint16_t au16data[20] // массив для хранения полученных данных от устройств
modbus_t ModRead[16]; // cтруктурный пакет modbus на 16 устройств
bool fullsend=false; // если отправлен весь массив данных
....
Modbus master(0,2,TXEN); // this is master and RS-232 or USB-FTDI 2 порт Сериал
void setup() {
master.begin( 19200 ); // baud-rate at 19200
master.setTimeOut( 10 ); // if there is no answer in 5000 ms, roll over
}
bool mobus_send(int pIndex, int pId,int pFun,int pReg,int pAns,int pDat)
{
if (pFun==6) {
au16data[pAns]=pDat;
ModRead[pIndex].u8id = pId; // slave address
ModRead[pIndex].u8fct = pFun; // function code (this one is registers read)
ModRead[pIndex].u16RegAdd = pReg; // start address in slave
ModRead[pIndex].au16reg =au16data+pAns; // ячейка в массиве куда будет записан полученный ответ
}
else
{
au16data[pAns]=pDat;
ModRead[pIndex].u8id = pId; // slave address
ModRead[pIndex].u8fct = pFun; // function code (this one is registers read)
ModRead[pIndex].u16RegAdd = pReg; // start address in slave
ModRead[pIndex].u16CoilsNo = 1; // читаем один байт
ModRead[pIndex].au16reg =au16data+pAns; // ячейка в массиве куда будет записан полученный ответ
}
master.query( ModRead[pIndex] );
return true;
}
return false;
}
void loop() {
.... // что-то делаем, а потом отправляем пакет:
ans=mobus_send(5,9,6,8,10,2); // 5-номер пакета, 9 - адрес устройства, 6-функция записи, 8 - регистр записи, 10 - поместить ответ в 10ю ячейку, 2 - значение регистра
// вот так будет выглядеть пакет 090600080002[CRC] где CRC контрольная сумма пакета.
...
//гдето на таймере:
master.poll(); // check incoming messages
if (master.getState() == COM_IDLE) {
//например включили светодиод который сказал что данные приняты/переданы
}
}
Я реализовал Slave и Master в одной арудино. Как Slave я с ней общаюсь с компа, как мастер - я общаюсь с устройствами от ардуино
Библиотеку ModbusRTU я малость модернизировал, чтобы реализовать мастер и слейв в одном устройстве.
Здравствуте! Вобщем запустил опросник с дисплеем,но корректно прочитать переменную типа float с плк не получается! В плк температура с датчика 28,34 а на дисплее 49408. В чем причина может быть? подскажите? адрес регистра 0. В модбас универсал сервере все корректно,на ардуино нет. То что тип данных разный или еще что.
Здравствуйте! Всем доброго времени! Подскажите пожалуйста-столкнулся спроблеммой при реализации модбус мастер на атмега328р. вообщем на ардуино уно все прекрасно работает ,код выкладывал выше. но когда извлек hex файл и прошил микроконтроллер и собрал то наотрез отказывается работать! собираю все тоже самое на уно то все прекрасно работает.в чем может быть проблемма ? или на отдельном микроконтроллере порт этот не работает или еще что. замерял напряжение на rx tx то оказалось почему то наоборот тоесть +5в постоянно а при переключениии прием передача то проскальзывает минус . парни голову уже сломал. в чем причина такого поведения? Всем за ранее спасибо кто откликнется!
Мой код управляет 16-ю частотниками Mistubishi и 4-мя ПИД-регуляторами температуры Autonics TM. Опрос оптических датчиков и отправка задачи контроллеру происходит в основном цикле программы(не в setup). Создаем что-то типа того:
void loop() {
....
switch (nextpak)
{
case 1: {
nextpak=100;
}
case 2: {
mobus_send(6,10,6,8,33,2);
nextpak=100;
}
case 3: {
mobus_send(7,10,6,8,33,2);
nextpak=100;
}
case 100:
{
nextpak=1;
}
} // switch
...
// где-то здесь обрабатываем порты ввода/вывода
если кнопка нажата тогда nextpak=2;
если другая кнопка нажата тогда nextpak=3;
}
Загрузчик только если это будет плата ардуино тоесть загрузка скетча по usb а если програматором шить hex то ненужно ничего только правильно установить fuse биты их можно посмотреть в файле boards.txt который лежит в папке arduino/hardvare ауть точно непомню найдете. А для извлечения hex из скетча в настройкас среды арлуино поставить галочку отображать компиляцию или чтото в этом духе скрмпилировать и внизу в окне сообщений скопировать путь к файлу с расширением hex обычно он в самом конце сообщения ну почти в самом конце да незабудте на контролер прицепить кварц 16мгц и два кондера 22пф на его ноги и на общий
в том то и дело я посмотрел этот файл board.txt и фьюзы выставил как на ардуиновскую атмегу и все равно все работает и экран и меню ничего не глючит а обмен по rs 485 не идет! Тут же снова перебираю на ардуино уно и блин все работает. Где засада не пойму
Да вообщем мучения закончились,незнаю- но пропаял еще раз ноги микросхем и поменял кварц на 16мгц и чудо все заработало .Всем говорю спасибо за поддержку и участие. скетч выложу ниже и фото что получилось
Такой вопрос. Нужна библиотека ModbusTCP Мастер + пример какой-нибудь.
Задача, Arduino в режиме Мастера по GPRS связывается с OPC сервером, который Slave, по Modbus протоколу и передает на него данные. Таких точек в режиме Мастера может быть до сотни. Так как статического IP у них не будет, то для них нужен режим Мастера.
Идентификация Ардуин либо через порт, либо через идентификатор.
Так как я в Ардуинах начинающий, хотя более 15 лет автоматизации за плечами, и есть опыт программирования, нужен какой-нибудь пример скретча.
Как Slave по протоколу Modbus TCP я уже соединился с OPC сервером. Все отлично управляется со Скады.
Сейчас задача в режиме Master подключиться к OPC, который переводим в режим Slave.
Пример в первом сообщении (ModbusTCP и библиотекой Mudbus) не понятен отсутствием рабочих примеров с библиотекой mudbus, начиная со строки if(Mb.Fc_rtu == 3).
Не подскажите программу - сканер Модбас TCP в режиме Slave.
Пример в первом сообщении (ModbusTCP и библиотекой Mudbus) не понятен отсутствием рабочих примеров с библиотекой mudbus, начиная со строки if(Mb.Fc_rtu == 3).
Не подскажите программу - сканер Модбас TCP в режиме Slave.
в этой строке задается функция модбас 1,3,5 или 6, выше в примере они описаны
вернее это условие проверки..
в теле цикла я так понимаю надо вместо DEC выставить цифровые значения адреса, начального регистра, функцию и число читаемых регистров(от 1 до..)
единственно мне не понятно, почему в примере в сериал номер регистра посылается прежде чем код функции, ведь должно быть наоборот. может быть ошибка, а может нет. так что если не заработает то возможно надо поменять местами строчки кода
Если я отправляю-получаю данные разных типов то и код функции будет разным, и наверно стоит функцию отправки-получения вынести в подпрограмму, задавая необходимые условия перед отправкой.
Цикл, как я понимаю, организовывать не нужно, просто задавая количество опрашиваемых регистров. Регистры при этом должны быть одного типа и идти по порядку.
Таким образом мы присваиваем начальные условия, например отправки, и вход в подпрограмму, далее условия получения и вход в подпрограмму.
Ну если по логике то получаем следующее: разложим FFF5 на байты и получим "1111 1111 1111 0101" самый старший бит несет информацию о знаке. 1 - т.е отрицательное число. Тогда можно сделать так - FFFF минус FFF5 и сдвинуть на один бит влево. Результат такой - FFFF - FFF5 = A, A+1 = B. Bxh = 11(dec) но мы знаем что оно отрицательное, т.к. старший бит был равен 1.
странно, я считал, что если создать переменную sign int и присовить ей ваши FFF5, то при отображении оно автоматически покажет нормальное знаковое число
покажите как вы в программе делаете, интересно просто
Такой вопрос. Кто-нибудь использовал протокол передачи ModbusTCP в связке с шилдом SIM900 + Mega2560?
Подскажите рабочие библиотеки, которые можно использовать для такой связки. SIM900 соединяю с сервером без библиотек, через команды AT, даже могу опять же в ручном режиме закинуть заранее сформированный пакет ModbusTCP и сервер его обработает, но получить данные с сервера никак не получается. Например запрос по состоянию дискретных переменных на сервере присылает непонятную кучу непонятной длины байт, хотя тот же запрос через Ethernet выдает правильный, понятный ответ. Возможно, это какая-то информация из SIM900, или шилд трансформирует присылаемые данные каким-то образом, понять логику пока не представляется возможным.
Возможно, использование библиотеки для шилда SIM900 поможет в фильтрации ненужной информации из буфера SIM900. Или есть библиотека ModbusTCP для шилда SIM900, как в примере вверху темы, для Ethernet.
Возможно, надо учесть какие-либо нюансы, танцы с бубном, для корректного приема ответа с сервера через SIM900, как-то подготовить шилд?
Кто в курсе?
p/s/
Все, вопрос решил. Все написал без библиотек, нюансов море, понимаю, почему молчали. Примеров и подсказок на просторах интернета не нашел. Вопрос закрыт.
Добрый вечер! Вот и мне интересно решить задачку с ModbusОм. Есть простое, слейв, устройство, которое должно выдавать по мадбас состояние концевиков. Код вот такой:
#include <SimpleModbusSlave.h>
enum
{
DATA_VAL,
HOLDING_REGS_SIZE
};
unsigned int holdingRegs[HOLDING_REGS_SIZE];
void setup()
{
pinMode(5,INPUT_PULLUP); pinMode(6,INPUT_PULLUP); pinMode(7,INPUT_PULLUP);
pinMode(8,INPUT_PULLUP); pinMode(9,INPUT_PULLUP);
if ((digitalRead(6) == 1) && (digitalRead(7) == 1))
{
modbus_configure(&Serial, 9600, SERIAL_8N2, 50, 3, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(9600, SERIAL_8N2, 50);
}
if ((digitalRead(6) == 1) && (digitalRead(7) == 0))
{
modbus_configure(&Serial, 9600, SERIAL_8N2, 51, 3, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(9600, SERIAL_8N2, 51);
}
if ((digitalRead(6) == 0) && (digitalRead(7) == 1))
{
modbus_configure(&Serial, 9600, SERIAL_8N2, 52, 3, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(9600, SERIAL_8N2, 52);
}
if ((digitalRead(6) == 0) && (digitalRead(7) == 0))
{
modbus_configure(&Serial, 9600, SERIAL_8N2, 53, 3, HOLDING_REGS_SIZE, holdingRegs);
modbus_update_comms(9600, SERIAL_8N2, 53);
}
}
void loop()
{
// формируем телеграмму
MData = 5;
if(digitalRead(8)==1 && digitalRead(9) == 1) MData = 0;
if(digitalRead(8)==0 && digitalRead(9) == 1) MData = 1;
if(digitalRead(8)==1 && digitalRead(9) == 0) MData = 2;
if(digitalRead(8)==0 && digitalRead(9) == 0) MData = 3;
// отправляем телеграмму
holdingRegs[DATA_VAL] = MData; // update data to be read by the master to adjust the PWM
modbus_update();
/* Note:
The use of the enum instruction is not needed. You could set a maximum allowable
size for holdinRegs[] by defining HOLDING_REGS_SIZE using a constant and then access
holdingRegs[] by "Index" addressing.
I.e.
holdingRegs[0] = analogRead(A0);
analogWrite(LED, holdingRegs[1]/4);
*/
}
Я бы создал массив, в теле void считывал бы значения состояния ног и писал бы их в массив. А потом по модбас запрашивал значение этого массива. Интересующий меня бит массива
Подскажите пожалуйста. Библиотеки SimpleModbusSlave.h и SimpleModbusMaster.h
К
enum
{
//мастеру
PACKET1, //4 слейв
PACKET3, //2 слейв
//слейву
PACKET2, //4 слейв
PACKET4, //2 слейв
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], 4, READ_HOLDING_REGISTERS, 0, 3, 0); // чтение данных slave-master
// Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
modbus_construct(&packets[PACKET2], 4, PRESET_MULTIPLE_REGISTERS, 3, 3, 3); // запись данных master-slave
//свет веранда
// Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
modbus_construct(&packets[PACKET3], 2, READ_HOLDING_REGISTERS, 6, 1, 6); // чтение данных slave-master
// Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
modbus_construct(&packets[PACKET4], 2, PRESET_MULTIPLE_REGISTERS, 7, 1, 7); // запись данных master-slave
// инициализируем протокол модбус
modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
pinMode(LED1, OUTPUT);
} // конец void setup()
Как думаете код будет работать?
Суть: мастер передает 4 слейву значения из 3 регистров (регистр 3, 4, 5). Принимает 3 регистра (регистр 0. 1, 2). Мастер передает 2 слейву одно значение (регистр 7) и принимает одно значение (регистр 6).
Или нужно в каждый пакет писать по одному регистру?
Уточню: у вас на ардуине мастер и на ардуине несколько слейвов? так? Мастер управляет слейвами. Т.е. только мастер может опрашивать и записывать данные в слейвы. Пакет Модбас на запись содержит - адрес устройства, функция записи (к примеру 06), адрес регистра слейва (00 01), данные (03 E8), CR CR. Запись происходит одним пакетом в один регистр. Следовательно, если мы хотим записать 3 регистра у слейва, то нам нужно 3 пакета. Но я не пробовал использовать мультипакеты, функции 15 и 16 (0х0F и 0x10). В теории: Команда состоит из адреса элемента, количества изменяемых элементов, количества передаваемых байт устанавливаемых значений и самих устанавливаемых значений. Данные упаковываются так же, как в командах чтения данных. Ответ состоит из начального адреса и количества изменённых элементов.
Так что выбирать вам. Либо копать в направлении мульти-функций или посылать несколько пакетов )))
Замечу - что адреса записались с 0000 по 0002, т.е указав количество регистров - он включает начальный и плюс +2. Далее идет количество байт, в примере на Вики указано 2 байта, но у меня не получилось 2 байта задать всем трем регистрам, в первый попадает наше значение, а в остальные идет мусор. Поэтому, нужно указать значение для каждого регистра. Если у нас их 3 то 2*3=6, и следоватьельно все 6 байт мы должны указать. Это 03F8 три раза (к примеру). (значение в dec = 1000).
Проще формировать самому пакет, например, накидывая в массив Data [N] необходимые данные, привязав каждый байт к конкретной переменной, данные сформируете универсально и автоматически, далее отправляя весь массив в порт. Универсальную распаковку массива при получении тоже сделать не составит труда. Все необходимые функции можете прописать сами, в том числе и свыше 1-16 функций. https://ru.wikipedia.org/wiki/Modbus
Уточню: у вас на ардуине мастер и на ардуине несколько слейвов? так? Мастер управляет слейвами. Т.е. только мастер может опрашивать и записывать данные в слейвы. Пакет Модбас на запись содержит - адрес устройства, функция записи (к примеру 06), адрес регистра слейва (00 01), данные (03 E8), CR CR. Запись происходит одним пакетом в один регистр. Следовательно, если мы хотим записать 3 регистра у слейва, то нам нужно 3 пакета. Но я не пробовал использовать мультипакеты, функции 15 и 16 (0х0F и 0x10). В теории: Команда состоит из адреса элемента, количества изменяемых элементов, количества передаваемых байт устанавливаемых значений и самих устанавливаемых значений. Данные упаковываются так же, как в командах чтения данных. Ответ состоит из начального адреса и количества изменённых элементов.
Так что выбирать вам. Либо копать в направлении мульти-функций или посылать несколько пакетов )))
Благодарю за разъяснения.
Для простоты чтения кода я думал запихать все в один пакет. Утрирую конечно, но суть та.
Мультипакеты даже трогать не буду. Мне бы с обычными разобраться.
Функции 15, 16 действительно удобны. Я например в основном пользуюсь 15, записывая несколько дискретных сигналов. Накидываю их в байт подобным образом:
bitWrite(Data[13], D1, Vent1); - где VN1 - номер дискретного канала (1,2,3,4 и т.д. макс.8 - в 1 байте 8 битов.), а дискретный boolean Vent1 - HIGH или LOW.
Так можно накидать состояния всех необходимых регистров, отправить в порт и считать в приемнике:
BuferDiscret [i] = bitRead (Buffer [11], i); - где i - номер канала, Bufer [11] - одиннадцатый байт в пакете Modbus TCP (я читаю пакет в массив). В цикле, изменяя номера канала, считываем в массив дискреты, и далее:
Функции 15, 16 действительно удобны. Я например в основном пользуюсь 15, записывая несколько дискретных сигналов. Накидываю их в байт подобным образом:
bitWrite(Data[13], D1, Vent1); - где VN1 - номер дискретного канала (1,2,3,4 и т.д. макс.8 - в 1 байте 8 битов.), а дискретный boolean Vent1 - HIGH или LOW.
Так можно накидать состояния всех необходимых регистров, отправить в порт и считать в приемнике:
BuferDiscret [i] = bitRead (Buffer [11], i); - где i - номер канала, Bufer [11] - одиннадцатый байт в пакете Modbus TCP (я читаю пакет в массив). В цикле, изменяя номера канала, считываем в массив дискреты, и далее:
вот предварительный скетч для опроса устройств
в принципе должен работать ,под рукой нет модуля пока.Может что дополните и подскажите! Буду очень признателен! Фото экрана позже выложу
на вид вроде нормально но проверять тоже некогда после работы собираю один проэкт на заказ и сроки до сентября так что пока занят
конфигурацию переменных вытащил в loop а потом функцией modbus_update(); он обновляет регистры и опрашивает. есть уменя плк-150 .время будет сконфигурирую и попробую .о результатах сообщю. вообще у меня есть сами микросхемы max485,хочу прямо через нее пробовать а не заказывать отдельный шилд. Делал в свое время модуль вводы вывода на ардуино slave и дискретные и аналоговые входа. все работало и с этой микросхемой,там обвязка минимальная!
на микросхемах можно и работать будет просто шилды для ленивых
фото мастера rs485 на ардуино
Делюсь своим рабочим примером. ПОкажу только несколько строк касаемых модбас:
Я реализовал Slave и Master в одной арудино. Как Slave я с ней общаюсь с компа, как мастер - я общаюсь с устройствами от ардуино
Библиотеку ModbusRTU я малость модернизировал, чтобы реализовать мастер и слейв в одном устройстве.
Здравствуте! Вобщем запустил опросник с дисплеем,но корректно прочитать переменную типа float с плк не получается! В плк температура с датчика 28,34 а на дисплее 49408. В чем причина может быть? подскажите? адрес регистра 0. В модбас универсал сервере все корректно,на ардуино нет. То что тип данных разный или еще что.
все получилось, когда в плк преобразоал в UINT и вывело корректно! вывод --пременные получается опрашивать можно с определенным типом данных
Здравствуйте! Всем доброго времени! Подскажите пожалуйста-столкнулся спроблеммой при реализации модбус мастер на атмега328р. вообщем на ардуино уно все прекрасно работает ,код выкладывал выше. но когда извлек hex файл и прошил микроконтроллер и собрал то наотрез отказывается работать! собираю все тоже самое на уно то все прекрасно работает.в чем может быть проблемма ? или на отдельном микроконтроллере порт этот не работает или еще что. замерял напряжение на rx tx то оказалось почему то наоборот тоесть +5в постоянно а при переключениии прием передача то проскальзывает минус . парни голову уже сломал. в чем причина такого поведения? Всем за ранее спасибо кто откликнется!
вот нашел по моему вопросу но тоже неясно на сколько это подключение работоспособно и реально.
http://deadlock.org.ua/kit/habr/post/729
и в чем смысл
Мой код управляет 16-ю частотниками Mistubishi и 4-мя ПИД-регуляторами температуры Autonics TM. Опрос оптических датчиков и отправка задачи контроллеру происходит в основном цикле программы(не в setup). Создаем что-то типа того:
>>код выкладывал выше. но когда извлек hex файл и прошил микроконтроллер и собрал то наотрез отказывается работать!
при отсутствии приема/передачи на RS постояннный потенциал между линиями в 2-5 вольт это нормально
а во время передачи соответственно побегут байтики. можно посмотреть осцилограммы.
по ссылке ниже автор ставил инвертор на Tx, значит там почему-то был перевернутый сигнал, все от бибилиотеки зависит наверное/
кстати, как заливали хекс от ардуино в 328р ? а то тоже хотел попробовать
Dr_grizzly, у вас своя библиотека какая-то ? откуда функция mobus_send ?
Смотри пост #57, эту библиотеку нашел здесь на форуме
#include <ModbusRtu.h>
bool
mobus_send(
int
pIndex,
int
pId,
int
pFun,
int
pReg,
int
pAns,
int
pDat)
15
{
16
if
(pFun==6) {
17
au16data[pAns]=pDat;
18
ModRead[pIndex].u8id = pId;
// slave address
19
ModRead[pIndex].u8fct = pFun;
// function code (this one is registers read)
20
ModRead[pIndex].u16RegAdd = pReg;
// start address in slave
21
ModRead[pIndex].au16reg =au16data+pAns;
// ячейка в массиве куда будет записан полученный ответ
22
}
23
else
24
{
25
au16data[pAns]=pDat;
26
ModRead[pIndex].u8id = pId;
// slave address
27
ModRead[pIndex].u8fct = pFun;
// function code (this one is registers read)
28
ModRead[pIndex].u16RegAdd = pReg;
// start address in slave
29
ModRead[pIndex].u16CoilsNo = 1;
// читаем один байт
30
ModRead[pIndex].au16reg =au16data+pAns;
// ячейка в массиве куда будет записан полученный ответ
31
}
32
33
master.query( ModRead[pIndex] );
34
return
true
;
35
}
36
37
return
false
;
38
}
Harbor,Здравствуйте! HEX так извлекал- скетч на ардуино иде компилируешь,
cilentlekx, я гдето читал, что для заливки хекса от ардуино нужно в атмегу загрузчик ардуиновский зашить сначала
По поводу hex прошивки - CodeSys 3.х отлично все заливает ))) попробуйте им
Загрузчик только если это будет плата ардуино тоесть загрузка скетча по usb а если програматором шить hex то ненужно ничего только правильно установить fuse биты их можно посмотреть в файле boards.txt который лежит в папке arduino/hardvare ауть точно непомню найдете. А для извлечения hex из скетча в настройкас среды арлуино поставить галочку отображать компиляцию или чтото в этом духе скрмпилировать и внизу в окне сообщений скопировать путь к файлу с расширением hex обычно он в самом конце сообщения ну почти в самом конце да незабудте на контролер прицепить кварц 16мгц и два кондера 22пф на его ноги и на общий
в том то и дело я посмотрел этот файл board.txt и фьюзы выставил как на ардуиновскую атмегу и все равно все работает и экран и меню ничего не глючит а обмен по rs 485 не идет! Тут же снова перебираю на ардуино уно и блин все работает. Где засада не пойму
а может быть что я на микроконтроллер кварц поставил на 12мгц а на УНО 16мгц? может скорости теперь не совпадают
Так 16 ставить надо
Да вообщем мучения закончились,незнаю- но пропаял еще раз ноги микросхем и поменял кварц на 16мгц и чудо все заработало .Всем говорю спасибо за поддержку и участие. скетч выложу ниже и фото что получилось
вот фото опросника
Доброго Здравия!
Такой вопрос. Нужна библиотека ModbusTCP Мастер + пример какой-нибудь.
Задача, Arduino в режиме Мастера по GPRS связывается с OPC сервером, который Slave, по Modbus протоколу и передает на него данные. Таких точек в режиме Мастера может быть до сотни. Так как статического IP у них не будет, то для них нужен режим Мастера.
Идентификация Ардуин либо через порт, либо через идентификатор.
Так как я в Ардуинах начинающий, хотя более 15 лет автоматизации за плечами, и есть опыт программирования, нужен какой-нибудь пример скретча.
Заранее Благодарю за помощь.
в самом первом сообщении есть ссылка на библиотеку ModbusTCP и пример.
для работы будет необходим модуль Ethernet shield, описание что как подключать есть
для начала попрбовать связать два устройства между собой, помигать светодиодиками
Если вы понимаете как работает протокол modbus то особо сложно не должно быть разобраться
Как Slave по протоколу Modbus TCP я уже соединился с OPC сервером. Все отлично управляется со Скады.
Сейчас задача в режиме Master подключиться к OPC, который переводим в режим Slave.
Пример в первом сообщении (ModbusTCP и библиотекой Mudbus) не понятен отсутствием рабочих примеров с библиотекой mudbus, начиная со строки
if
(Mb.Fc_rtu == 3).
Не подскажите программу - сканер Модбас TCP в режиме Slave.
Пример в первом сообщении (ModbusTCP и библиотекой Mudbus) не понятен отсутствием рабочих примеров с библиотекой mudbus, начиная со строки
if
(Mb.Fc_rtu == 3).
Не подскажите программу - сканер Модбас TCP в режиме Slave.
в этой строке задается функция модбас 1,3,5 или 6, выше в примере они описаны
вернее это условие проверки..
в теле цикла я так понимаю надо вместо DEC выставить цифровые значения адреса, начального регистра, функцию и число читаемых регистров(от 1 до..)
единственно мне не понятно, почему в примере в сериал номер регистра посылается прежде чем код функции, ведь должно быть наоборот. может быть ошибка, а может нет. так что если не заработает то возможно надо поменять местами строчки кода
44
Serial
.print(Mb.Start_rtu, DEC);
// Start address адресc регистра
46
Serial
.print(Mb.Fc_rtu, DEC);
// Function code код функции модбас
тут программка Модбас в режиме Slave, только кажется работает без регистрации 10 минут, но есть в сети крякнутые версии.
https://yadi.sk/d/Q_wDJjX2yPLa5
Уважаемый harbor, БлагоДарю за программу.
Если я отправляю-получаю данные разных типов то и код функции будет разным, и наверно стоит функцию отправки-получения вынести в подпрограмму, задавая необходимые условия перед отправкой.
Цикл, как я понимаю, организовывать не нужно, просто задавая количество опрашиваемых регистров. Регистры при этом должны быть одного типа и идти по порядку.
Таким образом мы присваиваем начальные условия, например отправки, и вход в подпрограмму, далее условия получения и вход в подпрограмму.
Подскажите читаю переменную с прибора
В описании написано что переменная имеет топ word_16 с диапазоном от -200 до +200
При чтении от 0 до +200 проблеме нет.
А вот когда значение например -11, то получаю 65255 (0xfff5)
По запросам вижу:
а тут должно быть -11:
Подскажите как привести к правильному виду.
почитайте про типы данных, знаковые целые в частности
например тут http://arduino.ua/ru/prog/UnsignedInt
почитайте про типы данных, знаковые целые в частности
например тут http://arduino.ua/ru/prog/UnsignedInt
я про это уже понял.
Но не пойму как мне привести к нормальному виду.
Используя калькулятор вижу что если в hex добавить FFFF то получу -11.
Если не сложно, подскажите как это сделать программно.
Ну если по логике то получаем следующее: разложим FFF5 на байты и получим "1111 1111 1111 0101" самый старший бит несет информацию о знаке. 1 - т.е отрицательное число. Тогда можно сделать так - FFFF минус FFF5 и сдвинуть на один бит влево. Результат такой - FFFF - FFF5 = A, A+1 = B. Bxh = 11(dec) но мы знаем что оно отрицательное, т.к. старший бит был равен 1.
странно, я считал, что если создать переменную sign int и присовить ей ваши FFF5, то при отображении оно автоматически покажет нормальное знаковое число
покажите как вы в программе делаете, интересно просто
Подскажите читаю переменную с прибора
В описании написано что переменная имеет топ word_16 с диапазоном от -200 до +200
При чтении от 0 до +200 проблеме нет.
А вот когда значение например -11, то получаю 65255 (0xfff5)
По запросам вижу:
а тут должно быть -11:
Подскажите как привести к правильному виду.
(int16_t)packets[i]
Всем доброго времени суток!
Такой вопрос. Кто-нибудь использовал протокол передачи ModbusTCP в связке с шилдом SIM900 + Mega2560?
Подскажите рабочие библиотеки, которые можно использовать для такой связки. SIM900 соединяю с сервером без библиотек, через команды AT, даже могу опять же в ручном режиме закинуть заранее сформированный пакет ModbusTCP и сервер его обработает, но получить данные с сервера никак не получается. Например запрос по состоянию дискретных переменных на сервере присылает непонятную кучу непонятной длины байт, хотя тот же запрос через Ethernet выдает правильный, понятный ответ. Возможно, это какая-то информация из SIM900, или шилд трансформирует присылаемые данные каким-то образом, понять логику пока не представляется возможным.
Возможно, использование библиотеки для шилда SIM900 поможет в фильтрации ненужной информации из буфера SIM900. Или есть библиотека ModbusTCP для шилда SIM900, как в примере вверху темы, для Ethernet.
Возможно, надо учесть какие-либо нюансы, танцы с бубном, для корректного приема ответа с сервера через SIM900, как-то подготовить шилд?
Кто в курсе?
p/s/
Все, вопрос решил. Все написал без библиотек, нюансов море, понимаю, почему молчали. Примеров и подсказок на просторах интернета не нашел. Вопрос закрыт.
Добрый вечер! Вот и мне интересно решить задачку с ModbusОм. Есть простое, слейв, устройство, которое должно выдавать по мадбас состояние концевиков. Код вот такой:
отсюда следующий вопрос: какой вид должен быть у телеграммы опроса?
50 03 00 01 00 00 - не работает ...
Наиболее разжеван протокол вот здесь http://ipc2u.ru/articles/prostye-resheniya/modbus-tcp/
По Вашему запросу "50 03 00 01 00 00", где
50 - номер устройства, к которому Вы обращаетесь.
03 - читаем Analog Output Holding Registers.
00 01 - адрес регистра.
00 00 - количество требуемых регистров.... ?
Может количество требуемых регистров 00 01 ? Номер устройства 50?
Также Вы используете бибилиотеку, проконтролировали ее работу?
Я бы создал массив, в теле void считывал бы значения состояния ног и писал бы их в массив. А потом по модбас запрашивал значение этого массива. Интересующий меня бит массива
Здравствуйте
Подскажите пожалуйста. Библиотеки SimpleModbusSlave.h и SimpleModbusMaster.h
К
Как думаете код будет работать?
Суть: мастер передает 4 слейву значения из 3 регистров (регистр 3, 4, 5). Принимает 3 регистра (регистр 0. 1, 2). Мастер передает 2 слейву одно значение (регистр 7) и принимает одно значение (регистр 6).
Или нужно в каждый пакет писать по одному регистру?
Благодарю.
Подниму тему. еще актуально.
Уточню: у вас на ардуине мастер и на ардуине несколько слейвов? так? Мастер управляет слейвами. Т.е. только мастер может опрашивать и записывать данные в слейвы. Пакет Модбас на запись содержит - адрес устройства, функция записи (к примеру 06), адрес регистра слейва (00 01), данные (03 E8), CR CR. Запись происходит одним пакетом в один регистр. Следовательно, если мы хотим записать 3 регистра у слейва, то нам нужно 3 пакета. Но я не пробовал использовать мультипакеты, функции 15 и 16 (0х0F и 0x10). В теории: Команда состоит из адреса элемента, количества изменяемых элементов, количества передаваемых байт устанавливаемых значений и самих устанавливаемых значений. Данные упаковываются так же, как в командах чтения данных. Ответ состоит из начального адреса и количества изменённых элементов.
Так что выбирать вам. Либо копать в направлении мульти-функций или посылать несколько пакетов )))
Нашел на Вики пример такого пакета https://ru.wikipedia.org/wiki/Modbus.
Накидал пример для себя и протестил пакет с функцией 10, вот что получилось
Адрес:Фукнция:Начальный регистр:Количество регистров:Количество байт данных:Данные
05:10:0000:0003:06:03F803F803F8:CRC
Замечу - что адреса записались с 0000 по 0002, т.е указав количество регистров - он включает начальный и плюс +2. Далее идет количество байт, в примере на Вики указано 2 байта, но у меня не получилось 2 байта задать всем трем регистрам, в первый попадает наше значение, а в остальные идет мусор. Поэтому, нужно указать значение для каждого регистра. Если у нас их 3 то 2*3=6, и следоватьельно все 6 байт мы должны указать. Это 03F8 три раза (к примеру). (значение в dec = 1000).
Проще формировать самому пакет, например, накидывая в массив Data [N] необходимые данные, привязав каждый байт к конкретной переменной, данные сформируете универсально и автоматически, далее отправляя весь массив в порт. Универсальную распаковку массива при получении тоже сделать не составит труда. Все необходимые функции можете прописать сами, в том числе и свыше 1-16 функций. https://ru.wikipedia.org/wiki/Modbus
Каждый байт расписан например тут https://ipc2u.ru/articles/prostye-resheniya/modbus-tcp/
Обработка не составит труда. Если не требуется TCP - выкиньте первые 4 байта.
Я пошел таким путем, так как было проще и объективней прописать пакет самому, накидывая данные по мере опроса функций.
Уточню: у вас на ардуине мастер и на ардуине несколько слейвов? так? Мастер управляет слейвами. Т.е. только мастер может опрашивать и записывать данные в слейвы. Пакет Модбас на запись содержит - адрес устройства, функция записи (к примеру 06), адрес регистра слейва (00 01), данные (03 E8), CR CR. Запись происходит одним пакетом в один регистр. Следовательно, если мы хотим записать 3 регистра у слейва, то нам нужно 3 пакета. Но я не пробовал использовать мультипакеты, функции 15 и 16 (0х0F и 0x10). В теории: Команда состоит из адреса элемента, количества изменяемых элементов, количества передаваемых байт устанавливаемых значений и самих устанавливаемых значений. Данные упаковываются так же, как в командах чтения данных. Ответ состоит из начального адреса и количества изменённых элементов.
Так что выбирать вам. Либо копать в направлении мульти-функций или посылать несколько пакетов )))
Благодарю за разъяснения.
Для простоты чтения кода я думал запихать все в один пакет. Утрирую конечно, но суть та.
Мультипакеты даже трогать не буду. Мне бы с обычными разобраться.
Еще раз спасибо.
Функции 15, 16 действительно удобны. Я например в основном пользуюсь 15, записывая несколько дискретных сигналов. Накидываю их в байт подобным образом:
bitWrite(Data[13], D1, Vent1); - где VN1 - номер дискретного канала (1,2,3,4 и т.д. макс.8 - в 1 байте 8 битов.), а дискретный boolean Vent1 - HIGH или LOW.
Так можно накидать состояния всех необходимых регистров, отправить в порт и считать в приемнике:
BuferDiscret [i] = bitRead (Buffer [11], i); - где i - номер канала, Bufer [11] - одиннадцатый байт в пакете Modbus TCP (я читаю пакет в массив). В цикле, изменяя номера канала, считываем в массив дискреты, и далее:
Vent1 = BuferDiscret[0]; // Пишем в переменные дискретных каналов.
Vent2 = BuferDiscret[1];
Для Вас Modbus RTU протокол с подробнейшим описанием: https://ipc2u.ru/articles/prostye-resheniya/modbus-rtu/
Функции 15, 16 действительно удобны. Я например в основном пользуюсь 15, записывая несколько дискретных сигналов. Накидываю их в байт подобным образом:
bitWrite(Data[13], D1, Vent1); - где VN1 - номер дискретного канала (1,2,3,4 и т.д. макс.8 - в 1 байте 8 битов.), а дискретный boolean Vent1 - HIGH или LOW.
Так можно накидать состояния всех необходимых регистров, отправить в порт и считать в приемнике:
BuferDiscret [i] = bitRead (Buffer [11], i); - где i - номер канала, Bufer [11] - одиннадцатый байт в пакете Modbus TCP (я читаю пакет в массив). В цикле, изменяя номера канала, считываем в массив дискреты, и далее:
Vent1 = BuferDiscret[0]; // Пишем в переменные дискретных каналов.
Vent2 = BuferDiscret[1];
Для Вас Modbus RTU протокол с подробнейшим описанием: https://ipc2u.ru/articles/prostye-resheniya/modbus-rtu/
благодарю
Ребята, а как можно обойти:
Хотелось бы чтобы всегда мастер на связи был, т.е если слейвы не отвечают, мастер бы не впадал в спячку а продолжал их теребить запросами.
благодарю