我的目标非常简单:我想使用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个字节,其中包括:
将字节[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实现方式,而我还没有找到合适的文档。
任何在该领域有经验的人,请提出任何建议。看来,我被困住了。
谢谢!
答案 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。