Распаковка бинарных данных Arduino на скетче Python

В дополнение к моему предыдущему сообщению: Одновременное чтение данных из нескольких последовательных портов, я застрял, пытаясь разработать скетч Python, который может считывать входящие последовательные данные из com-порта на моем Arduino и распаковать их из буфера в два отдельных файла cvs.

Один из CSV-файлов будет содержать данные первого датчика, а другой — данные второго датчика. Мне удалось развить скетч до такой степени, что при получении первого байта заголовка данные первого датчика распаковываются. Мне трудно настроить скетч, чтобы разрешить вызов заголовка второго байта для распаковки данных второго датчика из пакета данных. Ниже приведен мой сокращенный набросок. Спасибо всем.

def run(self):
    #Creating a csv file to read data from the first sensor
    self.click = open("ball_Data.csv", "wb")
    #Creating a csv file to read data from the second sensor
    self.flick = open("rugby_Data.csv", "wb")
    #creating the serial port object
    self.push = serial.Serial('COM6', 9600)
    while True:
        #If the incoming byte is equivalent to '$'
        if node == b'$':
            # the byte object is equivalent to the available bytes
            node = self.push.read()
            #an array to hold the sensor data
            sensor_array = []
            i = 0
            #This while loop initiates a count from 0 to 9
            #through the sensor array
            while i < 10:
                #The available byte present
                malcolm = self.push.read()
                #The next byte
                turnbull = self.push.read()
                #The incoming uint_16 data is unpacked into the variable lingo
                lingo= (struct.unpack('b', turnbull)[0] << 8) | struct.unpack('B',malcolm)[0]
                #The variable lingo is then appended to the sensor array
                sensor_array.append(lingo)
                #If the length of the sensor array is equivalent to 9
                #write the data through each count into the sensor array
                if len(sensor_array) == 9:
                    self.click.write(str(sensor_array[0] ..+ str(sensor_array[9]))
                    #My idea is that this else statement was supposed to trigger
                    #the next header for the second sensor which would be an '#'
                    #sign before unpacking the data
                    else:
                        oldde = self.push.read()
                        sensor_array = []
                        i = 10
                        while i < 20:
                            #The available byte present
                            malcolm = self.push.read()
                            #The next byte
                            turnbull = self.push.read()
                            lingo= (struct.unpack('b', turnbull)[10]<<8)|struct.unpack('B',malcolm)[10]
                            sensor_array.append(lingo)
                            if len(sensor_array) > 19:
                                self.flick.write(str(sensor_array[10]..+ str(sensor_array[19]))

                                The Packet data structure for the first and second sensor is:
                                    Packet1 from sensor 1:
                                        data_array[0] = headerbyte('#')
                                        data_array[1] = acceleration_xAxis
                                        data_array[2] = acceleration_yAxis
                                        data_array[3] = acceleration_zAxis
                                        data_array[4] = temperature
                                        data_array[5] = gyro_xAxis
                                        data_array[6] = gyro_yAxis
                                        data_array[7] = gyroz_xAxis
                                        data_array[8] = checksum
                                        Packet2 from sensor 2:
                                            data_array[9] = headerbyte('$')
                                            .
                                            .
                                            .
                                            data_array[17] = checksum

, 👍1

Обсуждение

Пожалуйста, исправьте формат кода. Отступ "выключен"., @Mikael Patel

@dada Он имеет в виду, что это фрагмент, и поэтому слева от вашего списка есть огромное количество пробелов, из-за чего большая часть его прокручивается сбоку. Вам не нужно сохранять этот отступ, поскольку он не соответствует контексту (что на самом деле является совершенно другой проблемой — здесь мы не имеем дело с фрагментами: http://snippets-r-us.com), поэтому удалите этот лишний отступ. чтобы его было легче читать, или, что еще лучше, опубликуйте весь код, чтобы у нас была возможность его понять., @Majenko

@MikaelPatel, я изменил формат кода в соответствии с просьбой., @dada

и @majenko, я бы больше прокомментировал код, чтобы вы лучше поняли, что я пытаюсь сделать., @dada

Можете ли вы опубликовать пример данных, отправляемых с Arduino на ваш компьютер, чтобы мы знали, что именно пытается проанализировать?, @Majenko

@majenko я только что загрузил скриншот пакета данных на последовательный монитор, @dada

Урк. Боюсь, это довольно бессмысленно. Можете ли вы создать описание пакета, подобное тому, как я описываю формат пакета ICSC здесь: https://github.com/MajenkoLibraries/ICSC, @Majenko

@majenko помогает, @dada

Это более удобно, да. Это все значения BYTE, не так ли?, @Majenko

@majenko ..Да они, @dada


1 ответ


Лучший ответ:

4

Меня несколько смущает ход вашей программы, поэтому вместо этого я расскажу вам, как я буду обрабатывать данные.

У вас есть однобайтовый заголовок, затем 7 байтов данных, за которыми следует однобайтовая контрольная сумма.

Чтение PySerial (я полагаю) блокируется по умолчанию, поэтому читать следующий серийный символ очень просто, в отличие от Arduino. У него также есть «многобайтовая» версия для чтения, в которой он может считывать заранее установленное количество байтов из потока для вас.

Итак, моя методология будет следующей:

  1. Прочитать байт. Это "#" или "$"?
  2. Если это так, вспомните, с каким потоком вы имеете дело, тогда:
  3. Чтение 7 байт с помощью this.push.read(7) в массив байтов (или строку в python < 2.6)
  4. Прочитать один байт для контрольной суммы. Если контрольная сумма верна (какие бы вычисления вы для этого ни использовали), распакуйте данные в массиве.
  5. Запишите данные в правильный файл в зависимости от потока, который вы запомнили на шаге 2.

Таким образом, вы не дублируете код для каждого потока датчика, вы просто говорите, что "этот пакет является потоком 2", и используете этот запомненный факт после того, как получили пакет и проверили его правильность.

Однако лучший протокол, более надежный, включает в себя как начальный, так и конечный байты, и весь ваш пакет заключен в эту пару байтов. Затем у вас есть механизм «скользящего окна», при котором входящие байты данных прокручиваются за пределы окна фиксированной ширины, и когда первый и последний символы в этом окне совпадают с вашими начальным и конечным байтами, вы затем извлекаете средний раздел и делаете то, что вам нужно делать с этим. Таким образом, если у вас есть $ или #, которые находятся на полпути через поток данных, он не вызовет прием, поскольку конечный байт не совпадает. Это делает всю синхронизацию данных более надежной.

Например, если у вас есть текущий пакет данных, который выглядит как $ho9*$fup, и вы по какой-то причине пропустили первый бит данных (arduino начала передачу до того, как вы были готовы принять , например) это может инициировать прием второго $, что даст вам неверные значения. Вместо этого, если у вас есть начальный символ в виде $ и конечный символ в виде # и вы включаете номер потока, ваш пакет будет выглядеть так:

$1ho9*$fup#

Затем, когда вы прокручиваете это окно, оно будет выглядеть так:

 $ #
вв
[.........$]
[.........$1]
[........$1ч]
[.......$1ч]
[......$1ho9]
[.....$1ho9*]
[....$1ho9*$]
[...$1ho9*$f]
[..$1ho9*$фу]
[.$1ho9*$фуп]
[$1ho9*$фуп#]

И первый и последний символы совпадают, поэтому вы получаете контент.

Если бы вы пропустили первый $, второй $ не совпал бы — скажем, расширенный поток выглядит так: $1ho9*$fup#$2hdiw83bf# и вы пропустили $1, окно выглядеть так:

 $ #
вв
[.........о]
[.........o9]
[........o9*]
[.......o9*$]
[......o9*$f]
[.....o9*$фу]
[....o9*$фуп]
[...o9*$фуп#]
[..o9*$фуп#$]
[.o9*$фуп#$2]
[o9*$фуп#$2ч]
[9*$фуп#$2хд]
[*$фуп#$2хди]
[$fup#$2hdiw] <= Не соответствует, хотя начинается с $
[фуп#$2hdiw8]
[вверх#$2hdiw83]
[p#$2hdiw83b]
[#$2hdiw83bf]
[$2hdiw83bf#] <= Совпадения — начинается с $ и заканчивается на #

Как видите, синхронизация вашего пакета становится намного надежнее. Обычно он неправильно срабатывал бы при первом увиденном символе $.

Всегда существует вероятность того, что символы $ и # могут находиться в правильных позициях в последовательных пакетах, чтобы обмануть систему, но шансы на это несколько невелики. Вы можете добавить дополнительную защиту от этого, «избегая» начального и стопового байтов, если они появляются в вашем потоке. Есть много возможных способов справиться с этим, если вам это действительно нужно.

,

...Господи Боже!!! Большое спасибо.!!!!!!!!!!!!!!!!!! ... я очень обязан, @dada