4

几个快速的问题。我有一个我正在尝试控制的 DMX king USB 照明控制器。

它基于提供 ac# 类的 Open DMX 协议(来自 Entec)。我已经将设备插入 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,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 方法查询设备。

有任何想法吗?

加雷斯

4

5 回答 5

8

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

谢谢你的帮助

于 2011-07-12T23:39:35.540 回答
2

我在开放的 dmx 站点上编写了 C# 类。它基于 Hippy 用 VB 编写的 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 应用程序中,第二个参数是一个短整型。但是,只有在将第二个参数强制转换为 char 时,在 C# 类中对其等价的任何调用才会起作用。

    [DllImport("FTD2XX.dll")]
    public static extern FT_STATUS FT_SetFlowControl(uint ftHandle, UInt16 usFlowControl, byte uXon, byte uXoff);
于 2011-05-10T20:53:21.097 回答
2

我通过机械 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);
        }

    }

}

}

于 2011-05-10T23:09:26.813 回答
1

我用 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);


    }
于 2013-02-03T09:07:55.680 回答
0

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

于 2011-05-10T21:56:49.313 回答