Hi Ghost_Rider,
Yes the Mega is capable of controlling 12 servos.
If you don't mind using up all the 16-bit timers, then it's possible to control 12 servos using hardware PWM. Using hardware PWM offers the benefit of 14-bit resolution at 50Hz and the fact that the timers require no intervention from the CPU, apart from loading the duty-cycle (OCRxx) register for each output.
The code below uses the Mega's 16-bit timers: 1, 3, 4 & 5, each with 3 outputs: A, B and C. The setup() portion of the code sets the timers up in phase and frequency correct mode, with an output frequency of 50Hz.
The loop() portion just centers each servo, then moves them to lower and higher positions. To move the servos just load the appropriate pOCRxxReg[] array with a value similar to the servo.writeMicroseconds() function: 1500 = center, 1000 = minimum, 2000 maximum:
// On the Arduino Mega there are 4 16 bit timers: 1, 3, 4 & 5, each with three outputs: A, B & C
// Store the addresses of the PWM timer compare (duty-cycle) registers
volatile uint16_t* pOCRxxReg[] = { &OCR1A, &OCR1B, &OCR1C, &OCR3A, &OCR3B, &OCR3C, &OCR4A, &OCR4B, &OCR4C, &OCR5A, &OCR5B, &OCR5C };
void setup() {
// Set PWM pins as outputs
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(46, OUTPUT);
pinMode(45, OUTPUT);
pinMode(44, OUTPUT);
// Initialise timers 1, 3, 4 and 5 for phase and frequency correct PWM
TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1C1); // Enable the PWM outputs OC1A, OC1B and OC1C on digital pins 11, 12 and 13
TCCR1B = _BV(WGM13) | _BV(CS11); // Set phase and frequency correct PWM and prescaler of 8 on timer 1
TCCR3A = _BV(COM3A1) | _BV(COM3B1) | _BV(COM3C1); // Enable the PWM output OC3A, OC3B and OC3C on digital pins 5, 2 and 3
TCCR3B = _BV(WGM33) | _BV(CS31); // Set phase and frequency correct PWM and prescaler of 8 on timer 3
TCCR4A = _BV(COM4A1) | _BV(COM4B1) | _BV(COM4C1); // Enable the PWM outputs OC4A, OC4B and OC4C on digital pins 6, 7 and 8
TCCR4B = _BV(WGM43) | _BV(CS41); // Set phase and frequency correct PWM and prescaler of 8 on timer 4
TCCR5A = _BV(COM5A1) | _BV(COM5B1) | _BV(COM5C1); // Enable the PWM outputs OC5A, OC5B and OC5C on digital pins 46, 45 and 44
TCCR5B = _BV(WGM53) | _BV(CS51); // Set phase and frequency correct PWM and prescaler of 8 on timer 5
ICR1 = 20000; // Set the timer 1 frequency to 50Hz
ICR3 = 20000; // Set the timer 3 frequency to 50Hz
ICR4 = 20000; // Set the timer 4 frequency to 50Hz
ICR5 = 20000; // Set the timer 5 frequency to 50Hz
}
void loop() {
for (uint8_t i = 0; i < 12; i++) // Iterate through the 12 servos
{
*(pOCRxxReg[i]) = 1500; // Centre the specified servo
delay(500); // Wait half a second
}
for (uint8_t i = 0; i < 12; i++) // Iterate through the 12 servos
{
*(pOCRxxReg[i]) = 1200; // Move the specified servo to a lower position
delay(500); // Wait half a second
}
for (uint8_t i = 0; i < 12; i++) // Iterate through the 12 servos
{
*(pOCRxxReg[i]) = 1800; // Move the specified servo to a higher position
delay(500); // Wait half a second
}
}