2014-01-28 3 views
0

У меня есть этот код MATLAB:Modbus TCP и MATLAB

function [s] = serialstart(opt) 
% Function for initializing a serial interface in matlab for interfacing 

% Functions using the serial port must be passed the serial port object 
% s in order for the serial port to be accessible. 

port = 502; 

s = tcpip('192.168.2.177',port); 
%????? 
set(s, 'InputBufferSize', 3000000); 

% Initialize serial port on specified com port 
    date_addr = 40001; 
date_num=1; 
date_addr_high = floor(date_addr/100); 
date_addr_low = mod(date_addr,100); 
date_num_high = floor(date_num/100); 
date_num_low = mod(date_num,100); 
%Open serial connection 
fopen(s); 

% Specify Terminator 
s.terminator='CR/LF'; 

fwrite(s,0,'char')      %Transactio identifier  0x00 
fwrite(s,0,'char')      % Transactio identifier  0x00 
fwrite(s,0,'char')      % Protokol identifier  0x00 
fwrite(s,0,'char')      % Protokol identifier  0x00 
fwrite(s,0,'char')      %  Data Bytes 0x00 
fwrite(s,1,'char')      %   Data Bytes  0x06 
fwrite(s,255,'char')      %  unit identifier 0xff 
fwrite(s,3,'uint8')      % Function   0x03 
fwrite(s,date_addr_high,'uint8')   %Register High Byte 
fwrite(s,date_addr_low,'uint8')   %Register Low Byte 
fwrite(s,date_num_high,'uint8')   %How many Register Low Byte 
fwrite(s,date_num_low,'uint8')  %How many Register High Byte 

out = fread(s,1,'char');     

fclose(s); 

но я получаю следующий ответ:

Предупреждения: Неудачные чтения: Указанный объем данных не был возвращен в Тайме-ауте период.

Вот настройки для объекта TCPIP:

TCPIP Object : TCPIP-192.168.2.177 

Communication Settings 
RemotePort: 502 
RemoteHost: 192.168.2.177 
Terminator: 'CR/LF' 
NetworkRole: client 

Communication State 
Status: closed 
RecordStatus: off 

Read/Write State 
TransferStatus: idle 
BytesAvailable: 0 
ValuesReceived: 0 
ValuesSent: 12 

соединение было успешным, но я не получаю никаких данных. Я не знаю, как получить любую Дату.

EDIT:

Я добавил это в конце:

while ~s.BytesAvailable 
end 
s.BytesAvailable 
res=fread(s,s.BytesAvailable)     
fclose(s); 

Теперь я не получаю никакого ответа.

ответ

0

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

+0

Спасибо за ваш ответ. Для чтения данных я сделал цикл while.bytesAvailable while. Я получаю 52 значения, теперь мне нужно выяснить, какое значение для регистра. – knuppel

+0

Я предлагаю использовать обратный вызов ['BytesAvailableFcn'] (http://www.mathworks.com/help/instrument/bytesavailablefcn.html) вместо использования цикла' while', чтобы проверить, когда у вас есть данные, - таким образом вам не нужно постоянно активно проверять наличие новых данных. –

+0

Я добавил это в конце: в то время как ~ s.BytesAvailable конец s.BytesAvailable Рез = Fread (с, s.BytesAvailable) fclose (ы); Я не получаю ответа – knuppel

2

Я знаю, что это старый пост, поэтому я не хочу его подбадривать, но у меня есть Modbus TCP, работающий с Matlab, и это одна из сообщений, которые я натолкнулся, когда я пытался заставить ее работать , поэтому я решил, что опубликую здесь ответ.

Я предоставлю это, сказав, что это делается с помощью инструментальной панели инструментов для Matlab, так как это необходимо для команды tcpip(). Я буду работать над тем, чтобы это работало без инструментария позже, так как получение всего инструментария только для Modbus TCP является излишним, но для быстрого развития пробной версии инструментария достаточно, чтобы немного помочь вам.

Таким образом, первый настроить порт:

IPADDR='192.168.0.1'; 
PORT=502; 
tcpip_pipe=tcpip(IPADDR, PORT); 
set(tcpip_pipe, 'InputBufferSize', 512); 
tcpip_pipe.ByteOrder='bigEndian'; 

Затем откройте порт:

try 
    if ~strcmp(tcpip_pipe.Status,'open') 
     fopen(tcpip_pipe); 
    end 
    disp('TCP/IP Open'); 
catch err 
    disp('Error: Can''t open TCP/IP'); 
    return; 
end 

Теперь, что я нашел в работе, чтобы подготовить сообщение целиком, а затем записать целая вещь сразу. Это помогает, я думаю, потому, что вы указываете endianness с te .ByteOrder выше, так что вам действительно не нужно беспокоиться о том, как он настраивается дальше, или если вы пишете сообщения в правильном порядке и т. Д.

Так что теперь, расстройство того, как структурировать сообщение Modbus TCP:

  1. ID транзакции - Это поле 2 байта, которое может быть любое произвольное число, которое вы хотите. Как правило, вы увеличиваете это значение на 1 каждый раз, когда вы отправляете сообщение. Устройство, которое вы передаете, будет повторять этот номер обратно, когда он отвечает, поэтому вы можете быть уверены, что будете разбирать данные для конкретного запроса. Если идентификатор транзакции в ответе не соответствует тому, что вы отправили, вы должны отказаться от данных.
  2. Протокол - Это 2-байтовое поле, которое должно быть всем нулем для указания Modbus TCP. Довольно просто.
  3. Байт Осталось - Это 2-байтовое поле, в котором указано, сколько байтов осталось в сообщении. Просто добавьте все байты; это число, которое здесь происходит.
  4. Ведомый ID - Это 1-байтовое поле. Сначала я понял, что это значение немного запутанно, но учтите следующее: вы используете Modbus TCP - у вас уже имеют прямое подключение к ведомому, потому что вы подключаетесь к указанному выше IP-адресу. Назначение идентификатора ведомого здесь, если вы используете маршрутизатор Modbus TCP-RTU, где ваше сообщение будет транслироваться в сети RTU. В этом случае вы пытаетесь указать адрес устройства за маршрутизатором в сети RTU. Если устройство, с которым вы пытаетесь установить соединение, совпадает с тем, которое вы указали для IP-адреса, тогда вам не нужно использовать идентификатор ведомого устройства. Значение, которое вы должны отложить, если вы его не используете, равно 255. Итак, tl; dr - если вы не делаете что-то сложное с Modbus, поставьте 255 для этого значения.
  5. Идентификатор функции - Это 1-байтовое поле. Это номер, который соответствует specific function code, который инструктирует устройство, что делать. В моем случае все, что я хотел сделать, это чтение регистров, поэтому мой идентификатор функции был 4 каждый раз.
  6. Данные - Это может быть все, что настроено вашим устройством, но есть несколько случаев «по умолчанию», которые я объясню, поскольку они должны быть довольно универсальными. Как правило, при отправке сообщения на устройство (ведомое устройство) данные будут представлять собой два значения по 2 байта, где первое 2-байтовое значение является адресом конкретного регистра, а второе 2-байтовое значение - либо числом регистры для чтения или значение, которое должно быть записано в этот регистр.

Итак, давайте попробуем пример. Я хочу, чтобы код транзакции был 3 (опять же, произвольное число, которое я выбираю и увеличиваю с каждой передачей, чтобы позволить мне соответствовать ответу на конкретную передачу). Я хочу, чтобы код функции был 4 (чтение регистров), я хочу начать с регистра 0, и я хочу читать 12 регистров. Для записи регистр обычно составляет 2 байта, поэтому это означает, что я хочу начать с регистра 0 и готовых 24 байтов информации.

Это сообщение выглядит следующим образом:

message = [... 
    %*** TRANSACTION ID ***% 
    uint8(0); ... % 
    uint8(3); ... % Two byte transaction ID 
    %*** PROTOCOL ***% 
    uint8(0); ... % 
    uint8(0); ... % Two byte protocol ID - all zeros means Modbus TCP 
    %*** BYTES REMAINING ***% 
    uint8(0); ... % 
    uint8(6); ... % Two byte number of bytes for everything after this 
    %*** SLAVE ID ***% 
    uint8(255); ... % Slave ID - use if end device is after a modbus tcp/rtu router, otherwise use 255 
    %*** FUNCTION ID ***% 
    uint8(4); ... % 4 - read input registers 
    %*** DATA ***% 
    %***** Starting Register *****% 
    uint8(0); ... % 
    uint8(0); ... % Two byte number that gives the starting register to read 
    %***** Number of Registers to Read *****% 
    uint8(0); ... % 
    uint8(12)]; % Two byte number that gives how many registers to read 

Теперь пишу это сообщение для устройства:

fwrite(tcpip_pipe, message,'int8'); 

Затем ждать ответа:

while ~tcpip_pipe.BytesAvailable,end 

А потом прочитанные возвращенные данные:

response = fread(tcpip_pipe,tcpip_pipe.BytesAvailable); 

Информация заголовка должна быть как ожидалось. Опять же, если идентификатор транзакции не соответствует тому, что вы отправили, вы должны отказаться от сообщения. Код функции должен совпадать с тем, что вы отправили. Если это не так, это, вероятно, ошибка: error function code - это то же, что и вы отправили, плюс 128. Таким образом, в моем примере я хотел прочитать входные регистры (код функции 4), и если есть ошибка (например, мое сообщение isn 't отформатирован правильно, укажите неверный номер регистра и т. д.), тогда код функции, который я получу в ответе, будет 4 + 128 = 132.

В качестве последнего замечания добавлю, что первый байт в ответе на команду чтения будет количество регистров (а не байтов!регистр - два байта), которые следуют в ответе, что кажется мне лишним, потому что в заголовке Modbus TCP уже есть длина полезной нагрузки, но я не делал протокол.

Надеюсь, это очень хороший пример того, как работает Modbus TCP, и весь код представлен кодом Matlab прямо из моего сценария функционирования, поэтому он должен работать на вас. Если вам нужна дополнительная информация о точных сообщениях, которые вы должны отправлять и получать, ознакомьтесь с Wikipedia page на Modbus. Когда вы это понимаете, все довольно просто.

Смежные вопросы