Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Компоненты Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.05.2022, 12:09   #1
geb2010
Пользователь
 
Регистрация: 15.10.2012
Сообщений: 25
По умолчанию Связь СП270 с ПК Дельфи

Здравствуйте !
Подскажите как написать функцию передачи данных пакетом программы Дельфи (мастер)
через ComPort для панели СП270 (slave) по протоколу Modbus RTU ?
Подключение СП270 разъем download к ПК разъем сом1 кабелем (RX->TX, TX->RX, GND).
Программирование СП270 по этому кабелю происходит нормально.
Панель СП270 подключена к ПК по RS232.
Параметры связи указаны одни и те же для СП270 и ПК:
скорость - 115200, бит - 8, стоп-бит - 1, четность - нет.
Строку по протоколу Modbus RTU для передачи я сформировал :

Для записи числа 88 [0058h] в панель СП270 с адресом 2[02h] в ячейку с адресом 300 [012Ch]
по протоколу Modbus RTU сформирована строка:
"02 06 01 2C 00 58 48 36 0D 0A"
где:
[02] – адрес панели СП270
[06] – функция записи в один регистр
[01 2С] – адрес записываемого регистра
[00 58] – данные для записи
[48 36] – контрольная сумма, 48 мл. байт, 36 ст. байт
[0D 0A] - признак окончания пакета

Передавал пакет с помощью функции, найденной в инете:

function PostComm(var Buf; size: word): integer;
var p: pointer; i: DWord;
begin
p := @Buf;
result := 0;
while size > 0 do begin
if not(WriteFile(f, p^, 1, i, nil)) then begin
Form1.Edit2.Text:='Передача не выполнена .';
exit;
end;
inc(result, i);
inc(integer(p));
dec(size);
Application.ProcessMessages;
end;
end;
// передача данных по нажатию кнопки
procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var str1: string; k1, l: integer;
begin
str1:=Edit1.Text;
// забиваем массив данными попарно
SetLength(buf, (Length(str1)+4) div 2);
k1:= 1;
for l := 0 to High(buf)-2 do begin
// преобразуем str1 в массив данных buf
buf[l] := StrToInt( '$' + Copy(str1, k1, 2) );
Memo1.Lines.Add('l: ' + IntToStr(l) + ' Äàííûå: ' + IntToStr(buf[l]));
k1 := k1 + 2;
end;
k1:=High(buf);
PostComm(Buf, k1);
end;

Посылал строкой - панель не реагирует, предполагаю что нужно
передавать пакетом, а как это сделать не знаю.
geb2010 вне форума Ответить с цитированием
Старый 07.05.2022, 12:53   #2
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,534
По умолчанию

Modbus RTU - бинарный протокол, ничего преобразовывать в строку не надо, передавать "как есть". 0D 0А в Modbus RTU не имеет смысла, длина пакета определяется счётчиком (третий байт), а не признаком 0D 0А. В вашем примере его нет. КС считалась как CRC - или именно как КС? Судя по остальному, о CRC понятия нет ?
В общем, попытка скрестить ежа и ужа (RTU и ASCII) провалилась.
А что, к етой панели нет описания? Выйти на панель без описания - рисково.
-------------------
Совет банальный до неприличия, но от этого не ставший менее верным: RTFM (Read The Fucking Manual)
https://ipc2u.ru/articles/prostye-resheniya/modbus-rtu/

Последний раз редактировалось digitalis; 07.05.2022 в 13:01.
digitalis вне форума Ответить с цитированием
Старый 07.05.2022, 15:36   #3
geb2010
Пользователь
 
Регистрация: 15.10.2012
Сообщений: 25
По умолчанию

digitalis
Контрольная сумма подсчитана как CRC16 и соответствует протоколу Modbus RTU.
Пример пакета взятый
по Вашей ссылке мой
11 Адрес устройства 02
06 Функциональный код 06
00 Адрес первого регистра Hi байт 01
01 Адрес первого регистра Lo байт 2C
00 Значение Hi байт 00 00
03 Значение Lo байт 03 58
9A Контрольная сумма CRC 48
9B Контрольная сумма CRC 36

Я не вижу, чтобы в пакете указано в третьем байте его длина ?
3 и 4 байты - адрес ячейки, в которую надо записать число из
5 и 6 байтов. Я понимаю так.
Вы меня не поняли - подскажите как послать этот пакет через Com1 ?
geb2010 вне форума Ответить с цитированием
Старый 07.05.2022, 16:10   #4
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,534
По умолчанию

Да очень просто. Вот это - выбросить.
Код:
buf[l] := StrToInt( '$' + Copy(str1, k1, 2) );
Memo1.Lines.Add('l: ' + IntToStr(l) + ' Äàííûå: ' + IntToStr(buf[l]));
И просто передать:
Код:
PostComm(Buf, k1);
Я не разбирался, как у вас сформирован буфер для передачи, но в вышеприведённом, в отличие от того, что по моей ссылке - нет количества байт.
А сам СОМ-порт открыт на передачу ? Мне через нативный СОМ-порт не приходилось работать, у нас была сеть через USB-UART, использовалась фирменный драйвер от FTDI, поэтому более детальный совет дать не могу.
Не получил ответа на вопрос: документация на эту панедь у вас есть? Примеры обмена есть? Если есть - они проверены и работают?
Хоть какой-нибудь ответ панель даёт?
-------------------------------
Посмотрел доку на эту приблуду... Называется: "Сделано на от...ись", только чтоб было. И многочисленные форумы по этой штуке ясности не добавляют. Не хотел бы я работать с этим...
Изображения
Тип файла: jpg MB.jpg (20.0 Кб, 50 просмотров)

Последний раз редактировалось digitalis; 07.05.2022 в 16:36.
digitalis вне форума Ответить с цитированием
Старый 07.05.2022, 17:06   #5
geb2010
Пользователь
 
Регистрация: 15.10.2012
Сообщений: 25
По умолчанию

digitalis
У Вас на изображении функция чтения, а у меня используется функция записи.
Буфер объявлен стандартно - buf: array of byte.
Порт инициализируется функцией PortInit -
function PortInit : boolean; // инициализация Сом порта
var ct: TCommTimeouts;
dcb: TDCB;
begin
f := Windows.CreateFile(PChar('COM1'), GENERIC_READ or
GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (f < 0) or not Windows.SetupComm(f, 2048, 2048) or
not(Windows.GetCommState(f, dcb)) then exit; //init error
dcb.BaudRate :=115200;
dcb.StopBits :=1;
dcb.Parity :=0;
dcb.ByteSize :=8;
if not(Windows.SetCommState(f, dcb)) or
not(Windows.GetCommTimeouts(f, ct)) then exit; //error
ct.ReadTotalTimeoutConstant :=50;
ct.ReadIntervalTimeout :=50;
ct.ReadTotalTimeoutMultiplier :=1;
ct.WriteTotalTimeoutMultiplier :=0;
ct.WriteTotalTimeoutConstant :=10;
if not(Windows.SetCommTimeouts(f, ct)) or
not(Windows.SetCommMask(f, EV_RING + EV_RXCHAR +
EV_RXFLAG + EV_TXEMPTY)) then exit; //error
result :=true;
end;
Может перед передачей данных надо Сом порту конкретно указать,
в каком режиме работать - на передачу или прием ?
Я думал, что при инициализации указано -
GENERIC_READ or GENERIC_WRITE, то этого достаточно.
Документация на панель СП270 есть. Из нее и взята строка для передачи.
Если передача прошла успешно, то на панели по указанному адресу появляются
переданные данные, в ответ панель присылает эти же данные.
У меня на панели ничего не происходит и ответа никакого нет.
Я вообще то планирую передавать и принимать данные по RS-485.
То если не трудно напишите как это делаете.
Я попробую связь по RS-485, может по ней получится?

Последний раз редактировалось geb2010; 07.05.2022 в 20:26.
geb2010 вне форума Ответить с цитированием
Старый 07.05.2022, 21:49   #6
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,534
По умолчанию

Давно это было, больше 10 лет тому... Я же писал: я использовал фирменный драйвер FTDI для FT232, поэтому там файловый принцип передачи-приёма не использовался. Надо спрашивать у ребят, которые организовыали связь по RS232 без привязки конкретно к Modbus, это их отпугнёт
А попробовать просто передать что-нить не из Дельфийской программы, а штатной терминалкой? Может быть, нужен полный кабель, не только Tx,Rx, а со всеми этими DTR, DSR, RTS, CTS и др.?
Я вот в дружественный форум radiokot.ru запостил вопрос - пока глухо. Никто этим снятым с пр-ва дивайсом не пользуется.

Последний раз редактировалось digitalis; 07.05.2022 в 21:57.
digitalis вне форума Ответить с цитированием
Старый 08.05.2022, 07:42   #7
geb2010
Пользователь
 
Регистрация: 15.10.2012
Сообщений: 25
По умолчанию

digitalis
Я знаю, что панель СП270 снята с производства. У нас уже 12 лет работают 3 пресса под управлением контроллеров АДАМ 5510 и СП270 используется для отображения инфы. Я писал для контроллеров программы, но в них использовались готовые dll для связи с СП270 и проблем не было.
А сейчас нужно сделать для станка пропитки модуль измерения скорости и метража, руководство не хочет покупать дорогие АДАМы. Я уже сделал на Ардуино и осталось только связать Ардуину с ПК для архивации и отображения текущих данных на СП270. Спасибо за посильную помощь, попробую связать по RS-485, но думаю не понимая точно как надо передавать не получится.
geb2010 вне форума Ответить с цитированием
Старый 08.05.2022, 12:19   #8
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,534
По умолчанию

Имея саму приблуду под рукой, на порядок проще довести её до ума. А то "брачная ночь дисстанционно" не приносит удовлетворения, как правило, ни одному из её участников. А на родственном форуме я кинул клич - никто не отозвался. Видно, не нашлось работавших с ней.
Вещь занятная. В былые времена сам бы с такой поигрался. Любопытно: она приходит "голой" в смысле картинки, и все контролы и окружение в неё надо запихивать при конфигурации - или же картинка поставляется уже готовой по заказу? По логике д.быть первый вариант.
Мне когда-то пришлось делать отдалённо похожее, но я имел чистый графический дисплей, и весь сценарий на нём реализовывал программно, по SPI. C Адамом (без Евы ) тоже имел дело, но в другом проекте. Там на одном конце - комп, на другом - сетка наших изготовленных устройств. Так что проблем не было - что хотим, то и воротим, оба конца под нашим контролем. По RS485. Позже я понял, что зря покупали этого парня: связка из 2 копеечных микросхем делала бы всё то же самое.
----------------
PS У нас был другой Агдам - не ПЛК, а просто преобразователь интерфейсов.
Кстати, если бы был тестер интерфейсов - можно было бы врезаться в линию и проследмить в уже работающем оборудовании - что и как там передаётся и принимается.
Но:
1.У вас такого тестера нет? (хотя можно сделать из ноутбука и микросхемы преобразователя интнрфейсов)
2. Кто ж вам позволит?
------
PPS В первом (см.выше) варианте д.быть очень детальное руководство для программиста: как готовить эту картинку и как её заливать конфигуратором (а не просто - соединить кабелем и нажать кнопочку) .

Последний раз редактировалось digitalis; 08.05.2022 в 12:31.
digitalis вне форума Ответить с цитированием
Старый 08.05.2022, 17:29   #9
geb2010
Пользователь
 
Регистрация: 15.10.2012
Сообщений: 25
По умолчанию

digitalis
Я писал выше, что панель СП270 уже используется у нас, и программу для ее опроса и саму ее конфигурацию делал я. Не ожидал, что у меня возникнет такая проблема ?! Саму панель при конфигурации заполняешь сам как хочешь. В работающей панели используется три экрана - главный и два вспомогательных. Панель разработана в "ОВЕН", на ихнем сайте есть описание на конфигуратор. В нем все подробно описывается как и что.
geb2010 вне форума Ответить с цитированием
Старый 28.05.2022, 09:52   #10
FPaul
Форумчанин
 
Регистрация: 25.01.2015
Сообщений: 472
По умолчанию

Для связи - чтения и записи в Овен ТРМ212 по RS485 использовал библиотеку SynAser из общего пакета Synapse.
http://synapse.ararat.cz/doku.php/download

Делал просто тестовую программу для изучения протокола, ничего серьёзного. Для серьёзных целей нужно как-то с потоками делать.

Посмотрите мой пример, он на FreePascal, но смысл будет понятен. Единственно, запись группы регистров не проверял, только одиночные регистры и то - недолго, чтобы не изнашивать память ТРМ212 - поэтому в сохранившемся исходнике нет записи.
Код:
{$mode Delphi}
program test02;

uses
  Windows,
  SysUtils,
  synaser,
  fpaModBus,
  _Owen_Trm212_Rtu;

var
  ModBusSetting_Prot: Int16 = trm212Prot_RTU;
  ModBusSetting_ALEn: Int16 = trm212A_LEn_8bit;
  ModBusSetting_Addr: Int16 = $0008;

  CommSetting_bPS: Int16 = trm212bPS_115200;
  CommSetting_LEn: Int16 = trm212Len_8bit;
  CommSetting_PrtY: Int16 = trm212PrtY_None;
  CommSetting_Sbit: Int16 = trm212Sbit_2bit;
var
  ser: TBlockSerial;
  uiR: UInt16;
  siR: SInt16;
  fR:  Float32;
  cR:  Char8;
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', SB2, False, False);
      writeln('Device: ' + Ser.Device + '   Status: ' + Ser.LastErrorDesc +
        ' ' + IntToStr(ser.LastError));
      //   Sleep(1000);
      Ser.purge;

      MB_ReadUInt16(ser, ModBusSetting_Addr, trm212SP, uiR);
      Writeln(uiR);
      Sleep(100);
      MB_ReadSignedInt16(ser, ModBusSetting_Addr, trm212SP, siR);
      Writeln(siR);
      Sleep(100);
      MB_ReadFloat32(ser, ModBusSetting_Addr, trm212SP_, fR);
      Writeln(fR: 0: 1);
      Sleep(100);
      MB_ReadChar8(ser, ModBusSetting_Addr, trm212DEV, cR);
      Writeln(cR);
      Sleep(100);
      MB_ReadChar8(ser, ModBusSetting_Addr, trm212VER, cR);
      Writeln(cR);
    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.
И модули в архиве
Вложения
Тип файла: 7z ModBus_Synaser.7z (4.3 Кб, 3 просмотров)
FPaul вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
связь SQL pakusya БД в Delphi 7 14.05.2013 13:25
BDE связь Defender42 Общие вопросы Delphi 11 24.09.2012 18:43
таблицы подстановок в дельфи(базы данных в дельфи) ManiagoZ БД в Delphi 0 15.05.2011 15:07
Связь BP WIN c ER WIN Yaga Помощь студентам 1 04.06.2008 22:39
Связь с БД Elena БД в Delphi 4 03.05.2007 16:08