Skip to content

Instantly share code, notes, and snippets.

@maiermic
Created May 30, 2019 08:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maiermic/574547db111aa929a607d0c00c4344ef to your computer and use it in GitHub Desktop.
Save maiermic/574547db111aa929a607d0c00c4344ef to your computer and use it in GitHub Desktop.
Python example of how to send and receive serial messages from a BaseCam gimbal with SimpleBGC 32-bit controller.
from collections import namedtuple
import serial
import struct
# outgoing CMD_CONTROL - control gimbal movement
ControlData = namedtuple(
'ControlData',
'roll_mode pitch_mode yaw_mode roll_speed roll_angle pitch_speed pitch_angle yaw_speed yaw_angle')
Message = namedtuple(
'Message',
'start_character command_id payload_size header_checksum payload payload_checksum')
def pack_control_data(control_data: ControlData) -> bytes:
return struct.pack('<BBBhhhhhh', *control_data)
def create_message(command_id: int, payload: bytes) -> Message:
payload_size = len(payload)
return Message(start_character=ord('>'),
command_id=command_id,
payload_size=payload_size,
header_checksum=(command_id + payload_size) % 256,
payload=payload,
payload_checksum=sum(payload) % 256)
def pack_message(message: Message) -> bytes:
message_format = '<BBBB{}sB'.format(message.payload_size)
return struct.pack(message_format, *message)
def unpack_message(data: bytes, payload_size: int) -> Message:
message_format = '<BBBB{}sB'.format(payload_size)
return Message._make(struct.unpack(message_format, data))
def read_message(connection: serial.Serial, payload_size: int) -> Message:
# 5 is the length of the header + payload checksum byte
# 1 is the payload size
response_data = connection.read(5 + payload_size)
print('received response', response_data)
return unpack_message(response_data, payload_size)
def rotate_gimbal():
CMD_CONTROL = 67
control_data = ControlData(roll_mode=1, roll_speed=0, roll_angle=0,
pitch_mode=1, pitch_speed=0, pitch_angle=0,
yaw_mode=1, yaw_speed=100, yaw_angle=0)
print('command to send:', control_data)
packed_control_data = pack_control_data(control_data)
print('packed command as payload:', packed_control_data)
message = create_message(CMD_CONTROL, packed_control_data)
print('created message:', message)
packed_message = pack_message(message)
print('packed message:', packed_message)
connection = serial.Serial('/dev/ttyUSB0', baudrate=115200, timeout=10)
print('send packed message:', packed_message)
connection.write(packed_message)
message = read_message(connection, 1)
print('received confirmation:', message)
print('confirmed command with ID:', ord(message.payload))
if __name__ == '__main__':
rotate_gimbal()
@maiermic
Copy link
Author

You need to install pyserial. Connect the BGC board to your (Linux) computer. Turn/power on the board. It is expected to be mounted as /dev/ttyUSB0 (see line 61). Then you can just run the script and the gimbal should start rotating. You need to stop the rotation manually, i.e. using hardware buttons on the gimbal.

This script was a proof of concept. I wrote a library for SimpleBGC as part of an ongoing project. The library is not available on pypi yet. serial_example.py rotates the gimbal in one direction, rotates back after 3 seconds and stops after another 3 seconds.

Which gimbal are you using?

@jpp-coremarine
Copy link

Hi, what are the different modes for roll_mode, pitch_mode, yaw_mode? thanks

@maiermic
Copy link
Author

@jpp-coremarine See CONTROL_MODE of CMD_CONTROL in serial API specification (page 49). The mentioned library has the values typed as an enum ControlMode.

@jpp-coremarine
Copy link

@jpp-coremarine See CONTROL_MODE of CMD_CONTROL in serial API specification (page 49). The mentioned library has the values typed as an enum ControlMode.

Got it! Thanks a lot!

@Icebearbear
Copy link

Hi @maiermic , can you share the hardware connection that is used for this code to run?

@maiermic
Copy link
Author

@Icebearbear You need a BaseCam gimbal with SimpleBGC 32-bit controller connected to a Linux computer via USB. The code assumes (see line 61) that it is mounted as /dev/ttyUSB0. Do you have troubles to connect? Which hardware are you using?

@thanhhai2020
Copy link

Hello @maiermic . i am using version 2.68b0 and have CRC16 checksum. Have you updated this yet? I am using it for object tracking using YOLO and tracking algorithm on jetson Orin NX, which control mode should I use? can you help me?

@maiermic
Copy link
Author

maiermic commented May 6, 2024

can you help me?

@thanhhai2020 Yes 🤓

Have you updated this yet?

Are you missing something? 🤔

which control mode should I use?

Propably ControlMode.speed, but it depends on your use case and how you calculate, where the gimbal shoud point to.

Can you tell me a little bit more about your use case? What kind of object are you tracking (single person, multiple persons, horse, race car, etc.)? How does the object move (linear? slow vs. fast, e.g. walking person vs race car)?

What camera are you using?

@thanhhai2020
Copy link

@maiermic thank you for your reply. I am combining the BGC Pro with the PM12025 to move the camera to track the UAV. My target could be a dji mini 3 pro.

@thanhhai2020
Copy link

image

@maiermic
Copy link
Author

maiermic commented May 6, 2024

@thanhhai2020 No, I haven't changed the protocol version yet. As you can see, the starting character is > instead of $ https://gist.github.com/maiermic/574547db111aa929a607d0c00c4344ef#file-rotate_gimbal-py-L22

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment