Day four was our final day of prototyping so we really wanted to get the ball drop working. We felt that being able to launch, fly a significant distance, drop the ball on a target, and return to a safe landing would give us a minimally viable entry for the Sparkfun AVC.
Having had no success with the passive drop on day three, today was all about programming the Pixhawk to activate a servo motor to initiate the drop. We constructed a simple prototype using some of the parts we had previously printed and then figured out how to wire it into the Pixhawk. It took some time to learn the idiosyncrasies of Pixhawk programming and get it to send the correct servo command at the right time. Perseverance was the word of the day, and it paid off in the end.
You can see the culmination of our four days of prototyping in the summary video, and then read on for all of the (hopefully) interesting details.
You Got Servo-ed
After constructing a quick and simple prototype of the drop mechanism, we attached it to the quad-copter using duct tape, that time-honored prototyping tool.
One of the major pain points of the day was finding good documentation for our specific situation. It's very possible that we just never happened to find the correct, up-to-date docs, but this was a major source of confusion.
The Pixhawk has 8 ports labeled MAIN OUT and 6 additional ports labeled AUX OUT. Based on the best information we could find, our initial guess was that the AUX ports should be used for controlling servos, and that we should pass a servo number of 1 to the DO_SET_SERVO command if we wanted to use AUX port 1. The command's position parameter was another uncertainty. We read that typical position parameter values ranged from 1000 to 2000, so we began with values in that range hoping to just see any movement that would confirm that we were on the right track. When we tried to run the program, the servo just sat there silently mocking us. At this point, the list of potential problems was long:
- Was the servo connected properly?
- Which port should we use?
- Did we use the right servo number in the command?
- Were we sending it valid position values?
- Is our DO_SET_SERVO command even executing?
- Did we need to initialize the port or set other initialization parameters?
What were we doing wrong? Well, as it turns out, all of the above. Let's take them one at a time and we'll share our discoveries and solutions along the way.
Was the servo connected properly?
It was time to go down to the hardware level and eliminate some of our unknowns. We started probing the Pixhawk's output ports with a volt meter and an oscilloscope.
We discovered some things that surprised us. The Pixhawk does not supply power to any of the power pins on its bank of PWM output ports. The only port that has a working 5V power pin is the RC IN port, which is used to talk to the receiver. We couldn't see an obvious place to get 5V power from the Pixhawk itself, so as a work-around we used one of the PWM outputs of the receiver module, which was powered by the Pixhawk's RC IN port. This is a bit of a hack, but it worked.
Which port should we use? Did we use the right servo number in the command?
We discovered that there is a servo test interface in the Mission Planner app. The docs say that it doesn't actually work, but some reports from the internet indicate that it does. When we initially used this interface to test our servo, it would never move, but we couldn't be sure if it was a working test.
After figuring out the servo connection as described above, we were able to confirm that the servo test interface in Mission Planner does indeed work! We were able to see output on MAIN port 8 when toggling the output of servo 8 on the UI. Some quick probing verified that servo numbers 5 - 8 correspond to ports 5 - 8 on the Pixhawk's MAIN OUT ports. The AUX OUT ports 1 - 3 map to servo numbers 9 - 11 on the test interface. Presumably, AUX OUT 4 - 6 map to servo numbers 12 - 14, but the UI didn't allow us to test that. We chose to use MAIN OUT port 8 for our servo, so as to avoid ports 1 through 6 since they will be used by the motors on our hex-copter.
Were we sending the servo valid position values?
Using the servo test UI, we could now determine that the proper position values for our mechanism were 100 and 1900 for the open and close position. This was an exciting moment - the servo was finally moving. It was a big step for us even though it could only be controlled through the test UI. We were finally confident that our servo should work if we could figure out how to execute the commands properly
Is our DO_SET_SERVO command even executing?
There are some gotchas in getting the DO_SET_SERVO command to execute properly. First, you can't just run a mission to move a servo. The servo command needs to be sandwiched between two navigation commands. But, not just any two navigation commands. The navigation commands need to take long enough to execute that the servo has time to complete its movement. This means that the waypoints must be far enough apart that they will not trigger before the servo has the chance to open all the way. We ran into a few more gotchas before Matt figured out a workable solution of a nav command followed by a single servo command, followed by another nav command (not too close to the first one), followed by another single servo command, and one final nav command. Trying a servo command followed by a condition delay didn't work.
We had hoped to test the servo with a tiny mission that we could execute indoors with the propellers removed from the quad-copter, but were unable to get that to work. We are still looking for a good way to debug mission programming, so let us know if you know how to get feedback from Pixhawk that would let us know when our commands are being executed.
The end result was a mission that could reliably and accurately drop a tennis ball on target, but it was a bit of a struggle to get there.
Other Progress and the Future
Aside from helping us debug servos, Alex was also able to make some good progress on the vision front. He installed a patch that allowed him to build a version of OpenCV that was able to properly enumerate menu items when using V4L2 (video for Linux 2). The bottom line is that we are finally able to capture frames from the USB camera that is connected to the Jetson board. That was a big step forward for our vision effort. Now that we have frames to process, we can start writing code to identify our balloon targets.
This brings us to the end of an extremely fun week. Matt and Alex are off to Las Vegas to compete with the Colorado ARML team (editor's note: Good luck, boys!) and so we are concluding this series of daily updates. This week has given us a great start at building an entry for this year's AVC, but we certainly have a lot more to do. We cannot yet find and pop balloons, but hopefully we'll be able to solve that problem in time for the competition on June 21st. We will post future updates and videos as we go, albeit less frequently. Thanks for reading!