PDA

Просмотр полной версии : Запись регистров ТРМ202



Saratov
12.09.2016, 13:30
Добрый день, есть два прибора ПР200 и ТРМ202, подключены в компьютеру через 485 интерфейс. Есть программа на C#, в которую я интегрировал библиотеку для работы с протоколом Modbus, а именно NmodBus4.

Для прибора ПР200 все замечательно читает и пишет(ReadHoldingRegisters/WriteMultipleRegisters/WriteSingleRegisters).

Что касается прибора ТРМ202, корректно только читает регистры(ReadHoldingRegisters), не могу записать 5 и 6 регистры, выдает ошибку(WriteMultipleRegisters/WriteSingleRegisters).

Насколько я понимаю у ПР200 функция записи имеет вид 0х06, а у ТРМ202 - 0х10? Кто-нибудь знает что нужно изменить или дополнить чтобы функция записи для ТРМ202 заработала?

RA.
12.09.2016, 13:49
а писать в трм 16ой функцией никак?

capzap
12.09.2016, 14:03
если пытались записать значения от нуля до девяти, то в настройках прибора добавьте один знак после запятой и записывайте нужное значение умноженое на десять

capzap
12.09.2016, 14:06
а писать в трм 16ой функцией никак?

а 0x10 это по Вашему чему равно?

RA.
12.09.2016, 14:13
а 0x10 это по Вашему чему равно?

по написанному понял что и в пр200 и в трм пишет 0х06

Saratov
12.09.2016, 14:26
если пытались записать значения от нуля до девяти, то в настройках прибора добавьте один знак после запятой и записывайте нужное значение умноженое на десять

пытался и 1 записывать, и 100 и 1000 один и тот же результат, что по 0х06 (WriteSingleRegisters) что по 0х10 (WriteMultipleRegisters)

меняется только код Exception с 1 на 3

Выдано исключение типа "Modbus.SlaveException".
Function Code: 134
Exception Code: 1 - The function code received in the query is not an allowable action for the server (or slave). This may be because the function code is only applicable to newer devices, and was not implemented in the unit selected. It could also indicate that the server (or slave) is in the wrong state to process a request of this type, for example because it is unconfigured and is being asked to return register values.

Exception Code: 3 - A value contained in the query data field is not an allowable value for server (or slave).
This indicates a fault in the structure of the remainder of a complex request, such as that the implied length is incorrect.
It specifically does NOT mean that a data item submitted for storage in a register has a value outside the expectation of the application program,
since the MODBUS protocol is unaware of the significance of any particular value of any particular register.

Так же заметил что при создании запроса IModbusMessage ReadResponse - для чтения (ReadHoldingRegisters) byte[] frameStart создается корректно - 17, 3, 2, 0

а при использовании метода записи WriteSingleRegister/WriteMultiplyRegister - создается некорректно насколько я понимаю? - 17, 134, 1, 130

capzap
12.09.2016, 15:12
что то не сходится, как тогда мастер опрашивает ПР. запишите в трм из другого источника, например с ПРки

Santi
12.09.2016, 17:32
Добрый день, есть два прибора ПР200 и ТРМ202, подключены в компьютеру через 485 интерфейс. Есть программа на C#, в которую я интегрировал библиотеку для работы с протоколом Modbus, а именно NmodBus4.

Для прибора ПР200 все замечательно читает и пишет(ReadHoldingRegisters/WriteMultipleRegisters/WriteSingleRegisters).

Что касается прибора ТРМ202, корректно только читает регистры(ReadHoldingRegisters), не могу записать 5 и 6 регистры, выдает ошибку(WriteMultipleRegisters/WriteSingleRegisters).

Насколько я понимаю у ПР200 функция записи имеет вид 0х06, а у ТРМ202 - 0х10? Кто-нибудь знает что нужно изменить или дополнить чтобы функция записи для ТРМ202 заработала?

Действительно в ТРМ202 можно записывать только функцией 10hex, но хоть эта функция в Модбасе предполагает возможность записи нескольких регистров, в ТРМ возможно запись только одного регистра. Если попытаететесь записать за одну операцию 2 или более регистров - получите ошибку. Это касается не только ТРМ, но и некоторых других приборов ОВЕН.

Saratov
13.09.2016, 11:22
Действительно в ТРМ202 можно записывать только функцией 10hex, но хоть эта функция в Модбасе предполагает возможность записи нескольких регистров, в ТРМ возможно запись только одного регистра. Если попытаететесь записать за одну операцию 2 или более регистров - получите ошибку. Это касается не только ТРМ, но и некоторых других приборов ОВЕН.

У Вас есть пример кода для записи в ТРМ202? Я пробовал менять в классе Modbus код функции(WriteMultipleRegisters) с 16 на 10 и давать на запись массив с одним элементом, все равно ошибку выдает.

Гарчев Евгений
13.09.2016, 11:47
Я пробовал менять в классе Modbus код функции(WriteMultipleRegisters) с 16 на 10 и давать на запись массив с одним элементом, все равно ошибку выдает.
Я надеюсь, тут опечатка... или же Вы изменяете адрес начального опрашиваемого регистра для функции WriteMultiplyRegister (0х10), предполагая что меняете номер функции. Можете полностью предоставить структуру Вашей функции?


и давать на запись массив с одним элементом, все равно ошибку выдает.
Какая размерность массива?

Saratov
13.09.2016, 12:40
Я надеюсь, тут опечатка... или же Вы изменяете адрес начального опрашиваемого регистра для функции WriteMultiplyRegister (0х10), предполагая что меняете номер функции. Можете полностью предоставить структуру Вашей функции?

Какая размерность массива?

Сначала сюда
/// <summary>
/// Write a block of 1 to 123 contiguous 16 bit holding registers.
/// </summary>
/// <param name="slaveAddress">Address of the device to write to.</param>
/// <param name="startAddress">Address to begin writing values.</param>
/// <param name="data">Values to write.</param>
public void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data)
{
ValidateData("data", data, 123);

var request = new WriteMultipleRegistersRequest(slaveAddress, startAddress, new RegisterCollection(data));
Transport.UnicastMessage<WriteMultipleRegistersResponse>(request);
}

Потом сюда


internal virtual T UnicastMessage<T>(IModbusMessage message) where T : IModbusMessage, new()
{
IModbusMessage response = null;
int attempt = 1;
bool success = false;

do
{
try
{
lock (_syncLock)
{
Write(message);

bool readAgain;
do
{
readAgain = false;
response = ReadResponse<T>();

var exceptionResponse = response as SlaveExceptionResponse;
if (exceptionResponse != null)
{
// if SlaveExceptionCode == ACKNOWLEDGE we retry reading the response without resubmitting request
readAgain = exceptionResponse.SlaveExceptionCode == Modbus.Acknowledge;
if (readAgain)
{
Debug.WriteLine(
"Received ACKNOWLEDGE slave exception response, waiting {0} milliseconds and retrying to read response.",
_waitToRetryMilliseconds);
Sleep(WaitToRetryMilliseconds);
}
else
{
throw new SlaveException(exceptionResponse);
}
}
else if (ShouldRetryResponse(message, response))
{
readAgain = true;
}
} while (readAgain);
}

ValidateResponse(message, response);
success = true;
}
catch (SlaveException se)
{
if (se.SlaveExceptionCode != Modbus.SlaveDeviceBusy)
throw;

if (SlaveBusyUsesRetryCount && attempt++ > _retries)
throw;

Debug.WriteLine(
"Received SLAVE_DEVICE_BUSY exception response, waiting {0} milliseconds and resubmitting request.",
_waitToRetryMilliseconds);
Sleep(WaitToRetryMilliseconds);
}
catch (Exception e)
{
if (e is FormatException ||
e is NotImplementedException ||
e is TimeoutException ||
e is IOException)
{
Debug.WriteLine("{0}, {1} retries remaining - {2}", e.GetType().Name, _retries - attempt + 1, e);

if (attempt++ > _retries)
throw;
}
else
{
throw;
}
}
} while (!success);

return (T)response;
}

Дальше

internal override IModbusMessage ReadResponse<T>()
{
byte[] frameStart = Read(ResponseFrameStartLength);
byte[] frameEnd = Read(ResponseBytesToRead(frameStart));
byte[] frame = Enumerable.Concat(frameStart, frameEnd).ToArray();
Debug.WriteLine("RX: {0}", string.Join(", ", frame));

return CreateResponse<T>(frame);
}

Дальше

public virtual byte[] Read(int count)
{
byte[] frameBytes = new byte[count];
int numBytesRead = 0;

while (numBytesRead != count)
numBytesRead += StreamResource.Read(frameBytes, numBytesRead, count - numBytesRead);

return frameBytes;
}

дальше сюда

public int Read(byte[] buffer, int offset, int count)
{
try
{
return _serialPort.Read(buffer, offset, count);
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace, ex.Message, ex.InnerException);
}
return 0;

}

и тут вылетают Exception и застревает, потому как прошлая функция ждет ответ величиной 4

Здесь в класса Modbus насколько я понял есть коды поддерживаемых функций и видимо 10 как раз не поддерживается, или я что то не так понимаю

namespace Modbus
{
/// <summary>
/// Defines constants related to the Modbus protocol.
/// </summary>
internal static class Modbus
{
// supported function codes
public const byte ReadCoils = 1;
public const byte ReadInputs = 2;
public const byte ReadHoldingRegisters = 3;
public const byte ReadInputRegisters = 4;
public const byte WriteSingleCoil = 5;
public const byte WriteSingleRegister = 6;
public const byte Diagnostics = 8;
public const ushort DiagnosticsReturnQueryData = 0;
public const byte WriteMultipleCoils = 15;
public const byte WriteMultipleRegisters = 16;
public const byte ReadWriteMultipleRegisters = 23;

Вот так записываю в тестовом проекте

SerialPort port = new SerialPort("COM3");

// configure serial port
port.BaudRate = 115200;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.ReadTimeout = 30;
port.Open();

// create modbus master
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port);

master.WriteSingleRegister(17,5,10);
master.WriteMultipleRegisters(17,5,new ushort[] {100});

Santi
13.09.2016, 13:48
У Вас есть пример кода для записи в ТРМ202? Я пробовал менять в классе Modbus код функции(WriteMultipleRegisters) с 16 на 10 и давать на запись массив с одним элементом, все равно ошибку выдает.
Мой пример Вам не поможет, я связывался с ТРМ202 со Шнайдеровской панели. А описанное мной ограничение можно прочитать в http://www.owen.ru/uploads/ki_prm_trm202_033.pdf

Также я сталкивался с этим ограничением и в других ОВЕНовских приборах, в которых и в руководстве об этом ничего не написано. Видимо этот Модбас-нюанс фирменный стиль ОВЕНа.

Гарчев Евгений
13.09.2016, 14:02
Здесь в класса Modbus насколько я понял есть коды поддерживаемых функций и видимо 10 как раз не поддерживается, или я что то не так понимаю


0х10 (это в HEX) = 16 (это в DEC)



SerialPort port = new SerialPort("COM3");

// configure serial port
port.BaudRate = 115200;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.ReadTimeout = 30;
port.Open();

// create modbus master
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port);

master.WriteSingleRegister(17,5,10);
master.WriteMultipleRegisters(17,5,new ushort[] {100});


port.StopBits = StopBits.One; - в ТРМ2хх 2 стоп-бита

master.WriteSingleRegister(17,5,10); - это лишнее.

Адрес ТРМ-а 17-ый?

Saratov
13.09.2016, 14:17
0х10 (это в HEX) = 16 (это в DEC)




port.StopBits = StopBits.One; - в ТРМ2хх 2 стоп-бита

master.WriteSingleRegister(17,5,10); - это лишнее.

Адрес ТРМ-а 17-ый?

да, адрес 17, пробовал я ставить port.StopBits = StopBits.Two - результата не дало.

Гарчев Евгений
14.09.2016, 12:11
Здравствуйте!
А перечень всех сетевых настроек ТРМ202 (из группы Comm) можете указать? Пробовали опросить ТРМ каким-нибудь стандартным ModBus-мастером?

Santi
14.09.2016, 12:22
По-моему автор писал, что читает без проблем, значит параметры связи правильные. Вопрос с записью.
По записи я бы еще уточнил какие именно переменные - int/float пытаетесь записать. Если int, то к-во регистров в одной операции д.б. 1, если float, то 2. Правда именно на трм202-м я пользовался только int, c float работал на другом приборе.

Гарчев Евгений
14.09.2016, 12:34
Да, действительно, не обратил внимание, на то, что чтение работает.
master.WriteMultipleRegisters(17,5,new ushort[] {100}); - здесь видно, что пишет в 5-ый регистр, а это int.
Лучше тогда на лог обмена посмотреть бы.