照明USB OpenDMX FTD2XX DMXking

几个快速的问题。 我有一个DMX王USB照明控制器,我正试图控制。

它基于Open DMX协议(来自Entec),提供ac#class。 我已经将设备插入RGB设备,如果我用他们的驱动程序测试USB设备,它连接到COM4,当我将他们的软件切换到发送模式时,我可以设置单独的DMX通道。

使用他们的OpenDMX类,进行一些修改(核心是相同的,我刚刚添加了一些额外的错误检查,我可以找到设备,查询它的信息等。当我打开设备时,我得到一个句柄。我可以写使用FT_Write到那个设备,但不管我做什么,实际上没有灯亮起来。

以下是一些相关的代码片段:

public static byte[] buffer; [DllImport("FTD2XX.dll")] public static extern FT_STATUS FT_Open(UInt32 uiPort, ref uint ftHandle); [DllImport("FTD2XX.dll")] public static extern FT_STATUS FT_Write(uint ftHandle, IntPtr lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesWritten); public static void writeData() { while (!done) { try { initOpenDMX(); status = FT_SetBreakOn(handle); status = FT_SetBreakOff(handle); bytesWritten = write(handle, buffer, buffer.Length); if (bytesWritten == 0) { break; } System.Threading.Thread.Sleep(25); } catch (Exception) { break; } } Connected = false; done = false; } 

所有状态都以FT_Ok的forms返回,bytesWritten返回为512(此USB控制器上的通道数)

我一直在想我错过了将设备设置为传输模式或类似的设备(它只有一个DMX插槽)

 public static void initOpenDMX() { status = FT_ResetDevice(handle); status = FT_SetDivisor(handle, (char)12); // set baud rate status = FT_SetDataCharacteristics(handle, BITS_8, STOP_BITS_2, PARITY_NONE); status = FT_SetFlowControl(handle, (char)FLOW_NONE, 0, 0); status = FT_ClrRts(handle); status = FT_SetLatencyTimer(handle, (byte)40); status = FT_Purge(handle, PURGE_TX); status = FT_Purge(handle, PURGE_RX); } 

我也尝试过Entec OpenDMX类而没有任何修改,它似乎也没有做任何事情。

只是想强调他们的控制软件工作正常,因此灯和控制器是兼容的。 我认为我使用FTD2xx的方式缺少一些东西。 没有错误(一切都是FT_OK)所以这表明DLL正在运行 – 特别是因为我可以使用FT_ListDevices和FT_GetDeviceInfo方法查询设备。

有任何想法吗?

加雷思

为了解决这个问题,我给制造商发了电子邮件 事实certificate,该设备不是OpenDMX,实际上它是一个DMXProUSB协议非常相似,它基于FTDI芯片,这就是为什么代码部分工作,但它有一个微控制器。 我将C ++示例控制器文件转换为C#并使其全部正常工作。 如果再次出现这种情况,我很乐意分享DMXProUSB的最终c#代码,但不支持。 我已经将代码通过电子邮件发送到manfacturer(dmxking)并在github上放了一个副本: https : //github.com/agrath/Sniper.Lighting.Dmx

谢谢你的帮助

我通过机械VB到C#翻译器运行Hippy的VB版本,发现了一个关键的区别。 FT_WRITE使用字符串将数据传递给非托管代码。 C#类使用指向字节数组的IPtr。

这个版本对我有用:

 using System; using System.Runtime.InteropServices; using System.Threading; // based on Hippy's VB Example // http://members.westnet.com.au/rowanmac/opendmx.html#tx // Working link: https://web.archive.org/web/20150217155014/http://members.westnet.com.au:80/rowanmac/opendmx.html namespace Test { class Program { [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Open(short intDeviceNumber, ref int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Close(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetDivisor(int lngHandle, int div); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Read(int lngHandle, string lpszBuffer, int lngBufferSize, ref int lngBytesReturned); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Write(int lngHandle, string lpszBuffer, int lngBufferSize, ref int lngBytesWritten); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Write(int lngHandle, IntPtr lpBuffer, int lngBufferSize, ref int lngBytesWritten); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetBaudRate(int lngHandle, int lngBaudRate); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetDataCharacteristics(int lngHandle, byte byWordLength, byte byStopBits, byte byParity); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetFlowControl(int lngHandle, short intFlowControl, byte byXonChar, byte byXoffChar); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_ResetDevice(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetDtr(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_ClrDtr(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetRts(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_ClrRts(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_GetModemStatus(int lngHandle, ref int lngModemStatus); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_Purge(int lngHandle, int lngMask); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_GetStatus(int lngHandle, ref int lngRxBytes, ref int lngTxBytes, ref int lngEventsDWord); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_GetQueueStatus(int lngHandle, ref int lngRxBytes); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_GetEventStatus(int lngHandle, ref int lngEventsDWord); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetChars(int lngHandle, byte byEventChar, byte byEventCharEnabled, byte byErrorChar, byte byErrorCharEnabled); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetTimeouts(int lngHandle, int lngReadTimeout, int lngWriteTimeout); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetBreakOn(int lngHandle); [DllImport("FTD2XX.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int FT_SetBreakOff(int lngHandle); // FTDI Constants const short FT_OK = 0; const short FT_INVALID_HANDLE = 1; const short FT_DEVICE_NOT_FOUND = 2; const short FT_DEVICE_NOT_OPENED = 3; const short FT_IO_ERROR = 4; const short FT_INSUFFICIENT_RESOURCES = 5; // Word Lengths const byte FT_BITS_8 = 8; // Stop Bits const byte FT_STOP_BITS_2 = 2; // Parity const byte FT_PARITY_NONE = 0; // Flow Control const byte FT_FLOW_NONE = 0x0; // Purge rx and tx buffers const byte FT_PURGE_RX = 1; const byte FT_PURGE_TX = 2; public static int handle=0; public static byte[] buffer = new byte[4]; // can be up to 512, shorter is faster private static string lpszBuffer=""+ (char) 0 + (char) 64 + (char) 64+ (char) 0; static void Main(string[] args) { init(); } public static string init() { short n = 0; // ==== ATTEMPT TO OPEN DEVICE ==== if (FT_Open(n, ref handle) != FT_OK) { return "FTTD Not Found"; } // ==== PREPARE DEVICE FOR DMX TRANSMISSION ==== // reset the device if (FT_ResetDevice(handle) != FT_OK) { return "Failed To Reset Device!"; } // get an ID from the widget from jumpers // GetID(ref n); // set the baud rate if (FT_SetDivisor(handle, 12) != FT_OK) { return "Failed To Set Baud Rate!"; } // shape the line if (FT_SetDataCharacteristics(handle, FT_BITS_8, FT_STOP_BITS_2, FT_PARITY_NONE) != FT_OK) { return "Failed To Set Data Characteristics!"; } // no flow control if (FT_SetFlowControl(handle, FT_FLOW_NONE, 0, 0) != FT_OK) { return "Failed to set flow control!"; } // set bus transiever to transmit enable if (FT_ClrRts(handle) != FT_OK) { return "Failed to set RS485 to send!"; } // Clear TX & RX buffers if (FT_Purge(handle, FT_PURGE_TX) != FT_OK) { return "Failed to purge TX buffer!"; } // empty buffers if (FT_Purge(handle, FT_PURGE_RX) != FT_OK) { return "Failed to purge RX buffer!"; } setDmxValue(0, 0); // should always be zero setDmxValue(1, 64); setDmxValue(2, 64); setDmxValue(3, 0); Thread thread = new Thread(new ThreadStart(writeDataThread)); thread.Start(); return "Ok"; } // init public static void setDmxValue(int channel, byte value) { buffer[channel] = value; lpszBuffer=""; for (int i = 0; i < buffer.Length; ++i) { lpszBuffer += (char)buffer[i]; } } public static void writeDataThread() { bool done = false; int lngBytesWritten=0; while (!done) { FT_SetBreakOn(handle); FT_SetBreakOff(handle); FT_Write(handle, lpszBuffer, buffer.Length, ref lngBytesWritten); System.Threading.Thread.Sleep(50); } } } 

}

我在open dmx网站上写了C#类。 它基于用VB编写的Hippy的Open DMX驱动程序。

//旧断链接:
http://members.westnet.com.au/rowanmac/opendmx.html#tx
//工作链接: https : //web.archive.org/web/20150217155014/http : //members.westnet.com.au : 80/rowanmac/opendmx.html

C#类没有初始化FDDI芯片上的东西。

多年来,这一直困扰着我。

我怀疑FT_SetFlowControl。 在VB应用程序中,第二个参数是short int。 但是,只有在将第二个参数强制转换为char时,对C#类的任何调用都是有效的。

  [DllImport("FTD2XX.dll")] public static extern FT_STATUS FT_SetFlowControl(uint ftHandle, UInt16 usFlowControl, byte uXon, byte uXoff); 

我用Marshal.Copy解决了这个问题

  public static void writeDataThread(int Length) { int lngBytesWritten = 0; IntPtr pnt = Marshal.AllocHGlobal(Length); Marshal.Copy(buffer, 0, pnt, Length); FT_SetBreakOn(handle); FT_SetBreakOff(handle); string StartCode = null; FT_Write(handle, StartCode, 1, ref lngBytesWritten); FT_Write(handle, pnt, Length, ref lngBytesWritten); } 

除串行端口外,FTDI芯片还具有GPIO引脚。 希望文档告诉您是否需要设置这些。 该函数是FT_SetBitMode 。 文档在这里 。