Search code examples
pythonarduinobluetoothpyserial

bluetooth data recieved from arduino gets divided into chunks in python


I was trying to send IMU data from MPU6050 from arduino pro micro to my pc using HC-05, and I wrote a small program in python to recieve it, but the data gets printed in different lines or gets divided into chunks.

Here is the Arduino code, I am using the Serial1 line to send data through HC-05.

Serial1.print(ypr[0]*180/M_PI);
Serial1.print(",");
Serial1.print(ypr[1]*180/M_PI);
Serial1.print(",");
Serial1.println(ypr[2]*180/M_PI);

And here is the code for reception, in python:

import bluetooth 
import serial
target_name = "HC-05"
target_address = None
        
nearby_devices = bluetooth.discover_devices()
        
for bdaddr in nearby_devices:
    if target_name == bluetooth.lookup_name(bdaddr):
        target_address = bdaddr
        break
    if target_address is not None:
        print ("found target bluetooth device with address ", target_address)
    else:
        print ("could not find target bluetooth device nearby")

port = 1
sock=bluetooth.BluetoothSocket(bluetooth.RFCOMM)
size = 512
sock.connect((target_address, port))
print("CONNECTED")

    while True:
        data = sock.recv(size)
        data=data.decode('ascii')
        # data=data.strip()
        # imu=data.split(',')
        print(data)

The Data is getting printed like this in python: python printing data in chunks and unordered

But I want it to be like this, as in Serial Monitor of arduino yaw pitch and roll values in order


Solution

  • I would suggest sending the values as bytes. It looks like you will need two bytes per x, y, and z value of the imu. You can get the value from the imu into an integer by multiplying by a value to remove the decimal places. e.g 12.34 * 100 is 1234.

    At the other end of the Bluetooth link you can unpack the bytes and divide by the same number to get the original value back.

    Example Arduino code:

    #include <SoftwareSerial.h>
    
    SoftwareSerial hc06(3,2);
    
    struct imu
    {
      int16_t x;
      int16_t y;
      int16_t z;
    };
    
    imu state;
    
    void setup(){
      //Initialize Serial Monitor
      Serial.begin(9600);
      //Initialize Bluetooth Serial Port
      hc06.begin(9600);
      Serial.println("setup done...");
      state.x = 12.34 * 100;
      state.y = 37.00 * 100;
      state.z = -10.99 * 100;
    }
    
    void loop(){
      // Write data from HC06 to Serial Monitor
        byte buf[6];
        buf[0] = state.x & 255;
        buf[1] = (state.x >> 8) & 255;
        buf[2] = state.y & 255;
        buf[3] = (state.y >> 8) & 255;
        buf[4] = state.z & 255;
        buf[5] = (state.z >> 8) & 255;
        hc06.write(buf, sizeof(buf));
        delay(2000);
    }
    

    And example Python code:

    """
    A simple Python script to receive bytes over Bluetooth using
    Python sockets (with Python 3.3 or above).
    """
    
    import socket
    import struct
    
    serverMACAddress = '00:00:12:06:53:92'
    port = 1
    with socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM) as s:
        s.connect((serverMACAddress, port))
        data = b''
        while True:
            while len(data) < 6:
                data += s.recv(1)
            x, y, z = struct.unpack('<hhh', data[:6])
            print(f"raw data={data} : x={x/100}, y={y/100}, z={z/100}")
            data = data[6:]
    
    

    Which gave the output:

    raw data=b'\xd2\x04t\x0e\xb5\xfb' : x=12.34, y=37.0, z=-10.99
    raw data=b'\xd2\x04t\x0e\xb5\xfb' : x=12.34, y=37.0, z=-10.99