5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
1

Приложение VBA Exel: обращение к Slave-устройству по протоколу Modbus RTU через порт RS485

07.06.2024, 14:07. Показов 503. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго дня Уважаемые.
Прошу оказать консультативную помощь в создании приложения Master-устройства для общения со Slave-устройством по протоколу Madbus RTU, через порт RS485, с помощью Vba Excel.
Спасибо _________ Юрий.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.06.2024, 14:07
Ответы с готовыми решениями:

Приложение для управления девайсом по протоколу Modbus RTU
Здравствуйте! Необходимо написать приложение для управления источником постоянного тока по...

STM32F103 подключение через UART-RS485 счетчик Modbus RTU не отзывается
Электрически все подключается через UART2->конвертер-RS485->счетчик 1. Проверка счетчика через...

Нет связи между модулем ввода (modbus rtu slave) и программой modbus poll на ноутбуке
Добрый день форумчанам. Сконфигурирован модуль modbus rtu slave в Ovation system. Опыт работы с...

Обращение к modbus устройству через TCP протокол
Добрый день, написал TCP клиент, все работает. Подскажите пожалуйста как обратиться к устройству с...

Протокол Modbus RTU/ASCII для режима Slave
Здравствуйте! Стоит задача реализовать протокол Modbus ASCII/RTU для режима Slave на Си. Программа...

30
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
07.06.2024, 16:13 2
Во вложении трофейная программа (просто не помню, где скачал).
Описание:
"Работаем с COM: портом

Автор: Riaan Aspeling

Эта маленькая программка открывает COM порт и позволяет записывать и считывать из него данные. Исходный код поможет Вам создать приложение, которое может работать с модемом, сканером баркодов, принтером, работающим через последовательный порт. "
Вложения
Тип файла: zip vb_serial_comms.zip (5.1 Кб, 6 просмотров)
1
5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
07.06.2024, 16:31  [ТС] 3
Так это Visual Basic 5.0, 6.0.
А мне хотелось бы Vba Excel.
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
07.06.2024, 17:01 4
Там используются функции Win32 API.
В VBA Excel нет контрола MsComm.
Но есть возможность создавать формы. Создайте, или скопируйте форму из примера и попробуйте.
У вас реальный или виртуальный порт RS-232?
0
5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
07.06.2024, 17:42  [ТС] 5
Мой компьютер настолько древний, что в нём есть реальный порт rs-232.
Однако, на моём slave- устройстве есть только порт RS485.
Поэтому мне нужно работать с спортом USB моего компьютера, через адаптер USB - rs485.
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
07.06.2024, 18:09 6
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
мне нужно работать с спортом USB моего компьютера, через адаптер USB - rs485.
Или через конвертер RS-232 - RS-485.
Суть в том, что COM-порт (RS-232), или USB (через драйвер) выполняют транспортную функцию, т.е. посредник. Вам в любом случае, придётся открывать COM-порт (RS-232), формировать фрейм в формате Modbus, отправлять его через тот же порт, ожидать наполнения буфера COM-порта, проверять полученный фрейм от устройства на соответсивие данных контрольной сумме, и , по окончании работы, закрывать COM-порт.
Если вам зачем-то нужно работать из-под Ms Excel, то, из-за отсутствия контрола MsComm, придётся использовать функции Win32 API, использование которых, приведены в приложенной мной программе.
0
5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
07.06.2024, 18:52  [ТС] 7
Цитата Сообщение от Argus19 Посмотреть сообщение
Или через конвертер RS-232 - RS-485.
Я хочу вообще забыть об RS-232.
У меня есть на slave-устройстве rs-485 и на компьютере usb-порт, всё.
---------------
Цитата Сообщение от Argus19 Посмотреть сообщение
Суть в том, что .... по окончании работы, закрывать COM-порт.
Это понятно.
То есть программирование на нижнем уровне.
---------------
Цитата Сообщение от Argus19 Посмотреть сообщение
Если вам зачем-то нужно работать из-под Ms Excel
Но если забыть про Excel, может быть тогда и пропустить, как промежуточное звено Visual Basic 6.0, где по-любому придётся работать с единичками и проверками контрольных сумм и всё такое прочее...
И взять уже тот язык программирования, на котором уже есть стандартная библиотека по протоколу Мадбас?
То есть подняться ещё на один уровень, забыв при этом про все эти единички и контрольные суммы?
Если не ошибаюсь, Python способен на такое.
--------------
Добавлено через 3 минуты
Цитата Сообщение от Argus19 Посмотреть сообщение
или скопируйте форму из примера
... скопировать, в vba Excel?
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
07.06.2024, 20:05 8
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
на компьютере usb-порт, всё.
При установке соответствующего драйвера, usb-порт появится в диспетчере устройств компьютера как СОМ-порт с определённым адресом.
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
То есть программирование на нижнем уровне.
Нижний уровень это ассемблер. И вам не будет позволено работать с портами компьютера. Можно работать только с драйвером.
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
Но если забыть про Excel, может быть тогда и пропустить, как промежуточное звено Visual Basic 6.0, где по-любому придётся работать с единичками и проверками контрольных сумм и всё такое прочее...
Работать надо с байтами. СОМ-порт передаёт и принимает байты. В конце фрейма Modbus RTU, что туда, что обратно, передаётся 2 байта контрольной суммы, которую придётся проверять. Точнее, проверять фрейм на соответствие контрольной сумме.
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
Если не ошибаюсь, Python способен на такое.
Не знаю.
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
скопировать, в vba Excel?
Создать аналогичную форму и скопировать в неё код. Создать модуль и скопировать в него код из исходного модуля.
Решить вопрос с автозапуском.
0
Модератор
Эксперт по электронике
8492 / 4349 / 1644
Регистрация: 01.02.2015
Сообщений: 13,503
Записей в блоге: 8
09.06.2024, 22:17 9
Возможно, отвечу не в тему...

Я бы попробовал несколько другой способ решения:
- в формате cvs сформировал список регистров, которые нужно считать из устройств
- сделал собственный скрипт для разбора этого списка и вызова по этим параметрам готовой утилиты modbus
- результаты от утилиты сохранил в cvs файле

Файлы cvs создаются, сохраняются, читаются и редактируются в Exel - это почти "родной" формат.


Когда-то в github встречался скрипт на Python для разового обращения к modbus slave устройству, адреса и прочие параметры обращения передаются через командную строку. Сейчас не вспомню название, но оно было на первой странице поиска.

Python для меня малознаком, а простенькие тестовые программки эпизодически делаю на FreePascal с использованием библиотек Synapse (работа с портом) и упрощенной самодельной функции чтения регистров хранения.

В январе решал вопрос о корректности чужой программы без исходников в Овен ПР200, для этого нужно было для нескольких состояний системы опросить по полсотни регистров и сравнить их значения, если они одинаковы - программу в ПР переписать.
За полчаса сделал такую простенькую программку на FPC
Кликните здесь для просмотра всего текста
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{$mode Delphi}
program test02;
 
uses
  Windows,
  SysUtils,
  synaser,
  fpaModBus;
 
type
  UnsignedInt16 = word;
  UInt16 = UnsignedInt16;
  Int16  = UnsignedInt16;
  SignedInt16 = smallint;
  SInt16 = SignedInt16;
  HexWord = word; {двухбайтовое число в 16-ричном формате}
  Binary = word;  {двухбайтовое число в двоичном формате}
  Float32 = single;
  Char8  = array [0..7] of char;
 
var
  Ser: TBlockSerial;
  uiR: UInt16;
  siR: SInt16;
  fR: Float32;
  cR: Char8;
  i: integer;
  nRes: integer;
begin
  Ser := TBlockSerial.Create;
  Ser.RaiseExcept := False;   //не обрабатываем исключения ошибок связи
  Ser.MaxLineLength := 255; {закрепим ограничение ModBus}
 
  try
    ser.Connect('COM3'); //ComPort
    if Ser.InstanceActive then // если подключились то настраиваем и работаем
    begin
      //   Sleep(1000);
      Ser.Config(115200, 8, 'n', SB1, False, False);
      writeln('Device: ' + Ser.Device + '   Status: ' + Ser.LastErrorDesc +
        ' ' + IntToStr(ser.LastError));
      Sleep(1000);
      Ser.purge;
 
 
      for i := 512 to 575 do
      begin
        nRes := MB_ReadUInt16(ser, 6, i, uiR);
        Write('nRes=', nRes: 4, ' HR[',i:3,']=', uiR: 5);
        writeln(' Device: ' + Ser.Device + '   Status: ' + Ser.LastErrorDesc +
          ' ' + IntToStr(ser.LastError));
      end;
 
    end
    else  // не подключились, ругаемся или ждем или пробуем по кругу
    begin
      //raise Exception.Create('Could not open device '+ ser.Device);
    end;
  finally
    Writeln('Serial Port will be freed...');
 
    if Ser.InstanceActive then
    begin
      Ser.Flush; // ждем до полного очищения буфера
      Ser.Purge; // если что то и есть до очищаем до конца
      Ser.CloseSocket; // отключаемся
    end;
    Ser.Free;
 
    Writeln('Serial Port was freed successfully!');
  end;
end.

Функция чтения и её применение для чтения uint16
Кликните здесь для просмотра всего текста
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
type
  TWordConvert = packed record
    case word of
      0: (w: word);
      1: (bl, bh: byte);
      2: (si: smallint);
  end;
  TDWordConvert = packed record
    case word of
      0: (dw: dword);
      1: (w0, w1: word);
      2: (b0, b1, b2, b3: byte);
      3: (f32: Float32);
  end;
  TBuffer = array [0..255] of byte;
 
const
  Timeout_1s = 1000;
 
function MB_ReadRegesters(var SerialPort: TBlockSerial;
  DevAddr, RegNo, RegCount: word; var ResBuffer): integer;
var
  Buffer: TBuffer;
  crc16: word;
  i: integer;
  ReadLen: word;
  Error: integer;
begin
  Error := 0;
  if not SerialPort.InstanceActive then
  begin
    //ComException('can not read from a closed port.');
    exit;
  end;
 
  if (DevAddr > 247) then
  begin
    if DevAddr > 40000 then
      DevAddr := DevAddr - 40001
    else
      exit;
  end;
{
Запрос
00 - адрес устройства
01 - функция
02 - адрес первого из группы считываемых регистров hi
03 - то же, lo
04 - количество считываемых регистров hi
05 - то же, lo
06 - crc16 lo
07 - то же hi
}
  Buffer[0] := lo(DevAddr);
  Buffer[1] := $03;
  Buffer[2] := hi(RegNo);
  Buffer[3] := lo(RegNo);
  Buffer[4] := hi(RegCount);
  Buffer[5] := lo(RegCount);
  crc16 := Crc16InitValue;
  for i := 0 to 5 do
    Crc16 := UpdateCrc16(Buffer[i], crc16);
  Buffer[6] := lo(crc16);
  Buffer[7] := hi(crc16);
 
  SerialPort.SendBuffer(@Buffer, 8);
  SerialPort.RecvBufferEx(@Buffer, RegCount * 2 + 5, Timeout_1s div 10);
 
{
Ответ в корректном случае
00 - адрес устройства
01 - функция
02 - количество байт в ответных данных
03 - данные lo
04 - данные hi
05 - CRC16 lo
06 - CRC16 hi
 
В случае ошибки
или таймаут
или устройство пришлёт
00 - адрес устройства
01 - (=$83) код функции с установленным старшим битом
02 - код ошибки (exception code)
03 - lo crc16
04 - hi crc16
}
 
  if Buffer[01] = $83 then
  begin
    Error := Buffer[02];
    ReadLen := 5;
  end
  else
  begin
    ReadLen := Buffer[2] + 3;
  end;
  Crc16 := Crc16InitValue;
  for i := 0 to ReadLen - 1 do
    Crc16 := UpdateCrc16(Buffer[i], crc16);
  if Crc16 <> Buffer[ReadLen] + 256 * Buffer[succ(ReadLen)] then
  begin
    //ошибка приёма пакета - не правильный crc16
  end
  else
  begin
    //writeln('CRC16 Ok');
  end;
  if RegCount * 2 = Buffer[02] then
  begin
    move(Buffer[3], TBuffer(ResBuffer), RegCount * 2);
  end
  else
  begin
    //ошибка приёма пакета - не правильное количество принятых байт
  end;
  Result := (SerialPort.LastError) * 256 + Error;
end;
 
function MB_ReadUInt16(var SerialPort: TBlockSerial; DevAddr, RegNo: word;
  var R: UInt16): integer;
begin
  Result := MB_ReadRegesters(SerialPort, DevAddr, RegNo, 1, R);
  R := Swap(R);
end;

В моих процедурах всё упрощено - это заготовки для быстрой диагностики проблем, а не решения для других...
1
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
09.06.2024, 22:53 10
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
Возможно, отвечу не в тему...
Думается, в тему.
Есть ещё вариант. Найти бесплатную SCADA-system с неограниченным сроком работы, но урезанным функционалом.
Тогда программирование и знать не надо.
0
5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
10.06.2024, 00:05  [ТС] 11
ФедосеевПавел,
Во-первых, спасибо, что присоединились к разговору.
А во-вторых, я ещё пока окончательно не решил, на каком языке программирования я остановлюсь.
Пока я рассуждаю примитивно просто.
1-й уровень, это языки, которые вообще не умеют работать с последовательным портом. К ним в частности относится и Вба Excel.
2-й уровень, это языки, которые умеют работать с последовательным портом, в частности это Visual Basic 5.0 и 6.0.
3-й уровень, это языки, в стандартные библиотеки которых входит и библиотека Мадбас. Это Питон и Си.
Поэтому, у меня пока идея найти хороший пример такой программе на Питоне и возможно немного адаптировать его под мои задачи.
На Питоне я никогда не работал, но думаю, это дело поправимое. Думаю, пусть это будет посредник между мной и моим устройством. Это будет "чёрный ящик", который общается с моим устройством по Мадбас и передаёт необходимые мне сведения. Ну и в случае надобности, посылает какие-то управляющие сигналы на моё устройство.
---
п.с. Кстати, я сейчас застрял на этапе установки Питона. Возможно, у Вас появится когда-нибудь желание подтолкнуть меня в теме:
Сокращение длины переменной PATH в Windows 7
===================================================
Цитата Сообщение от Argus19 Посмотреть сообщение
SCADA-system
Argus19,
Честно говоря, могу только догадываться, что это такое, но думаю, в любом случае мне нужен открытый код, чтобы я смог там хотя бы минимально что-то "допилить" под мои "хотелки".
===================================================
С уважением и благодарностью ___________ Юрий.
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
10.06.2024, 00:37 12
Цитата Сообщение от Юрий_Нд Посмотреть сообщение
Честно говоря, могу только догадываться, что это такое
https://ru.wikipedia.org/wiki/SCADA
0
Модератор
Эксперт по электронике
8492 / 4349 / 1644
Регистрация: 01.02.2015
Сообщений: 13,503
Записей в блоге: 8
10.06.2024, 00:52 13
Судя по выдаче поисковиков, для компилируемых языков довольно распространена libmodbus, а для Python - pymodbus.
У меня не было необходимости делать серьёзную программу, поэтому обошёлся Synaser и "велосипедом". Для серьёзного выбрал бы libmodbus (pymodbus). На их офсайтах видел множество примеров.

Предполагаю, переменная Path может переполняться от неочищенных путей для предыдущих версий каких-либо программ. Тут не знаю, что и посоветовать для очистки...
0
5 / 5 / 0
Регистрация: 25.06.2017
Сообщений: 571
10.06.2024, 09:01  [ТС] 14
Цитата Сообщение от ФедосеевПавел Посмотреть сообщение
Тут не знаю, что и посоветовать
... очень жаль.
======================================
Цитата Сообщение от Argus19 Посмотреть сообщение
SCADA-system
Да, именно это и является целью моей работы.
Только я хочу, чтобы я там хоть немножко что-то изменил для моих конкретных задач.
0
538 / 230 / 32
Регистрация: 22.09.2023
Сообщений: 650
10.06.2024, 09:41 15
Для начала нужно уяснить для себя, что ни через "железный" RS232 без написания собственнного драйвера уровня ядра, ни тем более через переходник USB-RS485 даже с написанием собственного драйвера, невозможно реализовать modbus-устройство, отвечающее требованиями спецификации modbus-RTU. Просто потому, что там требуется отслеживание интервалов 1.5 и 3.5 времени передачи байта.
Приложение VBA Exel: обращение к Slave-устройству по протоколу Modbus RTU через порт RS485


То есть или вы делаете какой-то аппаратный транслятор modbus-RTU во что угодно на микроконтроллере или забиваете на спецификацию и любое устройство с modbus-RTU имеет полное право отказаться работать с вашей программой.
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
10.06.2024, 12:26 16
Цитата Сообщение от Dushevny Посмотреть сообщение
даже с написанием собственного драйвера, невозможно реализовать modbus-устройство, отвечающее требованиями спецификации modbus-RTU.
Я писал программу на VB 6.0, с использованием контрола MaComm, которая опрашивала 4 прибора производства "ОВЕН". Ни каких проблем не было.
Писать собственный драйвер нет необходимости. Достаточно использовать драйвер, установленный в системе.

Цитата Сообщение от Юрий_Нд Посмотреть сообщение
Только я хочу, чтобы я там хоть немножко что-то изменил для моих конкретных задач.
Вы не описали ваши задачи, чтобы хоть как-то вас понять. Сколько приборов? Собираетесь ли вы их программировать, или только считывать данные и в каком количестве?

Добавлено через 24 минуты
Нашёл для VBA Excell:
Класс для COM-порта с поддержкой событий
Всё, что нужно сделать, реализовать протокол Modbus.
0
538 / 230 / 32
Регистрация: 22.09.2023
Сообщений: 650
10.06.2024, 14:49 17
Цитата Сообщение от Argus19 Посмотреть сообщение
Ни каких проблем не было.
Как вы отслеживали требуемые интервалы? Никак? То есть вы забили на спецификацию. "У меня все работает" - так себе аргумент. Понятно, что если у Юрия потом встанет какой-нибудь НПЗ - вас привлечь к ответственности не получится.
Приложение VBA Exel: обращение к Slave-устройству по протоколу Modbus RTU через порт RS485
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
10.06.2024, 16:28 18
Цитата Сообщение от Dushevny Посмотреть сообщение
Как вы отслеживали требуемые интервалы?
https://owen.ru/product/owen_as4
Он отслеживал.
0
538 / 230 / 32
Регистрация: 22.09.2023
Сообщений: 650
10.06.2024, 20:18 19
Цитата Сообщение от Argus19 Посмотреть сообщение
Он отслеживал.
Каким образом? Он понятия не имеет о Modbus RTU и требуемых ему интервалах.
0
534 / 376 / 76
Регистрация: 24.09.2017
Сообщений: 2,124
Записей в блоге: 13
10.06.2024, 20:33 20
Цитата Сообщение от Dushevny Посмотреть сообщение
Он понятия не имеет о Modbus RTU и требуемых ему интервалах.
Вопрос становится бесконечным.
У меня всё прекрасно работало через МsComm, Павел Федосеев привёл фрагмент кода, который так же прекрасно работает.
Каким образом вы реализовали протокол Modbus RTU?
0
10.06.2024, 20:33
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.06.2024, 20:33
Помогаю со студенческими работами здесь

Мой вариант реализации Modbus Slave RTU/ASCII на Arduino
Простая библиотека Modbas Slave для микроконтроллеров Arduino Здесь есть описание и видео обзор...

Эмулятор для Modbus RTU (slave и master) под Linux
Необходим эмулятор для отладки modbus rtu (slave и master). Работа предполагается только через...

Соединение S7-1200 c ПЧ FC51 по протоколу MODBUS RTU
Задача: считать задание в процентах с ПЧ FC51. Соединил контроллер S7-1200 (214-1AG40-0XBO) по...

Как сформировать запрос согласно протоколу Modbus RTU
Добрый день надо сформировать запрос согласно протоколу Modbuss RTU при нажатии кнопки отправить...

Сформировать запрос на чтение данных по протоколу modbus rtu
Добрый вечер! Появилась задача написать программку для master modbus rtu (на Borland C++ и...

Приложение для управления устройством по modbus RTU
Необходимо написать приложение для управления девайсом по modbus RTU. функция чтения 0х03, записи -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru