PDA

Просмотр полной версии : C# NModbus4+ПЛК63: Расшифровка значений



fillpackart
24.02.2016, 10:05
Здравствуйте! Я опрашиваю ПЛК с помощью библиотеки NModbus4 на C#, столкнулся с такой проблемой: Я считываю значения, но не могу их правильно преобразовать.
Например есть величина "температура смещения", в ПЛК её значение равно 57, я считываю её по нужному адресу регистра вот таким образом:
p.Ts = mbus.ReadHoldingRegisters((byte)p.Addres, 86, 1)[0];
В итоге прочитанное значение равняется 22. А например при значении на ПЛК 59 градусов прочитанное - 17.
Как быть?

Yegor
24.02.2016, 12:42
Код показать для начала.

fillpackart
24.02.2016, 13:19
код чего именно вам нужен? Функции опроса? Или всего проекта?

функция опроса:


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
EFDbContext f = new EFDbContext();
try
{
serialPort1.Open();
}
catch { }
var mbus = ModbusSerialMaster.CreateRtu(serialPort1);
PLC p = new PLC();
for (int i = 1; i < 8; i++)
try
{

p.Addres = i;
p.Date = DateTime.UtcNow;
try
{
mbus.ReadHoldingRegisters((byte)p.Addres, 1, 1).ToString();
}
catch { break; }
p.Tnv = mbus.ReadHoldingRegisters((byte)p.Addres, 24, 1)[0].ToString();
p.T1 = mbus.ReadHoldingRegisters((byte)p.Addres, 28, 1)[0].ToString();
p.Tgv = mbus.ReadHoldingRegisters((byte)p.Addres, 30, 1)[0].ToString();
p.OT_r = mbus.ReadHoldingRegisters((byte)p.Addres, 32, 1)[0].ToString();
p.GV_r = mbus.ReadHoldingRegisters((byte)p.Addres, 34, 1)[0].ToString();
p.Ts = mbus.ReadHoldingRegisters((byte)p.Addres, 86, 1)[0].ToString();
p.MaxTime = mbus.ReadHoldingRegisters((byte)p.Addres, 334, 1)[0].ToString();
p.Err_Code = mbus.ReadHoldingRegisters((byte)p.Addres, 333, 1)[0].ToString();
p.OT_percent = mbus.ReadHoldingRegisters((byte)p.Addres, 88, 1)[0].ToString();
p.VtempUst = mbus.ReadHoldingRegisters((byte)p.Addres, 82, 1)[0].ToString();
p.LimCloseOT = mbus.ReadHoldingRegisters((byte)p.Addres, 90, 1)[0].ToString();
p.LimOpenOT = mbus.ReadHoldingRegisters((byte)p.Addres, 92, 1)[0].ToString();
p.OTmission = mbus.ReadHoldingRegisters((byte)p.Addres, 94, 1)[0].ToString();
p.LimObrTemp = mbus.ReadHoldingRegisters((byte)p.Addres, 96, 1)[0].ToString();
p.TimeEn = mbus.ReadHoldingRegisters((byte)p.Addres, 335, 1)[0].ToString();
p.Gvenable = mbus.ReadHoldingRegisters((byte)p.Addres, 336, 1)[0].ToString();
p.GV_percent = mbus.ReadHoldingRegisters((byte)p.Addres, 98, 1)[0].ToString();
p.LimCloseGV = mbus.ReadHoldingRegisters((byte)p.Addres, 100, 1)[0].ToString();
p.LimOpenGV = mbus.ReadHoldingRegisters((byte)p.Addres, 102, 1)[0].ToString();
p.GVtempUst = mbus.ReadHoldingRegisters((byte)p.Addres, 104, 1)[0].ToString();
p.WinterTempUst = mbus.ReadHoldingRegisters((byte)p.Addres, 106, 1)[0].ToString();
p.SummerTempUst = mbus.ReadHoldingRegisters((byte)p.Addres, 108, 1)[0].ToString();
p.Seazon = mbus.ReadHoldingRegisters((byte)p.Addres, 337, 1)[0].ToString();
f.Plcs.Add(p);
f.SaveChanges();

MessageBox.Show("ПЛК №"+i+" успешно опрошен");
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
serialPort1.Close();
}

Yegor
25.02.2016, 05:14
Тот код, которым можно воспроизвести вашу проблему, конечно же. Раз в обмене участвует ПЛК, то и его конфигурацию неплохо увидеть бы. Как прилежный программист, вы уже должны были попробовать изолировать проблему в чистых проектах VS и Кодесиса. Вот их и стоило бы показать.

fillpackart
25.02.2016, 13:56
Нет доступа к проекту на ПЛК, есть только карта регистров. Проект на VS обрабатывает информацию с плк только в приведенной функции, остальной код - визуализация + работа с бд. Всё, что я могу, это посмотреть на ЖКИ значение параметра, считать его своей прогой и понять, что они не похожи друг на друга от слова совсем.

fillpackart
25.02.2016, 14:00
результат опроса - 22854
а вот реальные значения
Текущий режим: зима
ГВС: включен
Температура наружного воздуха: 2.9
Температура обратки: 53.8
Темепература прямой: 59.4
Температура ГВС: 76.6
Положение клапана отопления: 44.0
Положение клапана ГВС: 53.2
Температура смещения: 56.0
адрес:10

Yegor
25.02.2016, 14:33
По кратным двойке адресам регистров и по фактическим значениям на скриншоте предположу, что ПЛК настроен на передачу 32-битных плавающих в формате IEEE754. В таком случае надо склеивать чётный регистр с нечётным соседом и интерпретировать это как float. Вместо этого вы шпарите по чётным регистрам как по целым числам. Для простоты преобразования в NModbus4 (который в NuGet доступен) предусмотрена функция Modbus.Utility.ModbusUtility.GetSingle, принимающая на вход два ushort и отдающая float. Однако может потребоваться попереставлять местами байты каким-то образом (не имел дел с ПЛК63).

Ну и просто пример на калькуляторе (http://www.h-schmidt.net/FloatConverter/IEEE754.html): 53.8 = 01000010010101110011001100110011 = 0x42573333 = (0x4257, 0x3333) = (16983, 13107). Примерно так из 53,8 получается 16983. Не вижу этого числа на скриншоте, но здесь большую роль могут играть округления и порядок байтов.