Распаковка бинарных данных 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
@dada, 👍1
Обсуждение1 ответ
Лучший ответ:
Меня несколько смущает ход вашей программы, поэтому вместо этого я расскажу вам, как я буду обрабатывать данные.
У вас есть однобайтовый заголовок, затем 7 байтов данных, за которыми следует однобайтовая контрольная сумма.
Чтение PySerial (я полагаю) блокируется по умолчанию, поэтому читать следующий серийный символ очень просто, в отличие от Arduino. У него также есть «многобайтовая» версия для чтения, в которой он может считывать заранее установленное количество байтов из потока для вас.
Итак, моя методология будет следующей:
- Прочитать байт. Это "#" или "$"?
- Если это так, вспомните, с каким потоком вы имеете дело, тогда:
- Чтение 7 байт с помощью
this.push.read(7)
в массив байтов (или строку в python < 2.6) - Прочитать один байт для контрольной суммы. Если контрольная сумма верна (какие бы вычисления вы для этого ни использовали), распакуйте данные в массиве.
- Запишите данные в правильный файл в зависимости от потока, который вы запомнили на шаге 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
- Отправка значений с плавающей запятой из Python в Arduino с использованием последовательной связи
- Скрипт Python не может подключиться к последовательному порту
- Отладка различного поведения последовательного приема/отправки между Uno и Mega
- Как связать процессор компьютера с Arduino на плате?
- Как разделить входящую строку?
- Не удается связаться с ардуино с помощью python (Windows)
- Какова максимальная длина провода для последовательной связи между двумя Arduino?
- Последовательная связь Arduino с Python: отправка массива
Пожалуйста, исправьте формат кода. Отступ "выключен"., @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