Считывание данных с приемника RadioLink R12DS по протоколу S-BUS - PullRequest
0 голосов
/ 21 декабря 2018

Моя цель довольно проста: я хочу прочитать информацию с моего приемника RadioLink R12DS по протоколу S-BUS, используя настольное консольное приложение, написанное на C #.

Я использую передатчик AT9S, ослепленный вместе с приемником, в 12-канальном режиме,Я проверил это на контроллере полета 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] для сервоканалов включена .

Вот список моего кода:

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;
    }

У меня есть мысли в голове, и я хочу задать один вопрос здесь.

Возможно, что RadioLink использует другую, модифицированную или собственную реализацию S-BUS, чем Futaba, и я пока не нашел надлежащей документации.

Любой, кто имел опыт в этой области, любые предложения, пожалуйста,,Кажется, я застрял.

Спасибо!

1 Ответ

0 голосов
/ 26 июня 2019

Я провел некоторые исследования потока полученных данных и обнаружил, что устройства 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);
            }
        }
...