Rc_channels_override_send() takes from 11 to 12 positional arguments but 21 were given

rc_channel_values = [65535 for _ in range(18)]
rc_channel_values[channel_id - 1] = pwm
master.mav.rc_channels_override_send(
    master.target_system,                # target_system
    master.target_component,             # target_component
    *rc_channel_values)

It makes an error that “rc_channels_override_send() takes from 11 to 12 positional arguments but 21 were given”
does it mean it only have 8 channels? I want to makes the light on through mavlink.

Hi @ivanchen, welcome to the forum :slight_smile:

The error occurs because your mavlink thinks it needs to communicate using the mavlink 1 protocol (pymavlink default), but ardusub actually uses mavlink 2 (newer and improved), so our documentation is tailored to mavlink 2 examples. If you run master.wait_heartbeat() right after you create the mavlink connection then it will detect that the autopilot is using mavlink 2 and will switch to the correct function.

More generally, for turning on the lights I’d recommend instead using the set_servo function (e.g. master.set_servo(output_channel_number, pwm)) - it’s simpler since you directly set by the output servo channel rather than the input channel, and is less to type. We’re currently in the process of revamping our pymavlink docs, so that should be available in an example soon :slight_smile:

For now, note that the output servo channels are directly based on the pixhawk outputs. The ‘Lights’ input channel (for controlling via QGC and rc_channels_override) is 9 but can be assigned to various output ports depending on your preference/setup. By default the lumens are plugged in to port AUX 2, which servo output 10 (8 MAIN, +2 AUX), so for turning on the lights there you would use

import time
from pymavlink import mavutil

# assuming connecting from surface computer
master = mavutil.mavlink_connection('udpin:0.0.0.0:14550')

# wait a heartbeat to confirm connection and determine mavlink
#  protocol version 
master.wait_heartbeat()

# turn on the lights (servo output 10, AUX 2) to half (1500us pwm)
master.set_servo(10, 1500)
time.sleep(5) # leave them on for 5 seconds
master.set_servo(10, 1100) # turn them off again
2 Likes

Thank you for your reply! : )
The light still doesn’t work via your thought.
Should I set the environment variables in advance? I used to think it’s not necessary to set the environment after install pymavlink via pip.

When I run the py, the process stuck at the “master.wait_heartbeat()”, why it happend?

Have you checked which pixhawk port your light is plugged into? It’s possible it’s in a different port than the one in my example.

You can, but it shouldn’t be required. Once the heartbeat is successfully detected from an autopilot that’s running mavlink 2, pymavlink should automatically detect that and change to using mavlink 2 as well.

That means you don’t have a valid connection to your autopilot. There are multiple possible causes of that, but they depend on your setup. Assuming you’re trying to connect to your pixhawk from your surface computer, via the udp endpoint provided by the companion computer, then you’ll need to make sure your program has access to udp streams. If you’ve set up your network settings correctly (e.g. QGroundControl works as expected) then it’s possible you just need to allow python through your firewall, in the same way that you did for QGroundControl.

Thank you for your reply and your patience!
I’m sure that the light plugged into the AUX2, but that doesn’t work. In addition to, I tried set_servo(, ) from 1 to 8, pwm from 1100 to 1900 but all the motors on it doesn’t run at all. However, I still can control the motors via RC_Channels and MAV_CMD_DO_MOTOR_TEST. Why the set_servo doesn’t work?

Have you confirmed that the wait_heartbeat() call is completing? If you don’t have a valid connection with the autopilot then no commands you send will work as expected.

The set_servo functionality is intended to work for non-motion outputs (ones that aren’t being used for control of the ROV’s movement), whereas the rc_channels commands are simulating pilot input (so can control ROV movement) and MAV_CMD_DO_MOTOR_TEST commands are set up specifically to control individual motors, so can also control motors. It may be possible to get the set_servo functionality controlling motors, but I’m not sure what settings/parameters need to be set for that to work.

If you’ve confirmed that the wait_heartbeat message is completing and returning a heartbeat message, but set_servo still isn’t working to turn on your lights, could you send a photo showing the pixhawk ports, to confirm which port the lights are plugged into? :slight_smile:

Thank you! I’ve solve the problem by pluggng into the Rpi GPIO rather than the pixhawk. Another question come out that sometimes the Pi or my PC cannot receive the heartbeat from the pixhawk via USB connections(the process stuck at the “master.wait_heartbeat()”). I connect them with a USB-MicroUSB wire. Sometimes I reboot or replug the pixhawk the heartbeat comes, so strange. Do you know how can I deal with it?

That sounds like a workaround rather than actually solving the issue with your pymavlink connection, but if that’s sufficient for your purposes then ok.

It’s a bit hard to say without knowing the code you’re running when you’re connecting in the different configurations. The master.wait_heartbeat() call is blocking, and if you don’t have a valid connection then it will wait forever. As I mentioned two comments ago,

I would suggest creating the mavlink connection in pymavlink after the relevant physical connections are set up between your electronics, if you’re not already doing that.