首页 > 解决方案 > 在蓝牙套接字上使用 pySerialTransfer

问题描述

当设备通过 USB 电缆连接时,我有工作代码使用 pySerialTransfer 从 Raspberry Pi 向 Arduino 发送一个结构。但是,我想通过蓝牙而不是使用 USB 电缆来做到这一点。

独立地,使用单独的 python 代码和单独的 Arduino 草图,我已经能够让 Raspberry Pi 和 Arduino 通过蓝牙通过连续的文本流或二进制数据进行通信。

我的问题是我看不到如何结合这两种方法 - 即:如果我通过蓝牙发送二进制编码结构,我看不到如何获得 pySerialTransfer / SerialTransfer 库的好处来解析它接收端。我看到了如何“手动”进行解析,寻找特殊的终止字符等,但我希望通过 pySerialTransfer 避免这种需要。

感谢您提供任何指针/建议/示例。到目前为止,我能够构建的所有工作代码都在这里。

pySerialTransfer

工作 Arduino C 串行代码

#include "SerialTransfer.h"

SerialTransfer myTransfer;

int const ONBOARD_LED_PIN = 13;

struct POSITION {
  int id;
  float azimuth;
  float altitude;
} position;

void Blink(int n) {
  for (int i=0; i<n; i++) {
    digitalWrite(ONBOARD_LED_PIN, HIGH);
    delay(75);
    digitalWrite(ONBOARD_LED_PIN, LOW);
    delay(75);
  }
  delay(150);
}


void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
  pinMode(ONBOARD_LED_PIN, OUTPUT);
  digitalWrite(ONBOARD_LED_PIN, LOW);
}

void loop()
{
  if(myTransfer.available())
  {
    //////////////////////////////////////////////
    // handle call from Python

    myTransfer.rxObj(position, sizeof(position));

    //////////////////////////////////////////////

    //////////////////////////////////////////////
    // send response
    myTransfer.txObj(position, sizeof(position));
    myTransfer.sendData(sizeof(position));
    //////////////////////////////////////////////
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

工作树莓派序列号

import time
import struct
from pySerialTransfer import pySerialTransfer


def StuffObject(txfer_obj, val, format_string, object_byte_size, start_pos=0):
  """Insert an object into pySerialtxfer TX buffer starting at the specified index.

  Args:
    txfer_obj: txfer - Transfer class instance to communicate over serial
    val: value to be inserted into TX buffer
    format_string: string used with struct.pack to pack the val
    object_byte_size: integer number of bytes of the object to pack
    start_pos: index of the last byte of the float in the TX buffer + 1

  Returns:
    start_pos for next object
  """
  val_bytes = struct.pack(format_string, *val)
  for index in range(object_byte_size):
    txfer_obj.txBuff[index + start_pos] = val_bytes[index]
  return object_byte_size + start_pos


if __name__ == '__main__':
  try:
    link = pySerialTransfer.SerialTransfer('/dev/cu.usbmodem14201', baud=115200)

    link.open()
    time.sleep(2) # allow some time for the Arduino to completely reset
    base = time.time()

    while True:

      sent = (4, 1.2, 2.5)
      format_string = '<lff'
      format_size = 4+4+4
      StuffObject(link, sent, format_string, format_size, start_pos=0)
      link.send(format_size)

      start_time = time.time()
      elapsed_time = 0
      while not link.available() and elapsed_time < 2:
        if link.status < 0:
          print('ERROR: {}'.format(link.status))
        else:
          print('.', end='')
        elapsed_time = time.time()-start_time
      print()

      response = bytearray(link.rxBuff[:link.bytesRead])
      response = struct.unpack(format_string, response)

      print('SENT: %s' % str(sent))
      print('RCVD: %s' % str(response))
      print(' ')

  except KeyboardInterrupt:
    link.close()

蓝牙通讯

工作 Arduino 蓝牙通信

#include "SerialTransfer.h"
// Connect the HC-05 TX to Arduino pin 2 RX. 
// Connect the HC-05 RX to Arduino pin 3 TX through a voltage divider.
// 
 

long n = 0;
struct POSITION {
  float azimuth=5;
  float altitude=10;
};

SerialTransfer myTransfer;

void setup() 
{
    Serial.begin(9600);
 
    // HC-06 default serial speed for communcation mode is 9600
    Serial1.begin(9600);  
    myTransfer.begin(Serial1);
}
 
void loop() 
{
    n++;
    POSITION x;
    x.azimuth=n;
    x.altitude=n+1;
    
    myTransfer.txObj(x, sizeof(x));
    myTransfer.sendData(sizeof(x));
    
    if(Serial1.available() > 0){ // Checks whether data is comming from the serial port
      Serial.println(Serial1.read());} // Reads the data from the serial port
    delay(1000);
}

工作python蓝牙通信

import bluetooth
sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
bd_addr = '98:D3:11:FC:42:16'
port = 1
sock.connect((bd_addr, port))
d = sock.recv(10240000)
print(d)
sock.send("hello")

标签: pythonbluetoothpyserial

解决方案


pySerialTransfer / SerialTransfer 将使用 CRC 以数据包格式排列数据,因此它是通过串行通信快速安全的方式。

实际上,没有特殊字符来终止数据包,因为二进制数据可以是从 0x00 到 0xFF 的任何字符,涵盖所有 ASCII 码。


推荐阅读