PDA

Просмотр полной версии : owen_io.dll + .NET 4.0 + C#



iKarma
27.11.2013, 22:52
Здравствуйте.

Написал простенькое консольное приложение на шарпах с библиотекой owen_io.dll.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplicationOWENDLLImport
{
class Program
{
internal class OwenIO
{
[DllImportAttribute("owen_io.dll", EntryPoint = "OpenPort", CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPort(int n, int speed, int part, int bits, int stop, int vid);

[DllImportAttribute("owen_io.dll", EntryPoint = "ClosePort", CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePort();

[DllImportAttribute("owen_io.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFloat24", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadFloat24(int adr, int adr_type, string command, float value, int index);
}

static void Main(string[] args)
{
int result;
float value = 0;

result = OwenIO.OpenPort(2, 8, 0, 1, 0, 1);
Console.WriteLine(result); //возвращается 0 - успешно

result = OwenIO.ReadFloat24(32, 0, "PV", value, 0);
Console.WriteLine(result); //возвращается -104 - сетевая ошибка nErr
Console.WriteLine(value); //возвращается 0, т.к. значение не изменилось

result = OwenIO.ClosePort();
Console.WriteLine(result); //возвращается 0 - успешно

Console.ReadLine();
}
}
}

Как видно из моих комментариев порт открывается и закрывается нормально, т.е. без ошибок (код возврата 0), а вот чтение параметра PV не удаётся (код возврата -104, что соответствует сетевой ошибке nErr). Грешу на PChar и string.

Подскажите, пожалуйста, в чём может быть проблема. Заранее благодарен :)

З.Ы.: у меня owen_io.dll версии 1.2.0.17 - это последняя версия библиотеки?

firefox0013
28.11.2013, 13:01
С каким устройством пытаетесь общаться? Как оно подключено? На прямую в COM порт или через преобразователь интерфейса типа ОВЕН ЕКОН134? Сталкивался с подобной проблемой при работе через «ОВЕН ЕКОН134». Причиной была неправильная настройка порта.

firefox0013
28.11.2013, 13:07
И при работе через преобразователи COM-портов в Ethernet фирмы Moxa была такая же ситуация. Оказалось, что в русской документации на моксу A и B выходы были перепутаны. Если через преобразователи работаете то, скорее всего, нет связи преобразователя с устройством.

iKarma
28.11.2013, 14:02
Подключаюсь через АС4, работаю с ТРМ201. Но функции открытия и закрытия порта судя по кодам работают нормально.

firefox0013
28.11.2013, 15:24
Преобразователь подключенный к пк эмулирует com порт и вы общаетесь именно с этим ком портом т.е. с преобразователем а он уже с устройством. Порт пк -> преобразователь открывается но не факт что есть связь преобразователь -> устройство.

firefox0013
28.11.2013, 15:25
Проверьте настройки порта на преобразователе и на устройстве. они должны совпадать. с АС4 не работал но думаю принцип тот же.

iKarma
28.11.2013, 15:57
С Delphi у меня всё нормально работало (библиотека одинаковая), а с C# такая вот проблема. Так что думаю проблема в моём коде, а не в настройках приборов и т.д.

firefox0013
29.11.2013, 03:57
Тогда дело в дллимпорте. Я точно не помню как он пишется 1 раз делал потом на c# свою либу писал для общения по овену. укажите явно [In],[Out] параметры. float value точно было ин аут.



[DllImportAttribute("owen_io.dll", EntryPoint = "OpenPort", CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPort(int n, int speed, int part, int bits, int stop, int vid);

[DllImportAttribute("owen_io.dll", EntryPoint = "ClosePort", CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePort();

[DllImportAttribute("owen_io.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFloat24", CallingConvention = CallingConvention.StdCall)]
public static extern float ReadFloat24(int adr, int adr_type, [MarshalAs(UnmanagedType.BStr)] string command,[In] [Out] ref float value, int index);



Точно не помню но делал такое а код уже удалил. Попробуйте вместо Unicode поставить ASCII и тип возвращаемого значения float.

firefox0013
29.11.2013, 03:59
А вообще если вам ReadFloat24 надо используйте http://www.owen.ru/forum/showthread.php?t=16224 а ком порт как нибудь сами откроете.

firefox0013
29.11.2013, 07:51
Удалось победить проблему?

iKarma
30.11.2013, 17:22
Тогда дело в дллимпорте. Я точно не помню как он пишется 1 раз делал потом на c# свою либу писал для общения по овену. укажите явно [In],[Out] параметры. float value точно было ин аут.



[DllImportAttribute("owen_io.dll", EntryPoint = "OpenPort", CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPort(int n, int speed, int part, int bits, int stop, int vid);

[DllImportAttribute("owen_io.dll", EntryPoint = "ClosePort", CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePort();

[DllImportAttribute("owen_io.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFloat24", CallingConvention = CallingConvention.StdCall)]
public static extern float ReadFloat24(int adr, int adr_type, [MarshalAs(UnmanagedType.BStr)] string command,[In] [Out] ref float value, int index);



Точно не помню но делал такое а код уже удалил. Попробуйте вместо Unicode поставить ASCII и тип возвращаемого значения float.

Переписал код дллимпорта как вы сказали. Пришлось чуть-чуть и подредактировать код основной функции так:



double result;
float value = 0;

result = NativeMethods.OpenPort(2, 8, 0, 1, 0, 1);
Console.WriteLine(result);

result = NativeMethods.ReadFloat24(32, 0, "PV", ref value, 0);
Console.WriteLine(result);
Console.WriteLine(value);

result = NativeMethods.ClosePort();
Console.WriteLine(result);

Console.ReadLine();


Но всё равно не работает, код ошибки - NaN, т.е. я даже не знаю, что за ошибка. Есть идеи?

firefox0013
30.11.2013, 18:31
Переписал код дллимпорта как вы сказали. Пришлось чуть-чуть и подредактировать код основной функции так:



double result;
float value = 0;

result = NativeMethods.OpenPort(2, 8, 0, 1, 0, 1);
Console.WriteLine(result);

result = NativeMethods.ReadFloat24(32, 0, "PV", ref value, 0);
Console.WriteLine(result);
Console.WriteLine(value);

result = NativeMethods.ClosePort();
Console.WriteLine(result);

Console.ReadLine();


Но всё равно не работает, код ошибки - NaN, т.е. я даже не знаю, что за ошибка. Есть идеи?

У вас одно устройство подключено к ком порту или несколько? Мне кажется у вас не верные параметры при вызове фунцций.
OpenPort(int n, int speed, int part, int bits, int stop, int vid);
n - номер ком порта COM1 - 0 COM2 -1 и так далие
speed - скорость порта. обычно 115200
part - четность. если не ошибаюсь 0
bits - 8
stop - 1
vid - не помню

ReadFloat24(int adr, int adr_type, [MarshalAs(UnmanagedType.BStr)] string command,[In] [Out] ref float value, int index);

adr - адрес устройства в сети обычно 0
index = -1

Вы уверены в используемых параметрах? для устройств овен есть програмулина для настройки скачайте и попробуйте ей подключится что проверить что связь есть.

capzap
30.11.2013, 18:57
Но всё равно не работает, код ошибки - NaN, т.е. я даже не знаю, что за ошибка. Есть идеи?

Вы же вроде год назад озадачивались этой темой, тут читали: http://www.owen.ru/forum/showthread.php?t=12144&highlight=owen_io.dll

iKarma
01.12.2013, 12:54
Всё, наконец-то разобрался :)

Причина была в некорректном дллимпорте и вызове.

Вот корректный код (вдруг кому ещё поможет):



//...

[DllImportAttribute("owen_io.dll", CharSet = CharSet.Unicode, EntryPoint = "ReadFloat24", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadFloat24(int adr, int adr_type, System.IntPtr command, ref float value, int index);

//...

IntPtr name = Marshal.StringToCoTaskMemAnsi("PV");
result = NativeMethods.ReadFloat24(32, 0, name, ref value, -1);

//...

Игорь89
04.02.2014, 12:35
Добрый день! Срочно нужна помощь! Пишу программку на c# что то вроде диспетчеризации. С чтением данных разобрался полностью, а вот запустить машину, или перевести в дежурный режим никак! контроллер ТРМ133м02

пытался записать параметр "STAT"

int adr = Convert.ToInt32(textBox1.Text); // адрес прибора
IntPtr command = Marshal.StringToCoTaskMemAnsi("STAT");
int value = Convert.ToInt32(textBox3.Text); // величина, которую будем записывать

try
{
int result = RS485.WriteWord(adr, 0, command, value, -1);
MessageBox.Show("процесс " + result.ToString() + "\n" + "значение " + value.ToString());
}
catch
{
MessageBox.Show("ошибка чтения данных");
}
возвращает ошибку 104

импорт выполнен так:

class RS485
{
[DllImportAttribute("owen_io.dll", EntryPoint = "OpenPort", CallingConvention = CallingConvention.StdCall)]
public static extern int OpenPort(int n, int sped, int part, int bits, int stop, int vid);

[DllImportAttribute("owen_io.dll", EntryPoint = "ClosePort", CallingConvention = CallingConvention.StdCall)]
public static extern int ClosePort();

[DllImportAttribute("owen_io.dll", EntryPoint = "ReadIEEE32", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadIEEE32(int adr, int adr_type, System.IntPtr command, ref float value, ref int time, int index);

[DllImportAttribute("owen_io.dll", EntryPoint = "SetMaxRetriesGlobal", CallingConvention = CallingConvention.StdCall)]
public static extern void SetMaxRetriesGlobal(int n);

[DllImportAttribute("owen_io.dll", EntryPoint = "ReadFloat24", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadFloat24(int adr, int adr_type, System.IntPtr command, ref float value, int index);

[DllImportAttribute("owen_io.dll", EntryPoint = "ReadSInt", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadSInt(int adr, int adr_type, IntPtr command, ref int param, int index);

[DllImportAttribute("owen_io.dll", EntryPoint = "WriteWord", CallingConvention = CallingConvention.StdCall)]
public static extern int WriteWord(int adr, int adr_type, IntPtr command, int value, int index);
}

Пожалуйста, подскажите, как мне запустить или остановить этот контроллер! Уже мозг кипеть начинает!

Игорь89
05.02.2014, 20:41
ну подскажите пожалуйста, где же ошибка? в длл импорте?
[DllImportAttribute("owen_io.dll", EntryPoint = "WriteWord", CallingConvention = CallingConvention.StdCall)]
public static extern int WriteWord(int adr, int adr_type, IntPtr command, int value, int index);

может надо добавить ключевое слово ref или out? Блин все перепробовал, ни фига не получается. Люди же сталкивались с такой задачей.....

Игорь89
06.02.2014, 15:35
Короче, подключил сниффер COM порта (виртуального) и посмотрел пакеты.
RS485.WriteWord(adr, 0, command, value, -1); эта хрень отправляет пакеты
в которых размер блока данных почему то равен двум (0010), вместо ожидаемого одного (0001). как я понял, за величину блока данных отвечает параметр index. Но могу и ошибаться. Методом научного тыка определил, что при изменении index меняется размер блока данных. Однако, единицы добиться так и не смог. Решил записать правильные пакеты, и отправлять их напрямую в порт через класс SerialPort. посмотрим, что выйдет.

Дмитрий Егоренков
07.02.2014, 14:35
Позвольте поинтересоваться, по вашему мнению, какой должен быть размер поля данных при вызове функции WriteByte()?

Игорь89
07.02.2014, 21:26
Я думал, 1. проснифил конфигуратор, он отправляет два пакета. Первый с размером два байта, не зависимо от записываемой величины, и с неизвестным мне хэш кодом 2728 или 2827 не помню уже. А второй пакет содержит записываемую величину, размер 1 байт и хэш код 9C5B, что , собственно, я и ожидал увидеть. Сегодня отправлял пакеты напрямую с ком порта, получается. Так, собственно, и думаю решить проблему. Ибо для меня все равно остается загадкой этот нюанс, а сроки поджимают.

Игорь89
07.02.2014, 21:33
Может просветите меня, неуча, как оно должно выглядеть? Ладно, два байта. Почему конфигуратор отправляет два пакета, а данная функция один пакет? почему хэш коды разные?