J’ai réalisé la partie assemblage d’un robot quadrupède. Chaque « jambe » est contrôlée par 3 servos. Il me faut donc une solution pour contrôler indépendamment 12 servos.
Chaque servo monopolise un pin de la carte Arduino pour être contrôlé via un signal PWM. J’avais expliqué ce montage dans l’article https://randomcraftr.com/?p=1497.
Pour contrôler 12 servos, 12 pins sont nécessaires. Cela laisse peu de place pour connecter au robot un autre équipement : LEDs, actuateur ou senseur. Je décide donc de dédier un arduino complet juste pour la génération des signaux PWMs. Il faut connecter cet arduino à une seconde carte arduino qui le contrôlera. Je choisis pour cela le protocole I2C: il ne nécessite que deux fils pour communiquer avec un composant qui utilise le même protocole.
Il faut donc:
- Programmer une carte Arduino « maître » qui enverra les consignes de positions pour les 12 servos via le protocole I2C.
- Programmer une carte Arduino « esclave » qui traduira les consignes de positions reçues via le protocole I2C en 12 signaux PWM indépendants pour les 12 servos.
Voici le schéma de montage avec le code préchargé pour simuler le comportement sur 3 servos.
Et je reproduis le code de l’Arduino maître:
#include <Wire.h>
void setup()
{
Wire.begin(1); // join i2c bus (address optional for master)
}
void loop()
{
for (int position=0;position<=180;position+=10){
Wire.beginTransmission(2); // Init transmission to device #2
for (int idx_servo=0;idx_servo<12;idx_servo++){
Wire.write(idx_servo); // Set first integer value on I2C bus as servo id
Wire.write(position); // Set second integer value on I2C bus as servo position
}
Wire.endTransmission(); // Flush I2C bus to trigger slave action on information
delay(2000); // Wait before next position change
}
}
Ainsi que celui de l’Arduino esclave:
#include <Wire.h>
#include <Servo.h> // Include Servo library
Servo servo_array[12]; // Instanciate Servo object array
int servo_position[12]; // Instanciate Servo position array
void setup()
{
Wire.begin(2); // Join i2c bus with address #2
Wire.onReceive(receiveEvent); // Register event to trigger when I2C communicates
Serial.begin(9600);
for(int servo_idx=0;servo_idx <12;servo_idx++)
{
Serial.print("Init servo ");
Serial.println(servo_idx);
// Attach 12 servos on pin 3-13
servo_array[servo_idx].attach(servo_idx+2);
// Attach set all position values to 0
servo_position[servo_idx] = 0;
}
}
void loop()
{
delay(100);
}
// Event to trigger when data is received on I2C bus
void receiveEvent(int howMany)
{
Serial.println("Receiving ... ");
while(2 <= Wire.available()) // Capture two data at once
{
int servo_id = Wire.read(); // First integer is known as servo id
int servo_pos = Wire.read(); // Second integer is known as servo position
Serial.print("Send servo ");
Serial.print(servo_id);
Serial.print(" position ");
Serial.println(servo_pos);
servo_array[servo_id].write(servo_pos); // Set position to servo
}
}
Une fois ce principe de fonctionnement établi, on peut porter la partie esclave sur un ATMEGA hors de la carte Arduino, et brancher ainsi toutes les pattes du robot.
Le schéma sous une forme moins interactive:



