ArduPilot Channel 4 Code

In case it is useful to anyone, here is my code for controlling the 4th channel through the Ardupilot board.

The main thing that stumped me for a while is you need to change timer2 from CTC mode to Normal mode. The default Ardupilot code has Timer 2 in CTC mode which resets the counter every time the throttle compare interrupt is captured. To drive two channels you need to be in Normal mode allowing the timer to go all the way to 255 before resetting.

Channels 3 and 4 to have noticable more granularity than the first two channels (as expected), but within this granularity, the movement is nice and reliable. In the linked video, you can see that when being controlled by the ardupilot the rudder motion is slightly more jerky.

I also added an extra flight mode to my code called SERVO_TEST. When in servo_test, the main loop skips any sort of navigation or stabilization, and simply passes the radio inputs through to the servos. I did this so I could get a feel for how well my servo code was working.

I hadn't seen any code on the site for channel 4 actually integrating into an Ardupilot software load, so I thought I would post mine..

My pin assignments are as follows:
pinMode(2,INPUT); //- Aileron in
pinMode(3,INPUT); //- Elevator in
pinMode(8,OUTPUT); //- Throttle out
pinMode(9,OUTPUT); //- Elevator out
pinMode(10,OUTPUT); //- Aileron out
pinMode(11,OUTPUT); //- Rudder out
pinMode(12,INPUT); //- Rudder in
pinMode(13,INPUT); //- throttle in

(Note that I'm using RADIO_TYPE 0, so I have no code in the RADIO_TYPE 1 sections).




Below is a video from my shop of the rudder motion, both in MANUAL mode (straight from the radio) and in SERVO_TEST mode (radio read by the ArduPilot and Passed through untouched).

E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones


  • Developer
    I have a new version of 2.7 to upload soon that has double the CH3 and CH4 resolution - 4µs steps. You should be able to try it by tomorrow if testing goes well.
  • My bad, of course the files above are not yours.. should have asked Tom. Anyway, same questions hold ;-)
  • Hello Mark,
    I'm doing a project where I'm also going to need an extra channel. I've got a couple of questions:
    - Is the code above (in the linked files) your latest version?
    - Why did you change the ch3_in code? (radio.pde, line 39)
    - You use PB4 to capture the rudder channel - normally it is used for the GPS lock led. Did you just get rid of that?
  • Developer
    Finished update of AP 2.6 with ch-4 mods, after several attempts got it to compile fine, now to test in ArduPilot! I still need to add jumper from Pin 12 to Rudder servo in signal.
    I changed code so rudder/yaw behaves like Aileron / Elevator, channels 1 & 2
    added trim function. Added some defines to header AP_2_6.h and some inits to main AP_2_6 also.
  • Hey Mark..

    I think your F7 value is more correct than my 77 value. &= 0x77 will toggle boththe 4th and the 8th Bit of the PORT B register. When I formed that hex value on my , I obviously missed the hightest bit. I think my code has been toggling that 8th bit this whole time. (Seems to work but might have some unintended consequences). I think I'll switch to F7 like you.
  • Developer
    Tom great work,
    I was able to get ch-4 running in the same fashion with normal mode back in ArduPilot v 2.2, but I used slightly different value for:

    ISR(TIMER2_COMPB_vect ) //Interrupt of timer 2 compare B, ch4
    PORTB &= 0xF7; //Putting the pin D11 (PB3) low. 0xF7 is the NOT of 0x08

    you are using 0x77 .... what value works better??

    and I combined these two into a single line...

    void init_PWM( )
    TIMSK2 = _BV(OCIE2A); // Timer/Counter2 Compare Match A
    TIMSK2 |= _BV(OCIE2B); // Timer/Counter2 Compare Match B Interrupt set active.

    my single line...
    TIMSK2 = (1<<OCIE2A) | (1<<OCIE2B); //interrupt masks for Timer2 counter A and B
    These two are line are equal, I think

    I am using Ch-4 for flaps on my Ventus 2hx powered glider

    Ch-4 is reliable, but a little course, but great for flaps.

    I will inject your newer version Ch-4 into v2.6 and see how it works...
  • Nice work Tom, do you add some jumper wires to the ArduPilot board?
  • Thanks Jason... good to know I'm on the right track.

    Well first, my plan is to tune the aileron elevator gains to get fly by wire mode working well on this aircraft. My rudder channel is currently a pure pass through in fly by wire mode.

    Once that's done, my first thought is to write a rudder control loop to zero the lateral (wingtip to wingtip) acceleration of the aircraft. Basically use the rudder to co-ordinate each turn (Ardu-"step on the ball"?). On this particular airframe the adverse yaw isn't too bad (nearly non existent), but this is the most basic use for rudder in most aircraft.

    In the long run if I can teach this thing to do aerobatics, the rudder rules will depend on the particular maneuver:
    In rolls, rudder and elevator must be used together to maintain the resultant of lateral and vertical acceleration at 1G.
    In looping maneuvers, the rudder needs to be used to zero out yaw rate.

    In preparation for this, I've already added Yaw/Pitch/Roll Rate and Normal/Vertical/Lateral Acceleration to the binary data coming out of the ArduIMU.

  • Developer
    Just read the code and it looks great. Next question is how shall we use the capability? What are your thoughts?
  • This is exactly what we've been needing for a while now. Combined with Events it's a real treat. Waypoint reached- Quickly cut throttle 5seconds, snap a photo and go to next waypoint.

    Well done! If only i knew how to implement it...
This reply was deleted.