Hello everyone!

Currently I'm working on a project that will attempt to use additional control surfaces to induce stresses in the wings of an aircraft that some of my colleagues are developing.  At the moment I'm using an Arduino Nano as a prototype - I want it to have six inputs (from the rx) and eight outputs (four extra control surfaces).  I would use the Ardupilot for this project, but we need 8 inputs and 14 outputs in the final device, so I decided to use an Arduino Mega 2560 board (it's in the mail right now, so I'm using the Nano until then).

Anyway, I'm trying to understand how the Ardupilot servo outputs are written, because I'm not having much luck with my code on the Nano.  I've made use of the Arduino servo library, as well as the function pulseIn() to save having to develop those functions from scratch, but as soon as I add more than one servo to the code, it seems that the processor is unable to keep up with outputting two PWM signals at once.  For example, my code currently looks like this:

// Required header files
#include <Servo.h>

// Input pins
#define inPWM1 0

// Output pins
#define outServoPin1 4
#define outServoPin2 5

// Other Magic Numbers
#define SERVO_MIDPOINT 1500

// Create servo control objects
Servo outServo1;
Servo outServo2;

void setup()
{
    // Configure inputs
    pinMode(inPWM1, INPUT);

    // Configure outputs
    outServo1.attach(outServoPin1);
    outServo2.attach(outServoPin2);
}

void loop()
{
    // Direct pass through to outputs
    outServo1.writeMicroseconds(pulseIn(inPWM1, HIGH));
    outServo2.writeMicroseconds(pulseIn(inPWM1, HIGH));
}

When I cause the servos to move moderately quickly, they freeze up or lag.  When I remove the line of code for outServo2, Servo1 then responds immediately.  If I add code for even more servos (say, eight), then they barely respond at all.

I've glanced over the cpp files for both the servo library and the relevant portions of code in the Ardupilot libraries - they appear to make similar use of interrupts and timers to read and write the pwm signals, so can somebody tell me what magic there is in the Ardupilot that makes it capable of smoothly controlling all those servos at once?

Or is it that the clock speed of the Ardupilot is just a lot faster than the 16Mhz of the Arduinos?

Thanks for reading and answering!

Views: 1036

Replies to This Discussion

Lewis,

    The APM_RC library is the one that we use in ArduPilot/ArduCopter to read/write pwm values used by the servos.  It uses low level avr hardware calls (although i suspect the servo lib you're using does as well) which makes it fast.  When you update a pwm value that you want sent out to the servos, our code only needs to update one register in the avr.  The rest is all handled by the hardware.  So I guess your question is why is that servo lib so slow...I'm not sure but we've certainly seen other situations where the arduino libraries are not optimised for speed because, in the beginning at least, people tend to use them for simple things so they're optimised for ease of use and simplicity instead of speed.

     I don't think it's because of the relative speed of the nano vs the 2560.

     Ah...my guess is that it's actually the pulse in that is slow in your code.  I'll bet that it's waiting for the next pulse...if you replace that with a single call to pulseIn and save it to a variable and then use that value to output to both servos i'll bet it speeds up.

Randy,

Thanks for the tips.  I tried what you said, and it's marginally better, but still not ideal... I think that the servo library is also no speed-optimized.  Even if it were, it doesn't help in the long run.  Assuming no speed issues, I was going to write the code something like this:

// Required header files
#include <Servo.h>

// Define input pins
#define inPWM1 0
#define inPWM2 1
#define inPWM3 2
#define inPWM4 3

// Define output pins
#define outServoPin1 4
#define outServoPin2 5
#define outServoPin3 6
#define outServoPin4 7
#define outServoPin5 8
#define outServoPin6 9
#define outServoPin7 10
#define outServoPin8 11

// Magic Numbers
#define SERVO_MIDPOINT 1500

// Create servo control objects
Servo outServo1;
Servo outServo2;
Servo outServo3;
Servo outServo4;
Servo outServo5;
Servo outServo6;
Servo outServo7;
Servo outServo8;

void setup()
{
    // Configure inputs
    pinMode(inPWM1, INPUT);
    pinMode(inPWM2, INPUT);
    pinMode(inPWM3, INPUT);
    pinMode(inPWM4, INPUT);

    // Configure outputs
    outServo1.attach(outServoPin1);
    outServo2.attach(outServoPin2);
    outServo3.attach(outServoPin3);
    outServo4.attach(outServoPin4);
    outServo5.attach(outServoPin5);
    outServo6.attach(outServoPin6);
    outServo7.attach(outServoPin7);
    outServo8.attach(outServoPin8);
}

void loop()
{
    // Get inputs from receiver/autopilot

    // Run algorithms to calculate outputs based on wing flex, airspeed, etc
    /*
    outPWM1 = ...
    outPWM2 = ...
    etc.
    */

    // Output synthesized pwm signals to servos
    outServo1.writeMicroseconds(outPWM1);
    outServo2.writeMicroseconds(outPWM2);
    outServo3.writeMicroseconds(outPWM3);
    outServo4.writeMicroseconds(outPWM4);
    outServo5.writeMicroseconds(outPWM5);
    outServo6.writeMicroseconds(outPWM6);
    outServo7.writeMicroseconds(outPWM7);
    outServo8.writeMicroseconds(outPWM8);
}

/*
Some algorithms and functions would be here
*/

But if I use pulseIn, plus inputs from strain gauges and airspeed and who knows what else, the processor is not going to happily process all that info and output all those signals.  Not to mention that the final product will have 14 outputs.  Yet the Ardupilot seems to be able to do it.  If I load the APM2 (or APM1) code onto an Aruino Mega 2560 board, will that be a good place to start?

Thanks again!

Lewis,

     You might want to try looking at the APM_RC library instead.  It's got some example sketches that might be helpful.  The thing is that there are quite a few differences between the standard Arduino Mega board and the APM1 or APM2...so the sketches might not even work...:-(.

I think that's my best bet for now.  I'll take a look at modifying them for the Nano/Mega and see what I can come up with.

Thanks!

RSS

Social Networking

Contests

Season Two of the Trust Time Trial (T3) Contest has now begun. The fourth round is an accuracy round for multicopters, which requires contestants to fly a cube. The deadline is April 14th.

A list of all T3 contests is here

Groups

Advertisement

© 2013   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service