Projet Kapduino : Piloter les servos

Les radios commandes, déclencheurs divers et variés. Les circuits électroniques et autres bidouillages.

Projet Kapduino : Piloter les servos

Messagede Deltakap le Sam 05 Septembre 2009, 16:27

J'ai commencé mon histoire ici viewtopic.php?f=6&t=423&start=140#p14974, mais ce n'est pas forcement une très bonne idée.... alors je reprends là ;)

Donc, comment piloter un servo de panoramique modifié 360°, c'est à dire avec le potentiomètre de position désaccouplé et la butée de rotation supprimée ?

En fait, On a juste besoin de le faire tourner dans les deux sens et de l'arreter, facile en principe... sauf que ce servo n'a plus de position d'équilibre ce qui ne facilite pas son arrêt total.
On sait juste que pour l'arreter, il va falloir lui envoyer une impulsion proche de 1,5ms ou 1500us (si le potentiomètre ou l'ajustable qui le remplace est bien réglé) et que pour le faire tourner, il va falloir jouer sur la durée de cette impulsion.
PS: sur un servo monté directement sur le Picavet ou le pendule, sans engrenages supplémentaires, cette variation de durée va être de l'ordre de 10us pour le faire tourner suffisamment lentement !!!

On va donc avoir des paramètres très sensibles qui vont dépendre du montage de la nacelle. Une bonne idée à ce niveau serait, à mon avis, de rendre ces paramètres indépendants du programme (pour garder un programme standard utilisable tel quel par tous) et de passer par une phase de réglages permettant à chacun de stocker ses propres paramètres sans avoir à modifier des variables dans le code.

Ces microcontroleurs disposent d'une mémoire dite EEPROM qui stocke les valeurs écrites même si on éteind l'Arduino... ça parait un excellent endroit pour y stocker ces paramètres ;)

Voilà comment je vois le truc pour l'instant: Créer un ou plusieurs sketches de réglage en utilisant les possibilités de dialogue entre le PC et l'Arduino via le port COM (USB) pour ajuster les différents paramètres et les stocker en mémoire EEPROM.
Pour le servo de PAN, il faut déterminer (et ça va dépendre de chaque nacelle):
- la durée de l'impulsion qui arrete au mieux le servo
- la variation de durée qui va permettre de le faire tourner (en réglant en fait sa vitesse de rotation)
- la durée necessaire pour faire un tour complet (qui dépend de la vitesse ci-dessus)
C'est le minimum pour faire tourner un AutoKap !


Le dialogue PC/Arduino

Pour programmer l'Arduino, nous disposons d'une liaison USB (en fait une émulation de port série)
On peut donc utiliser des programmes classiques de communication sur port série. Le programme Arduino sur le PC dispose d'un bouton "serial monitor" qui permet de voir ce qui transite sur ce port et de "dialoguer" avec l'Arduino. Hyperterminal est programme windows très pratique (plus pratique?) pour "dialoguer" sur ce port (il n'est plus fourni avec Vista, mais se trouve facilement sur le Net).
Quelque soit le programme, il faut couper momentanement cette liaison pour uploader un nouveau sketch sur l'Arduino.

Voilà en tout cas une méthode séduisante pour définir ses propres paramètres ;)
Dernière édition par Deltakap le Lun 07 Septembre 2009, 17:04, édité 1 fois.
Avatar de l’utilisateur
Deltakap
Plus de 1000 messages
 
Messages: 1432
Inscription: Lun 22 Septembre 2008, 11:35
Localisation: Du coté de Granville

Re: Projet Kapduino : Piloter le servo de PAN

Messagede Deltakap le Sam 05 Septembre 2009, 16:56

1ère étape: arrêter le servo de PAN:

Code: Tout sélectionner
// réglage arrêt du servo Panoramique

#include <Servo.h>
#include <EEPROM.h>

#define PAN_PIN  2
#define PAN_IDLE  1500 //us

Servo pan_servo;


int inByte = 0;         // incoming serial byte
int idle_value;

void setup() {
  idle_value = EEPROMReadInt(0);
  if (idle_value < 1400 || idle_value >1600) idle_value = PAN_IDLE;

  pan_servo.attach(PAN_PIN);

  Serial.begin(9600);
  Serial.println();
  Serial.print("Actual pan_idle value: ");
  Serial.println(idle_value);
}

void loop() {
//réglage
  if (Serial.available() > 0) {
    inByte = Serial.read()-48; // get incoming byte:

    switch (inByte){
      case 1:
        idle_value++;
        pan_servo.write(idle_value);
        Serial.println(idle_value);
        break;
      case 2:
        idle_value--;
        pan_servo.write(idle_value);
        Serial.println(idle_value);
        break;
      case 3: // store pan_idle in EEPROM (address 0 & 1)
        EEPROMWriteInt(0, idle_value);
        Serial.print("pan_idle value ");
        Serial.print(idle_value);
        Serial.println(" stored at the eeprom address 0");
        break;
      case 4: // read pan_idle from EEPROM (address 0 & 1)
        Serial.print("pan_idle value at the eeprom address 0: ");
        Serial.println(EEPROMReadInt(0), DEC);
        break;
    }
   
  }
}

//from http://blog.ncode.ca/wp-content/uploads/2008/08/eeprom-int-readwrite.pde
void EEPROMWriteInt(int p_address, int p_value)
   {
   byte lowByte = ((p_value >> 0) & 0xFF);
   byte highByte = ((p_value >> 8) & 0xFF);

   EEPROM.write(p_address, lowByte);
   EEPROM.write(p_address + 1, highByte);
   }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
   {
   byte lowByte = EEPROM.read(p_address);
   byte highByte = EEPROM.read(p_address + 1);

     return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
   }


Avec hyperterminal ouvert et connecté, en appuyant sur 1 ou 2 sur le clavier du PC, on règle la valeur qui arrete le servo et quand c'est fait, on appuie sur la touche 3 pour stocker la valeur dans l'Arduino... plus besoin de toucher à "#define PAN_IDLE 1500 //us". La touche 4 permet de lire la valeur stockée.

Cette valeur est maintenant stockée dans l'Arduino et pourra être utilisée dans les sketches suivants... et accessoirement de pouvoir la modifier sur le terrain depuis la future télécommande sans trimballer le PC !
Avatar de l’utilisateur
Deltakap
Plus de 1000 messages
 
Messages: 1432
Inscription: Lun 22 Septembre 2008, 11:35
Localisation: Du coté de Granville

Re: Projet Kapduino : Piloter le servo de PAN

Messagede Deltakap le Sam 05 Septembre 2009, 17:00

2ème étape: régler la vitesse du servo avec cet autre sketch:

Code: Tout sélectionner
// réglage vitesse du servo Panoramique

#include <Servo.h>
#include <EEPROM.h>

#define PAN_PIN 9
#define PAN_IDLE  1500 //us
#define PAN_SPEED 20 //us

Servo pan_servo;


int inByte = 0;         // incoming serial byte
int idle_value;
int speed_value;

void setup() {
  idle_value = EEPROMReadInt(0);
  if (idle_value < 1400 || idle_value >1600) idle_value = PAN_IDLE;
  speed_value = EEPROMReadInt(2);
  if (speed_value >1000) speed_value = PAN_SPEED;

  pan_servo.attach(PAN_PIN);
  pan_servo.write(idle_value + speed_value);
  Serial.begin(9600);
  Serial.println();
  Serial.print("Actual pan_idle value: ");
  Serial.println(idle_value);
  Serial.print("Actual pan_speed value: ");
  Serial.println(speed_value);
}

void loop() {
//réglage
  if (Serial.available() > 0) {
    inByte = Serial.read()-48; // get incoming byte:
 
    switch (inByte){
      case 1: // read pan_idle from EEPROM (address 0 & 1)
        speed_value--;
        if (speed_value<=0) speed_value=0;
        pan_servo.write(idle_value + speed_value);
        Serial.println(speed_value);
        break;
      case 2: // read pan_idle from EEPROM (address 0 & 1)
        speed_value++;
        if (speed_value>1000) speed_value=1000;
        pan_servo.write(idle_value + speed_value);
        Serial.println(speed_value);
        break;
      case 3: // read pan_speed from EEPROM (address 2 & 3)
        EEPROMWriteInt(2, speed_value);
        Serial.print("pan_speed value ");
        Serial.print(speed_value);
        Serial.println(" stored at the eeprom address 2");
        break;
      case 4: // read pan_idle from EEPROM (address 0 & 1)
        Serial.print("pan_idle value at the eeprom address 0: ");
        Serial.println(EEPROMReadInt(0), DEC);
        Serial.print("pan_speed value at the eeprom address 2: ");
        Serial.println(EEPROMReadInt(2), DEC);
        break;
    }
   
  }
}

//from http://blog.ncode.ca/wp-content/uploads/2008/08/eeprom-int-readwrite.pde
void EEPROMWriteInt(int p_address, int p_value)
   {
   byte lowByte = ((p_value >> 0) & 0xFF);
   byte highByte = ((p_value >> 8) & 0xFF);

   EEPROM.write(p_address, lowByte);
   EEPROM.write(p_address + 1, highByte);
   }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
   {
   byte lowByte = EEPROM.read(p_address);
   byte highByte = EEPROM.read(p_address + 1);

     return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
   }



En appuyant sur 1 ou 2, on règle la vitesse du rotation du servo, puis on appuie sur la touche 3 pour stocker la valeur dans l'EEPROM de l'Arduino. La touche 4 permet de lire la valeur stockée.
Avatar de l’utilisateur
Deltakap
Plus de 1000 messages
 
Messages: 1432
Inscription: Lun 22 Septembre 2008, 11:35
Localisation: Du coté de Granville

Re: Projet Kapduino : Piloter le servo de PAN

Messagede Deltakap le Sam 05 Septembre 2009, 17:03

3ème étape et un nouveau sketch pour régler cette fois la durée de rotation pour 1 tour:

Code: Tout sélectionner
// réglage durée pour 1 tour du servo Panoramique

#include <Servo.h>
#include <EEPROM.h>

#define PAN_PIN 9
#define PAN_IDLE  1500 //us
#define PAN_SPEED 20 //us

#define START 1
#define STOP 2


Servo pan_servo;

int inByte = 0;         // incoming serial byte
int idle_value;
int speed_value;
int one_turn_time=0;

void setup() {
  init_pan_servo();
  Serial.begin(9600);
}

void loop() {
//réglage
  if (Serial.available() > 0) {
    inByte = Serial.read()-48; // get incoming byte:
 
    switch (inByte){
      case START:
        pan_servo.write(idle_value + speed_value);
        one_turn_time = millis();     
        break;
      case STOP:
        pan_servo.write(idle_value);
        one_turn_time = (millis()-one_turn_time)/100; // en 100ème de secondes
        EEPROMWriteInt(4, one_turn_time);
        Serial.println(one_turn_time);
        break;
    }
  }
}

void init_pan_servo(){
  idle_value = EEPROMReadInt(0);
  if (idle_value < 1400 || idle_value >1600) idle_value = PAN_IDLE;
  speed_value = EEPROMReadInt(2);
  if (speed_value >1000) speed_value = PAN_SPEED;
  pan_servo.attach(PAN_PIN);
  pan_servo.write(idle_value);

//from http://blog.ncode.ca/wp-content/uploads/2008/08/eeprom-int-readwrite.pde
void EEPROMWriteInt(int p_address, int p_value)
   {
   byte lowByte = ((p_value >> 0) & 0xFF);
   byte highByte = ((p_value >> 8) & 0xFF);

   EEPROM.write(p_address, lowByte);
   EEPROM.write(p_address + 1, highByte);
   }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
   {
   byte lowByte = EEPROM.read(p_address);
   byte highByte = EEPROM.read(p_address + 1);

     return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
   }



On prend un repère, on appuie sur 1 pour lancer la rotation. Quand le servo a fait un tour complet, on appuie sur 2. La valeur est stockée dans l'EEPROM
Avatar de l’utilisateur
Deltakap
Plus de 1000 messages
 
Messages: 1432
Inscription: Lun 22 Septembre 2008, 11:35
Localisation: Du coté de Granville

Re: Projet Kapduino : Piloter le servo de PAN

Messagede Deltakap le Sam 05 Septembre 2009, 17:07

4ème étape: un AutoKap (enfin bon, que la rotation du servo de PAN pour l'instant)

Code: Tout sélectionner
// Autokap

#include <Servo.h>
#include <EEPROM.h>

#define PAN_PIN 9 // le servo est connecté sur la pin 9 de l'Arduino
#define PAN_IDLE  1500 //us, valeur par défaut si la valeur de l'EEPROM n'est pas correcte
#define PAN_SPEED 20 //us, valeur par défaut si la valeur de l'EEPROM n'est pas correcte
#define ONE_TURN_TIME 20 //sec, valeur par défaut si la valeur de l'EEPROM n'est pas correcte

#define SHOOTS_PER_TURN 12 // nb de photos par tour, à ajuster éventuellement


Servo pan_servo;

int inByte = 0;         // incoming serial byte
int idle_value;
int speed_value;
int turn_time=0;

void setup() {
  init_pan_servo();
  init_turn_time();
}

void loop() {
  pan_servo.write(idle_value + speed_value);
  delay(100*turn_time/SHOOTS_PER_TURN);
  pan_servo.write(idle_value);
 
  delay(5000);// attend 5 sec que la nacelle se stabilise
  shoot();// à définir
  delay(5000);// attend 5 sec pendant que l'APN shoote
}





void init_pan_servo(){
  idle_value = EEPROMReadInt(0);
  if (idle_value < 1400 || idle_value >1600) idle_value = PAN_IDLE;
  speed_value = EEPROMReadInt(2);
  if (speed_value >1000) speed_value = PAN_SPEED;
  pan_servo.attach(PAN_PIN);
  pan_servo.write(idle_value);
}

void init_turn_time(){
  turn_time = EEPROMReadInt(4);
  if (turn_time < 100 || turn_time > 10000) turn_time = ONE_TURN_TIME;
}

void shoot(){}//à compléter !

//from http://blog.ncode.ca/wp-content/uploads/2008/08/eeprom-int-readwrite.pde
void EEPROMWriteInt(int p_address, int p_value)
   {
   byte lowByte = ((p_value >> 0) & 0xFF);
   byte highByte = ((p_value >> 8) & 0xFF);

   EEPROM.write(p_address, lowByte);
   EEPROM.write(p_address + 1, highByte);
   }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
   {
   byte lowByte = EEPROM.read(p_address);
   byte highByte = EEPROM.read(p_address + 1);

     return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
   }


Bon, bin voilà une façon de faire :)
Ce dernier programme peut être utilisé sans modification (hormis éventuellement la constante SHOOTS_PER_TURN) sur n'importe quelle nacelle (360°) réglée avec les sketches précédents.
Les sketches suivants pourront utiliser également les réglages très particuliers de ce servo de PAN. C'était ça l'idée ;)

A noter que toute cette phase de réglages pourrait être évitée et se faire dynamiquement et automatiquement si on avait un capteur (même relatif) de position sur le PAN... je pense par exemple à la roue codeuse d'une souris (sauf que je vois pas pour l'instant comment monter quelque chose de propre et de solide).
Ca permettrait aussi de refaire ce réglage automatique en vol (si les batteries faiblissent et si ça dérive)
Avatar de l’utilisateur
Deltakap
Plus de 1000 messages
 
Messages: 1432
Inscription: Lun 22 Septembre 2008, 11:35
Localisation: Du coté de Granville


Retourner vers L'électronique embarquée et au sol

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 2 invités