通过S-BUS协议从RadioLink R12DS接收器读取数据

时间:2018-12-21 18:44:39

标签: c# serial-port console-application

我的目标非常简单:我想使用C#编写的台式机控制台应用程序通过S-BUS协议从RadioLink R12DS接收器中读取信息。

在12通道模式下,我将AT9S发送器与接收器一起使用。我在Pixhawk飞行控制器上进行了测试。一切都很好,检索数据没有任何问题。

我根据调查的文章设计了一个控制台应用程序。以下是其中最有价值的几个:

http://forum.fpv.kz/topic/303-frsky-x8r-sbus-v-cppm-konverter-na-arduino/ https://github.com/bolderflight/SBUS

我的应用程序从COM端口一个接一个地接收字节流,并尝试捕获消息头“ 0x0F”,但它没有出现。

SBUS协议使用波特率为100000、8个数据位,偶校验位和2个停止位的反向串行逻辑。 SBUS数据包长25个字节,其中包括:

  • 字节[0]:SBUS标头,0x0F
  • 字节[1-22]:16个伺服通道,每个伺服通道11位
  • 字节[23]:
  • 第7位:数字通道17(0x80)
  • 第6位:数字通道18(0x40)
  • 第5位:丢帧(0x20)
  • 第4位:激活了故障安全(0x10)
  • 位0-3:不适用
  • 字节[24]:SBUS结束字节,0x00

将字节[1-22]映射到伺服通道的表是included

这是我的代码清单:

static void Main(String[] args)
    {
        var availablePorts = SerialPort.GetPortNames();
        using(var port = new SerialPort(availablePorts[0], 100000, Parity.Even, 8, StopBits.Two))
        {
            port.DataReceived += PortOnDataReceived;
            while(true)
            {
                if(!port.IsOpen)
                    TryReconnect(port);

                Thread.Sleep(1000);
            }
        }
    }


    // HANDLERS ///////////////////////////////////////////////////////////////////////////////
    private static void PortOnDataReceived(Object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
    {
        var serialPort = (SerialPort)sender;
        if(SbusConverter.TryReadMessage(serialPort, out var messageBuffer))
        {
            var message = SbusConverter.Convert(messageBuffer);

            Console.WriteLine(message.ServoChannels[0]);
        }
    }

public static Boolean TryReadMessage(SerialPort serialPort, out Byte[] messageBuffer)
    {
        const Int32 messageLength = 25;
        const Int32 endOfStream = -1;
        const Byte sBusMessageHeader = 0x0f;
        const Byte sBusMessageEndByte = 0x00;

        messageBuffer = new Byte[messageLength];

        if(serialPort.BytesToRead < messageLength)
            return false;

        do
        {
            var value = serialPort.ReadByte();
            if(value == endOfStream)
                return false;

            if(value == sBusMessageHeader)
            {
                messageBuffer[0] = (Byte)value;
                for(var i = 1; i < messageLength; i++)
                {
                    messageBuffer[i] = (Byte)serialPort.ReadByte();
                }

                if(messageBuffer[0] == sBusMessageHeader &&
                   messageBuffer[24] == sBusMessageEndByte)
                    return true;
            }

        } while(serialPort.BytesToRead > 0);

        return false;
    }

我脑子里有想法,我想在这里问一个问题。

与Futaba相比,RadioLink可能使用不同的,经过修改的或自己的S-BUS实现方式,而我还没有找到合适的文档。

任何在该领域有经验的人,请提出任何建议。看来,我被困住了。

谢谢!

3 个答案:

答案 0 :(得分:0)

我对接收到的数据流进行了一些调查,发现RadioLink设备使用“ 0x1F”作为插入“ 0x0F”的帧起始字节。另一个连接和消息属性是相同的。

var availablePorts = SerialPort.GetPortNames();
        using(var port = new SerialPort(availablePorts[0], 100000, Parity.None, 8, StopBits.One)
        {
            Handshake = Handshake.None
        })
        {
            port.DataReceived += PortOnDataReceived;
            while(true)
            {
                if(!port.IsOpen)
                    OpenPort(port);

                Thread.Sleep(1000);
            }
        }

答案 1 :(得分:0)

为时已晚了两年,但我只是注意到答案代码中设置了1个停止位,而不是2个。可能可以解释0x1F而不是0x0F以及否则的移位数据。

答案 2 :(得分:0)

我正在尝试执行相同类型的操作,拦截来自 herelink 无线电控制器的 Sbus 信号,到目前为止我发现数据发生偏移,并且我的起始字节被识别为 0x1E 的值。此外,数据在示波器上看起来非常嘈杂,由于信号质量差和从 0 到 1 的斜坡,可能会丢失一些 1。