Ardupilot: 4 channels

Hi,I'm staring at my ardupilot this morning and the ardupilot code and I'm not making all the connections in my head.I see that the v2.2.3 code is setup to be able to read ch1 and ch2 coming from the receiver and is able to drive ch1, ch2, and ch3 for the output servos.I would very much like to reach ch3 and ch4 from the receiver. Is this possible? Are the appropriate pins connected on the Atmega328 that will allow me to do this? The current code appears to use pins 2 & 3 for servo inputs. What pins would I use to read channels 3 & 4 (or are these not connected and I'm out of luck?)Going in the other direction and looking at servo outputs ... how would I setup the code to drive a 4th servo? I found a posting from January (?) with one way to drive channels 3 & 4, but it looked like it was pretty cpu intensive, and it looks like the ardupilot board design has changed a bit since then ... and it looked like Jordi came up with a much cleaner way to drive ch3. What should I do to get the 4th channel running?Thanks,Curt.

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

Join diydrones

Email me when people reply –

Replies

  • Developer
    Hello Curtis,

    Let me explain a little bit the theory of operation. I pasted the code and i comment it better:

    OCR2A and OCR2B will control the servo position. The resolution is 8uS so if you need to pulse the servo to 1500us then you set the OCR2A=187 (187*8=1496uS). Is the same with OCR2B.

    The next code shows how and why i setup the registers:

    /*************************************************************/
    /*From here everything was made to create the throttle servo*/

    TIMSK1 |=(1 << ICIE1); //See page 136, timer 1 interrupt mask

    //Setting up the Timer 2
    TCCR2A = (1<<WGM21); //CTC mode
    TCCR2B =(1<<CS20)|(1<<CS22); //prescaler 128, at 16mhz (128/16)=8uS, the counter will increment 1 every 8us
    OCR2A = 138; //1104us/8; The top, when the counter reaches the value defined here will execute the interrupt, 187 is the servo centered...
    OCR2B = 187;
    TIMSK2 = (1<<OCIE2A)|(1<<OCIE2B); //interrupt masks for Timer2 counter A and B
    sei();//Enabling interrupts
    }


    The next part of the code is using Timer1, that generates an interrupt every 20uS. SO every 20uS the code is inside this function will execute. Note that every time it executes, it will restart the counter of TIMER2 (TCNT2) later you will know why, also will set the pins PB0 (D8) and PB3(D9) to high (start of the pulse):

    ISR(TIMER1_CAPT_vect)//This is a timer 1 interrupt, executed every 20us
    {
    TCNT2=0; //restarting the counter of timer 2
    PORTB |= 0x09; //Putting the pins high PB0 and PB3 (pin 8 and 11 of arduino)...
    }

    Now the Pulse for the servo started. Now Timer Compare A (pin 8) and B (pin 11) will start counting. After the timer Compare A or B reaches the desired pulse width (OCR2A&B set the limit) it will generate another interrupt. For the limit OCR2A the interrupt is "TIMER2_COMPA_vect" and for "OCR2B" the interrupt functions is "TIMER2_COMPB_vect". But what happens when the interrupt is executed? Well it will just pull down the digital pins and end the PW for the servo, and everything will start over again:

    ISR(TIMER2_COMPA_vect ) //Interrupt of timer 2 compare A
    {
    PORTB &= 0xFE;//Pulling the Digital pin 8 (PB0)down. 0xFE is the NOT of 0x01.
    }

    Now the interrupt for Timer2 Compare B:

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

    And that's alll!!! Is the best way i was able to do it =). I can't use a smaller prescale because the counter will overflow.

    Regards!
  • 3D Robotics
    Just to add to Jordi's comment, you need to add a wire under the board for Chan 3 and 4. See the manual ("Preparing the hardware") for an example
  • Developer
    Hello Curtis,

    Bad and good news:

    The bad news is that you only have 1 pin remaining. The fact of read the two more channel may slow down the system. I should use external interrupts or something to read the pulse width but i don't have enough timers. So you can only read an extra channel using the pulseIn function.

    The good news is that you can control the 4th channel BUT! the channel 3 and 4 are like "noisy" if you connect a servo over there you will see how it has tiny, tiny glitches. I'm in another laptop i can see code but if you look look into the servo tab, and check the servo initialize function some of the stuff is disabled using the comments lines "//", well is you uncomment it you will enable the channel 4 in the pin you select over there. Try to fallow the comments.

    Would be nice if there's any software where i can put all the code easily in the post and i can highlight it etc. To explain better.

    Good Luck (in the good way)! =)
This reply was deleted.

Activity

Neville Rodrigues liked Neville Rodrigues's profile
Jun 30
Santiago Perez liked Santiago Perez's profile
Jun 21
More…