PDA

Просмотр полной версии : СЧИТЫВАНИЕ ДАННЫХ ПО MODBUS RTU В МНОГОМЕРНЫЙ МАССИВ ДАННЫХ



Maria
15.02.2016, 12:57
Здравствуйте!
Подскажите, пожалуйста, можно ли осуществить считывание данных панелью СПК207 по MODBUS RTU в многомерный массив вида ARRAY [1..2] OF ARRAY [1..79] OF WORD?
В моем примере имеется переменная DataInput:ARRAY [1..2] OF ARRAY [1..79] OF WORD.
При конфигурировании каналов MODBUS RTU и привязке их к переменным программы я указываю: Application.MIRS.DataInput[1][1]. Как я выяснила, такое обращение не корректно. Можно ли осуществить данную задачу или считывание осуществляется только в одномерный массив?
22640

Евгений Кислов
15.02.2016, 13:04
В моем примере имеется переменная DataInput:ARRAY [1..2] OF ARRAY [1..79] OF WORD.
При конфигурировании каналов MODBUS RTU и привязке их к переменным программы я указываю: Application.MIRS.DataInput[1][1]. Как я выяснила, такое обращение некорректно.

Добрый день.
Каким образом вы это выяснили?

Yegor
15.02.2016, 13:10
Конфигуратор среды ожидает одномерный массив, и вероятно, поэтому просто так подставить многомерный нельзя. Но можно:
а) воспользоваться библиотекой SysLibMem (или SysMem — не помню, как в третьем кодесисе), а именно функцией SysMemCpy, чтобы скопировать содержимое одномерного массива в многомерный в один приём;
б) просто объявить указатель на многомерный массив, присвоить ему адрес одномерного массива, и обращаться через указатель.


VAR
plainArray: ARRAY [0..79] OF WORD;
ptrMdArray: ARRAY [1..2] OF ARRAY[0..39] OF WORD;
END_VAR


ptrMdArray := ADR(plainArray);


test := ptrMdArray^[1][23];

Maria
15.02.2016, 13:25
Добрый день.
Каким образом вы это выяснили?

Т.к. возникает ошибка при компиляции.

Евгений Кислов
15.02.2016, 13:26
Т.к. возникает ошибка при компиляции.

Тогда покажите ее, пожалуйста. Какой версией CODESYS вы пользуетесь?

Maria
15.02.2016, 13:33
Тогда покажите ее, пожалуйста. Какой версией CODESYS вы пользуетесь?

Версия CODESYS V3.5 SP6 Patch 4
22641

Евгений Кислов
15.02.2016, 13:40
Версия CODESYS V3.5 SP6 Patch 4
22641

У вас имя ФБ совпадает с именем slave-устройства. Попробуйте задать им разные имена. Если ошибки не исчезнут, выкладывайте архив проекта.

Maria
15.02.2016, 14:11
Да, все верно, ошибки были из-за одинаковых имен.
Спасибо!

Maria
16.02.2016, 08:47
У меня возник еще один вопрос, связанный со считыванием данных.
Есть устройство, с которого необходимо считать данные по Modbus RTU в обычный одномерный массив (рисунок 1).
22655
В том случае, когда я объявляю функциональный блок в программе PLC_PRG (рисунок 5), данные с опрашиваемого устройства приходят корректно (рисунок 4)
22657
22658
Если я объявляю функциональный блок в списке глобальных переменных GVL (рисунок 2) и не объявляю его в PLC_PRG (рисунок 6), тогда данные с устройства в массив не приходят (рисунок 3)
22659
22660
22661
Получается, что так делать нельзя?

Евгений Кислов
16.02.2016, 09:00
У меня возник еще один вопрос, связанный со считыванием данных.
Есть устройство, с которого необходимо считать данные по Modbus RTU в обычный одномерный массив (рисунок 1).
22655
В том случае, когда я объявляю функциональный блок в программе PLC_PRG (рисунок 5), данные с опрашиваемого устройства приходят корректно (рисунок 4)
22657
22658
Если я объявляю функциональный блок в списке глобальных переменных GVL (рисунок 2) и не объявляю его в PLC_PRG (рисунок 6), тогда данные с устройства в массив не приходят (рисунок 3)
22659
22660
22661
Получается, что так делать нельзя?

Выложите архив проекта, пожалуйста.

Maria
16.02.2016, 09:13
https://yadi.sk/d/tqw8VMdbouKzg

Евгений Кислов
16.02.2016, 12:53
https://yadi.sk/d/tqw8VMdbouKzg

Проверил проект - обмен идет. Не обращайте внимания на надпись NoBP в компоненте Modbus - смотрите на значения переменных в программе.

На скриншоте - считал из слэйва число 10 в один из элементов массива.

22668

Maria
16.02.2016, 13:10
Спасибо за ответ!

Zerling
22.06.2022, 06:01
Здравствуйте, не хочу новую тему открывать.
По нестандартному протоколу приходит(буфер) массив байт, его хочу преобразовать в массив типа INT.

решил через цикл FOR записывать из буфера в двумерный массив
Как присвоить значения из одномерного массива в двумерный?

-------------------
a_a_byte: ARRAY [1..10] OF ARRAY [1..2] OF byte;
a_byte: OF ARRAY [1..20] OF byte;
i, w :int;// i - номер массива байт; w- номер байта массива
-------------
a_a_byte[i,w]:=a_byte[i+5],a_byte[i+4] --компилятор ругается,а я не знаю как правильно..

Евгений Кислов
22.06.2022, 06:15
Здравствуйте, не хочу новую тему открывать.
По нестандартному протоколу приходит(буфер) массив байт, его хочу преобразовать в массив типа INT.

решил через цикл FOR записывать из буфера в двумерный массив
Как присвоить значения из одномерного массива в двумерный?

-------------------
a_a_byte: ARRAY [1..10] OF ARRAY [1..2] OF byte;
a_byte: OF ARRAY [1..20] OF byte;
i, w :int;// i - номер массива байт; w- номер байта массива
-------------
a_a_byte[i,w]:=a_byte[i+5],a_byte[i+4] --компилятор ругается,а я не знаю как правильно..

Добрый день.

Отвечая на конкретный вопрос - проще всего добавить в проект библиотеку CAA Memory и сделать так:


MEM.MemMove(ADR(a_byte), ADR(a_a_byte), SIZEOF(a_a_byte) );

Но если "по нестандартному протоколу приходит(буфер) массив байт", то можно сразу разместить эти байты в "массиве типа INT" без использования каких-то промежуточных двумерных и одномерных байтовых массивов.

Zerling
22.06.2022, 10:57
не понимаю, как собрать из байт int без промежуточных вариантов. Я сделал объединение, чтоб указывать объединение.массивбайт[3]:=байт_буфера[4]; объединение.массивбайт[4]:=байт_буфера[3];

Евгений Кислов
22.06.2022, 11:00
не понимаю, как собрать из байт int без промежуточных вариантов. Я сделал объединение, чтоб указывать объединение.массивбайт[3]:=байт_буфера[4]; объединение.массивбайт[4]:=байт_буфера[3];

Покажите скриншотом фрагмент кода, в котором у вас "по нестандартному протоколу приходит(буфер) массив байт".
А лучше - вырежите этот фрагмент и выложите в виде небольшого демонстрационного проекта.

melky
22.06.2022, 11:41
Zerling
BitConverter.ToInt(массив байт, позиция). более правильнее посмотрите в справке. возможно предварительно надо будет переставлять байты. в зависимости в куда, функция возьмет требуемое количество байт с указанной позиции.

ой, тут по ПЛК, извиняюсь :)

Zerling
23.06.2022, 07:33
Код пока не написан, только разбираюсь, что к чему.
Принимаю посылку через CAA COM.Read / OCL.UNM_SerialRequest, дальше - фб в котором отделяю и собираю адрес и значение переменной(сейчас использую одну, а потом нужно будет с десяток). Собственно, поэтому и использовал юнион - не знаю других способов собрать из двух байт тип инт.

Евгений Кислов
23.06.2022, 07:36
CAA COM.Read / OCL.UNM_SerialRequest возращают считанные данные по указателю - то есть можно передать на входы pBuffer / pResponse адрес чего угодно - например, сразу массива INT'ов.

Zerling
23.06.2022, 07:59
Я так изначально делал, увидел кашу внутри и понял, что нужно менять порядок байтов. Сейчас собрался использовать массив из объединения.

Наверное, просто нужно написать фб, заменяющий значения в массиве, а его отправлять в массив INT

Zerling
01.07.2022, 06:36
FUNCTION_BLOCK buff2int
VAR_INPUT
Pt_of_buff: POINTER TO ARRAY [1..255] OF BYTE;//
Pt_of_int: POINTER TO ARRAY [1..125] OF INT;//
END_VAR
VAR_INPUT
x_START: BOOL;// Старт пересборки буфера
END_VAR
VAR
i: byte;// шаг FOR/ номер ячейки буфера байт
m: BYTE;// Номер ячейки выходного массива
dut_var: W2ab;// объединение, массив 2 байта + инт
END_VAR


IF x_START THEN i := 0; END_IF
FOR i := 1 TO 20 DO ///20 условно, нужно смотреть или 3 или 7 ячейку для определения размера пакета
m:=i/2; // номер ячейки конечного массива
IF i.0 THEN //смотрим бит. тру значит число нечетное
// присваиваем значение из нечетной ячейки массива в [0] подъячейку объединения
MEM.MemMove(ADR(Pt_of_buff^[i]), ADR(dut_var.ab_digit[0]), SIZEOF(Pt_of_buff^[i]) );
ELSE
//присваиваем значение из четной ячейки массива в [1] подъячейку объединения
MEM.MemMove(ADR(Pt_of_buff^[i]), ADR(dut_var.ab_digit[1]), SIZEOF(Pt_of_buff^[i]) );
//по идее - ИНТ число уже сформировано, его можно записать в массив инт
MEM.MemMove(ADR(dut_var), ADR(Pt_of_int^[m]), SIZEOF(dut_var) );

END_IF END_FOR



получилось как-то так...