So, this is one of my helicopters. I know what you’re thinking, “gosh, helis are so 7 years ago!” Well, not this heli. Allow me to explain…
Hitec Commercial Solutions has developed a line of UAVCAN servos with the intent of full ArduPilot support, and we had the idea to put some in the air so we could say to people, “why, yes, thank you for asking! We DO run these ourselves!” I did some requirements-gathering on the Google to make sure that the servos we chose were capable of the same speed and power specifications as the Align servos originally shipped with this kit. Before I get in to that, let me give some history…
“What is this kit?” you ask? This is a heli I bought off RCGroups a while back that came fully built and was flyable when I got it. It is an Align TREX 550E that has been upgraded to include a 600-sized DFC head and a 600 tailboom and blades. I flew it for some time trying to sharpen my 3D skills, but could never really get there since everyone wanted to get rid of their helis and tinker with mini quads. So, from time to time I’d bring it out, but honestly it sat for some time. I always wanted to get comfortable flying helis, maybe in some 3D, but since no one I flew with normally would fly helis I didn’t have anyone to learn from, and since the FBL on it was BeastX, there was no bail-out in case I got stuck. I was pretty deep in to ArduPilot at the time, but wasn’t sure if I was ready to do some TradHeli stuff.
Fast forward to Q1 2019, I called up @lthall and said “dude I’m doing this, is it safe” and he said “yeh mate all good.” So I set off and installed a Pixhawk 2.1 (don’t hate me Philip, that’s what it says on the top of it!) to a totally different helicopter: an Align 700L DFC heli that just commands some respect in the air. I wanted this to be more a UAV-style copter that I could do autonomous missions on, but also some FPV and mild acro. I had plenty of zip ties, and I learned through the years that heli guys love their zip ties, and they love securing everything down. They’re like cats in that regard: nothing can move! So I installed TradHeli, got everything squared away, and went through the tuning process on ArduCopter 3.6.9, putting a pretty good stress on my friendship with Leonard because I’d constantly hit him up and say “ok look at this log with me” and “how can I make that thing it’s doing be better.” I even got Bill and Chris to help me on some forum posts. But, I never had an incident with that 700, and it got me confident. Then Leonard came to the States for a visit and wanted to fly the heli, but my radio was a jerk and was ignoring trainer-inputs from his radio. You may be asking, “but, why did you have to use a trainer radio, this has ArduPilot - just let him bail out to Loiter!” Well, Leonard flies Mode 1. He’s one of those people. Monsters. I fly mode 2, and when you’re talking about taking the sticks of your friend’s 700-sized heli, you want to be as comfortable as possible. He was happy to just work the ground station with me and help maybe tune it even better:
But I ultimately got him to fly it around in Loiter and I think even Stabilize for a few moments:
He was hooked too! You could tell he was enjoying it because his smile in this picture wasn’t even forced or anything!
Awww, look at how happy that little mudskipper is!
Fast forward a bit more… to the relevant part. I was talking with some folks at Hitec and one of them (Shawn) says, “We should do UAVCAN servos on your heli!” I say “Dude, that’s awesome, I have plenty of zip-ties, let’s do it on my 550 that I have been wanting to set-up with ArduCopter anyway!” I think Shawn really wanted them to go on the 700 since he had seen that fly, and it is a bigger heli, but I knew the 550 was going to be the one I would work and push harder, so ultimately it was the chosen one.
I verified the requirements of the servos by comparing torque and speed ratings of the existing servos in the heli and finding the appropriate Hitec Commercial UAVCAN servo to replace them. Shawn and I decided on the MD950TW but the ones that were in stock had slightly-slower-yet-way-more-torquey gears installed. I couldn’t find anything one way or the other that said if the speed they provided was “fast enough” so, knowing that in a control system you can never have too quick of a response time we opted to re-gear them to the same speed/torque by using the gears from the D940TW. Once this was done, it was time to get after it…
Now, you can’t just physically install UAVCAN servos and be done with it. You have to configure them. Configuring the UAVCAN servos from Hitec requires use of the DPC-CAN programming dongle, and the software utility. It isn’t hard, but, in fairness it could be easier.
There were a handful of configurations I needed to perform:
- End-point adjustment
- By default they swing like 170 degrees or something and I only wanted 90, but I still wanted full resolution of -1 to 1, (aka 1000 to 2000) so I remapped the endpoints on the MD950TWs so that -1 (1000us) and 1 (2000us) end up on the servo’s sweep, while 0 (1500us) is still the middle of the sweep
- They need to know what “node” is master on the bus. Typical config in ArduPilot is that the flight controller will be Node 10, so you have to tell each servo that Node 10 is its boss.
- I needed to enable “streaming”
- More on this later but basically this is what enables the status message from the servo back to the autopilot
- Each servo needs to know what its actuator_id is
- In ArduPilot, you connect servos to PWM pins and then configure the _FUNCTION for that PWM to be whatever you want to be. In ArduCopter, you use servo functions 33, 34, 35 and 36, usually on PWM1-4. But I’m plugging in to the CAN port, so I need to know which physical servo is going to map to that function in ArduPilot. Details below.
These are relatively easy configurations to make, but it is easy to do it not correctly in the current iteration of the software tool. I’ll put up another article on the very wiki soon and link to it here once it is up on how to configure the servos, but for now, let’s move on. It is worth saying though, these servos are NICE. And they are very powerful. I kind of love them.
At the time of the initial installation, Tridge and I did some remote sessions where we were desktop sharing, trying to get the status messages working by sniffing traffic on the CAN bus. It was pretty fancy thing we had set up, I even had a second autopilot hooked up at one point trying to act as the sniffer, but ultimately we had to table that effort because we simply were not seeing data come back out of the servos. We went down that path because we both thought it’d be cool to get the UAVCAN status messages in to ArduPilot and then if it were easy, get them logged in to dataflash. I was checking with internal Hitec engineers to see if the streaming of the status message was even supported. While working through that process, I decided to finish the ArduCopter config by piping SERVO1-4 across CAN1 and verifying I was getting control from the CUAVv5Nano to the servos, and that was all good. Next, the physical and autopilot configurations were completed, including setting the ESC and AutoPilot up to look for a headspeed of about 2400RPM. I set the BEC to deliver 8.0V to the servos (again, you can’t have too much powah!) and used one of our internal dev boards to connect the servos to the CAN1 port:
Since there isn’t enough current in the CAN accessory ports of these flight controllers, I soldered the bec voltage to the CAN breakout board (again, this is an internal board not yet ready for commercial consumption, but one is coming), and started zip-tying everything down. That was probably the most tedious part! #somanyzipties
Finally the time came. I finished my ground checks and took the heli outside, hoped super hard that it didn’t crash or try to take my head off (because all you need is a little hope!) and spooled up. It flew fine. In fact it was pretty uneventful. I had used a combination of settings from my 700 heli as well as some of the recommended defaults from the tuning wiki and it was… fine. I knew it needed tuning, but, it was fine. I even went in to Acro and did a back flip, which was comical to say the least since Yaw was nowhere near the tune it should have been for that attempt. But it was fine. I loitered, I stabilized, I even AltHolded. All good.
I spent a few days (over a few weeks) doing tuning flights, trying to get the VFFs right, the YAW tune right, etc. It was feeling ok, but I knew the performance could be better. One thing I noted was that the P and D terms were all very low in order to not have oscillation. I was getting a little frustrated, and through the course of verifying settings across the entirety of the Heli, went to check something on the servo configs… And there it was: this beautiful checkbox that has been there all along, “Stream Mode”
I turned it on, and immediately called Tridge. I felt bad, because even though we had just gotten off a call maybe 10mins prior, I didn’t give him a heads up before calling back and he may have been busy cleaning his desk or something, he does that from time to time, but he answered. I told him I found this check box, so we hooked up the UAVCAN_Gui_Tool and verified we were seeing servo status messages! YEAH!!! We decided on 20Hz for the stream rate and he quickly provided a firmware to test and see if we could log this data. This was going to be so cool!
It didn’t work.
But then he found out why and provided an updated firmware to test. It worked! The ArduPilot dataflash logs now contained the data - at the rate specified by the servo - that the servo was providing. This servo data is in accordance with the specification provided here and delivers the following elements:
- Actuator ID (servo number)
- Power Rating (percent)
Tridge then published and ultimately was able to merge PR13163 that not only captured this data, but also data from UAVCAN ESCs. Yay! Later in the tuning process, and Bill and Leonard can explain this way better than I can, we were able to use this data to prove that control system lag between desired rate output and actual rate output observed by the autopilot was not something inside the control system itself, that all that lag is post-actuator. Even while logging at only 20Hz while actuating at 400Hz, the data had already proven useful!
I resumed the tuning process by following the guidance for using a dynamic notch filter, an amazing piece of control law magic provided by Andy and Leonard. The next problem I ran in to was one I had anticipated: I was asking the ESC for all it had with regards to RPM, so there wasn’t enough overhead for an appropriate level of margin to safely “govern” the RPM. I found myself not too much caring about that lack of margin, as this heli was being built to be a 3D thing. So I hit up Leonard again (and again… and again… and again) and we spent a LOT of time getting filters right for this heli. I even had a series of conversations and a call with Bill, and even got Bill and Leonard on the same call together to help me. Bill kind of got ninja’d in to that call (sorry Bill) but it all proved very helpful. These guys very much care about the success of this system, and my appreciation for not only their help, but also their patience along the way, cannot be overstated.
Through these conversations, it got to the point that Leonard and I started getting experimental. We were able to see the headspeed was coming out of the dynamic harmonic notch (which was effectively set up as a static harmonic notch) from time to time and that noise would find its way in to the system. No biggy, I knew that was going to be the case so I finally installed an RPM sensor, changed the configuration to follow the headspeed, and that noise went away. We also were able to find some valid reasons for a filter down low, in the 9-13Hz range. Leonard and I initially decided to put a static notch at 9Hz, and later followed up with a change to 11Hz. That squashed a lot of noise too, but there was still something else even lower. Again, Bill and Leonard can go in to what types of noise this crap was. I’m not a control law guy, so, I do what Leonard tells me, or what Bill tells me, unless they don’t agree. Luckily that “don’t agree” thing doesn’t really happen.
Leonard and I took some slightly different approaches to the Low-Pass Filters for Roll, Pitch, and Yaw than I think some other TradHeli folks may have done. First, for Roll and Pitch we ended up gradually stepping the FLTD and FLTE all the way down to 5Hz. Bill cautioned that this will introduce a laggy feel, something he called out because he knew I was trying to specifically tune against. We proceeded with caution but as I would lower those two LPFs down 5Hz, I’d re-tune D and P for that axis, until reducing it didn’t really result in the ability to tune D and P higher. That ended up being 5Hz. I then re-tuned Angle P for Roll and Pitch. Roll ended up at 9.6. Pitch at 8.5.
Next I wanted to get aggressive with Yaw. I had taken a video of the heli with BeastX on it doing a bunch of “yaw spins” in both directions as well as backflips and rolls. We examined that video and determined I was getting about 540deg/s on Yaw with no bounce-back. So I edged my Yaw Rate demand up to that, turned my accel for Yaw from 100,000deg/s/s to 150,000deg/s/s, and began again the process of tuning Yaw. I should note that we started tuning Yaw initially with no feed-forward. This was a conscious and intentional decision early on. As I was now flying a heli that had a pretty darned good Roll and Pitch tune, we felt safer pushing Yaw to see how we could do. This is where some frustration started to kick in again on my part. I wasn’t getting discouraged yet, but, I felt like I might get discouraged soon… I could do 1, 2, 5 yaw spins in either direction, and the log data would always show that we’re meeting the rate demand as well as the DesiredYaw angle, but if I let off the stick, there would be bounceback. Depending on where we were with the tuning, that bounceback would range from 10 degrees to once as many as 90. We played with various values for the I term for Yaw, as some of this bounceback was definitely coming from a build-up of the integrator. I got it to the point it wasn’t bouncing back, but at the cost of unacceptably reduced Yaw Rate, and Accel. At this point, Leonard did his maths thing and we came up with a value to put in to the yaw feed-forward controller. Things started getting better, but never what it should be. If we go higher in FF now, we overshoot Yaw Rate and still end up overshooting on the stop. I fine-tuned a few things to get it as close as we could get it, while still having some bounceback. It wasn’t going to be too often that I’d want to do some clever full-rate Yaw move, but, I’d know it was there and it was bugging me. So, we left that Rate and FF tune and I started tuning Angle_P for Yaw. I had to give up on that too, but for a pretty interesting reason: I was able to get the tuning knob for Yaw Angle_P to go as high as 20 with no oscillation! It got sharp, sure, but, the bounceback wouldn’t go away and it just got more “twitchy” as I’d go up. So I just arbitrarily said “ok 15 it is.” and left it there. The reason this process got frustrating was because in the attempt to arrest the spin, the controller would never ask for max actuator output. In my rookie opinion, if I set a min/max value for a servo position for a given axis, I want the controller to be able to use that whole range of motion for control. Otherwise, why am I even setting it? This felt like a short coming of the controller to me, but I was hesitant to just come out and say that because I was fearful I’d hurt Leonard’s feelings (he’s a delicate flower sometimes) or damage a new relationship I was starting with Bill. Then they were like, (and I’m paraphrasing) “Ok this is a shortcoming of the system, and here’s how we want to fix it.”
This work got Leonard very interested in seeing how low we could go with the low-pass filters on Roll and Pitch. I set off to the field and turned the FLTD for Roll down to 2.5Hz and was able to get higher P and D gains for Roll. We decided to move the FLTE for Roll to 10Hz and move to Pitch. With Pitch, I was not able to get a better tune by bringing FLTE down to 2.5Hz, in fact it started to get worse. So I moved Pitch’s FLTD back to 5Hz, FLTE back to 10Hz, and did some verification flights that all checked out well.
It was around this time of “trying to get that darned bounce-back ou of Yawt” saga that Leonard and Bill both started talking about a D term for FeedForward. Again, I’m not a control law guy, but, that sounded very interesting to me. To me (the uninitiated) the thought of getting a D term on VFF meant I could get even more rapid-response to rate requests without the risk of overshoot AND with a reduced chance of oscillation. Both Leonard and Bill on their own confirmed that this will help me get to full actuator output for instances like this, as well. This sounds like the thing I have been waiting for. Leonard and Bill had a series of very technical conversations that I got to listen to, and I came out of those conversations thinking, “My heli is going to fly so gooood!”
Leonard set up for the “VFFD” settings, and Bill complimented that work with their System Latency work, which Bill needs to explain because I’ll do a horrible job representing the amount of engineering that goes in to that work. Before installing the dev firmware with VFFD, I did a series of SystemID flights for Bill, and then some for Leonard, and one more for Bill after he got a chance to review the initial set of tests. The SystemID stuff is deep in Bill-land, but at a high level the output of that work is that my heli has virtually no latency compared to the more UAV-style setups we typically see in ArduPilot. Because of that, I have offered up to run the same tests on my 700-sized UAV heli that I like to fly around upside-down with a 360 camera on it, but that is a story for another time. But, at this point, I built and loaded up the firmware that had the FeedForward Dterm (“VFFD”) capabilities, Leonard worked out some predictions for the values for each axis, and sent me out to fly. Fortunately, he also instrumented some new tuning-knob capabilities for me that will be coming to Master soon:
TUNING_RATE_PITCH_FD = 59, // body frame pitch rate controller FD term
TUNING_RATE_ROLL_FD = 60, // body frame roll rate controller FD term
TUNING_RATE_YAW_FD = 61, // body frame yaw rate controller FD term
TUNING_STABILIZE_ROLL_KP = 62, // stabilize roll angle controller’s P term
TUNING_STABILIZE_PITCH_KP = 63 // stabilize pitch angle controller’s P term
I was particularly happy with the ability to tune Stab-P for Roll and Pitch independently, thanks Leonard!
Prior to starting this session, Leonard and I decided to start getting less experimental with the low-pass filters due to some D oscillations we could only see in the logs but not in flight. So we agreed for Roll and Pitch to set FLTD back to 5 from 2.5, bringing it in line with what Pitch was set to from the last session out. We may consider going back up in the future but, every time we change this requires a re-tune of D and P for that axis, so for now we set FLTE for Roll and retuned. (remember, the reason we were bringing FLTE and FLTD down was because we weren’t able to get any stability control from the Rate pids due to the high level of noise in the system; filtering that out let us get D and P up to a point where they were assisting the way they were supposed to.)
Once I re-tuned D and P for roll, it became time to start rolling in the FeedForward Dterm.
I started with Pitch, setting the tuning knob to 59, the tune_min to 0 and the tune_max to the prediction. In flight I ramped the slider all the way high and noticed a nice crisp performance going in to maneuvers. I landed and did the same for roll, with the same experience. With Yaw, however, as I got past half way to the predicted value, I started seeing slow but steady yaw oscillations in hover. The oscillations were gone at about half-way, so I landed and disabled the tuning knob, saving the parameters for each axis.
In performing a test flight after doing this, I accidentally had a tail-strike, causing some damage to the heli that requires some replacement parts before my next flight, so I’ll update progress on this tuning in the coming weeks, and I’m planning on bringing this heli to Canberra for the ArduPilot Developer’s conference next month. Should be a good time!
I think my biggest eye-opener and take-away so far, after of course the willingness and eagerness to help from Leonard, Bill, Tridge, Shawn (Hitec) and even Paul with some EKF3 observations I’ve had, and some other folks, is the impact that the filtering has had. Don’t get me wrong, I’m not new to deep-dive tuning or filtering in general, but you have to understand that I had an ok-flying Heli pre-filter that was flying basically no P and D on roll/pitch, to a pretty-darned-nicely flying heli that isn’t flying as much P and D as it could be, but is flying measurably and objectively very well. The control and responsiveness is impressive from my not-expert-heli-flying background (I can do a thing or two, but I’m no Tareq Alsaadi). There are some improvements to be made, sure, but you really have to dive in to find them. Thank you to everyone involved in building and maintaining this system, it is truly awesome.
Here are what I think are the relevant specs of the heli:
Heli: Align 550E DFC, modified with 600-sized DFC head and 600-sized tail; stock KDE 1175kv motor, Castle ESC, 6Sm 550mm mains, 96mm tails, 112T/11T, 131T/34T
UAVCAN Servos: Hitec Commercial Solutions MD950TW
AutoPilot: CUAV V5 Nano; Here GPS (I suppose I should put a Here2 on this to make it even more UAVCAN, but I don’t have one, sadface) ; Hall Effect RPM monitor; 915MHz telem radio;
Firmware: ArduCopter 4.0.2-rc4 (as of this writing)
Control: Horus X12S with RX4R
Yaapu Telemetry: Ready
Current Zip-tie count: 31
Sorry Leonard for not making this an Audiobook, but for all those who followed along so far, thanks for your interest! I’m certain all this work we’ve done will result in an even more-capable system for folks to fly their Helicopters with.