Ive been trying to get a RPI setup to listen to a Mavlink assigned port on my FC, and run code when the MAV_CMD_DO_DIGICAM_CONTROL (203) command is seen.
I’ve been unable to see this command, and I’m not certain what I am missing. I’m seeing data on the port, and I’m able to see a heartbeat, but nothing else.
Unfortunately I’m a bit too green to understand the linked example/make it work yet, but the concept of requesting the messages has helped.
I’m able to see the RPI now as sysID 0 in mavlink investigator, which I wasn’t before.
I’m able to send a message, and receive acknowledgement from my FC on sys ID 1, but I dont understand what/how to set the message rates. It seems like MAV_CMD_SET_MESSAGE_INTERVAL (511) might be what I need to send, but I get errors when I try 511. Is there any further direction you could give on this- or is figuring out that example code the way to go here?
This is what Im currently working with
"""
Example: Set that a message is streamed at particular rate
"""
from pymavlink import mavutil
# Start a connection listening on a UDP port
connection = mavutil.mavlink_connection('/dev/serial0',baud=921600)
# Wait for the first heartbeat to set the system and component ID of remote system for the link
connection.wait_heartbeat()
print("Heartbeat from system (system %u component %u)" % (connection.target_system, connection.target_component))
connection.target_system = 1
connection.target_component = 0
# Define command_long_encode message to send MAV_CMD_SET_MESSAGE_INTERVAL command
# param1: MAVLINK_MSG_ID_BATTERY_STATUS (message to stream)
# param2: 1000000 (Stream interval in microseconds)
message = connection.mav.command_long_encode(
connection.target_system, # Target system ID
connection.target_component, # Target component ID
mavutil.mavlink.MAV_CMD_SET_MESSAGE_INTERVAL, # ID of command to send
203, # Confirmation
mavutil.mavlink.MAVLINK_MSG_ID_BATTERY_STATUS, # param1: Message ID to be streamed
1000000, # param2: Interval in microseconds
0, # param3 (unused)
0, # param4 (unused)
0, # param5 (unused)
0, # param5 (unused)
0 # param6 (unused)
)
# Send the COMMAND_LONG
connection.mav.send(message)
# Wait for a response (blocking) to the MAV_CMD_SET_MESSAGE_INTERVAL command and print result
response = connection.recv_match(type='COMMAND_ACK', blocking=True)
if response and response.command == mavutil.mavlink.MAV_CMD_SET_MESSAGE_INTERVAL and response.result == mavutil.mavlink.MAV_RESULT_ACCEPTED:
print("Command accepted")
else:
print("Command failed")
I guess my confusion is what to do with it. With “203” in the code, It seems to succeed, but not in what I need to accomplish. I am looking to listen for when the fc gets/runs 203- so I can run a cam from the pi.
Try adding a statustext monitorig block as the bottom of your script:
while True:
msg = connection.recv_match(blocking=True, timeout=0.5)
if msg:
if msg.get_type() == 'STATUSTEXT':
#print STATUSTEXT packet text
print(msg.text)
That way you’ll be able to see any error messages that come from the ArduPilot.
You need to understand MAVLink routing to configure everything correctly. But in short,
Your onboard RPi must have the same SystemID as the FC
Your RPi must emit heartbeat (typically at 1Hz)
Your RPi must have ComponentID that isn’t 0 or FC ComponentID (IIRC typically 141 1) or Component ID of any other device on the same vehicle.
then Ardupilot should route communication to and from the RPi correctly (according to MAVLink routing rules) and you should see your camera on MAVLink inspector.
Then you have to configure Ardupilot for camera control over MAVLink by setting CAMx_TYPE to MAVLink (5) or MAVLinkCamV2 (6) depending on MAVLink camera control protocol you want to use.
Sounds like I’m definitely missing the proper ID setup. I was viewing this as the RPI having none- or a unique SysID,(this was also suggested to me from a skilled ardupilot member) and I had assumed that the componentID was not important for this task and could be left 0, but the description you provided makes perfect sense.
I had this mavinspector screen open on my laptop this morning from previous tests, so I included it.
Just to ensure I understand, this shows my FC as sysID 1,component 1, my GCS as sysID 255, component 190, and my RPI as sysID 255, component 0. ? I’m fairly certain I will need to set the sysID and compID in python for the RPI and not in Mission planner, I’ve looked quite a bit at the available settings for Mavlink comms there along the way- and do have the camera options set the Mavlink.
I’ve been able to set Sys and comp ID’s, after alot of fiddling
As directed- Target and source need to match, which looks like I have right, and I have a comp id that is not 0. I also seem to be sending a heartbeat, but, My listen code is not getting anywhere still.
It would seem the message Im trying to listen for is routed specifically from GCS to FC. I can see in the Ack from FC, its sending the ack to SysID 255, comp 190. (Im assuming the same occurs when the message is sent from GCS to FC, but Im disconnected/away currently) Seems to me that these messages would not be available to the pi since they are specifically routed. I either need to change the component type to 0 to broadcast, or, set my pi to the same systemID and component ID as the FC? This would deviate from the advice given from @LupusTheCanine however.
So in the below, my RPI wont see this ack message from the FC, as its being routed to sys255, comp190. IF I set the rpi to 255, 190, I might be able to see the message? Seems having 2 devices with matching addresses is not correct however.
If your message targets broadcast component or RPi it should reach the RPi.
If Ardupilot gets commanded to take photo it emits appropriate MAVLink command (assuming it is configured for MAVLink camera control)and it should emit its own ack. Your digicam will send it’s ack to the FC and it should forward the ACK to GCS).
My message comes from the GCS, from what I see the comp ID is set dynamically for it? So I didnt see a way of broadcasting the command from GCS so the RPI could see it.
When Ardupilot receive a command to capture a photo (from GCS/LUA,…), it will also emit and broadcast CAMERA_FEEDBACK message - you should see it in mavlink inspector and also as a mark on Mission planner map. Camera should be configured as mavlink type.
Then you can easily capture it on RPi (with same sysid as FC and different component id) like this:
msg = connection.recv_match(type=‘CAMERA_FEEDBACK’, blocking=True,timeout=1)
I’ve turned to Claude to try to work through this on a suggestion.
Nothing I (we) have tried seems to catch a 203 command.
My code is currently setup to display all messages, so its a constant stream of messages from FC (presumably) so I can’t really see any flaw in my physical connection.
I’ll keep plugging away at this I guess. If anyone has suggestions of Mission planner tools to help troubleshoot that I might not be aware of, or other tips, Im all ears.
Are there any other prerequisites to having this DO_DIGICAM_CONTROL (203) command be broadcast that I might be overlooking? If I take a freshly flashed FC, set cam1 type to mavlink, and trigger from right clicking the map screen, DO_DIGICAM_CONTROL (203) gets broadcast and not directly routed to the connected FC?
Thanks for this suggestion. Since my approach is still not working after numerous attempts and angles following documentation and responses here, I’ll try this as a means of knowing the message has been sent and confirming the pi sees/handles the message.
Do you have CAM1_TYPE set to 5 ?
Then when you execute “Trigger camera NOW” in Mission planner, you should see msg 203 from GCS and also msg 180 from FC in mavlink inspector (then its simple to capture 180 on RPi).