@Patrick : pour le trie, sur la version "naive", ça vaut le coup. Pour la V2, je suis pas sur si c'est encore le cas.
@Patrick : ton second message, j'ai pas compris, en particulier "et sur It."
Sinon, voici la V2, qui devrait être utilisable :
//équivalences pin/port
// 2 PD2
// 3 PD3
// 4 PD4
// 5 PD5
// 6 PD6
// 7 PD7
// 8 PB0
// 9 PB1
//octets avec un 0 à l'endroit correspondant à un pin dans les registres et 1 ailleurs
#define ZERO_DU_PIN_2 B11111011
#define ZERO_DU_PIN_3 B11110111
#define ZERO_DU_PIN_4 B11101111
#define ZERO_DU_PIN_5 B11011111
#define ZERO_DU_PIN_6 B10111111
#define ZERO_DU_PIN_7 B01111111
#define ZERO_DU_PIN_8 B11111110
#define ZERO_DU_PIN_9 B11111101
//nom du pot correspondant à chaque pin
#define PORT_DE_PIN_2 PORTD
#define PORT_DE_PIN_3 PORTD
#define PORT_DE_PIN_4 PORTD
#define PORT_DE_PIN_5 PORTD
#define PORT_DE_PIN_6 PORTD
#define PORT_DE_PIN_7 PORTD
#define PORT_DE_PIN_8 PORTB
#define PORT_DE_PIN_9 PORTB
#define PERIODE_US 20000 //période
uint16_t duree_pulse_us[10]={0,0,1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700}; //position initiale
uint16_t duree_pulse_us_min[10]={0,0,1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000};
uint16_t duree_pulse_us_max[10]={0,0,2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000};
int angle_min[10]={0,0,0, 0, 0, 0, 0, 0, 0, 0};
int angle_max[10]={0,0,180, 180, 180, 180, 180, 180, 180, 180};
void envoyer_pulse()
{
unsigned long start_time=micros();
//mise à 1 de tous les pins
PORTD |= B11111100; //mise à 1 des pins 2 à 7 du port D (ie pins 2 à 7 de l'arduino)
PORTB |= B00000011; //mise à 1 des pins 0à 1 du port B (ie pins 8 et 9 de l'arduino)
while( (PORTD & 0B11111100) | (PORTB & 0B00000011) ) //tant qu'au moins un des pins est à 1
{
unsigned long duree_actuelle_du_pulse=micros()-start_time; //durée écoulée depuis le début du pulse
if(duree_actuelle_du_pulse>=duree_pulse_us[2])
PORT_DE_PIN_2 &= ZERO_DU_PIN_2;
if(duree_actuelle_du_pulse>=duree_pulse_us[3])
PORT_DE_PIN_3 &= ZERO_DU_PIN_3;
if(duree_actuelle_du_pulse>=duree_pulse_us[4])
PORT_DE_PIN_4 &= ZERO_DU_PIN_4;
if(duree_actuelle_du_pulse>=duree_pulse_us[5])
PORT_DE_PIN_5 &= ZERO_DU_PIN_5;
if(duree_actuelle_du_pulse>=duree_pulse_us[6])
PORT_DE_PIN_6 &= ZERO_DU_PIN_6;
if(duree_actuelle_du_pulse>=duree_pulse_us[7])
PORT_DE_PIN_7 &= ZERO_DU_PIN_7;
if(duree_actuelle_du_pulse>=duree_pulse_us[8])
PORT_DE_PIN_8 &= ZERO_DU_PIN_8;
if(duree_actuelle_du_pulse>=duree_pulse_us[9])
PORT_DE_PIN_8 &= ZERO_DU_PIN_9;
}
}
void set_position_degrees(byte pin, int angle_deg)
{
uint16_t duree_us=map(angle_deg, angle_min[pin], angle_max[pin], duree_pulse_us_min[pin], duree_pulse_us_max[pin]);
duree_pulse_us[pin]=duree_us;
}
void setup() {
Serial.begin(115200);
for(int i=2;i<=9;i++)
{
pinMode(i,OUTPUT);
}
Serial.println("Hello");
}
int c=0;
void loop() {
c++;
unsigned long start_time=micros();
envoyer_pulse();
unsigned long duration=micros()-start_time;
Serial.println(duration);
/*//faire ici les calculs pour la nouvelle position des servos (position en µs de pulse, pas en degrés)
duree_pulse_us[2]=1500+((c/100)%2)*300;
duree_pulse_us[3]=1500+((c/100)%2)*300;
duree_pulse_us[4]=1500+((c/100)%2)*300;
duree_pulse_us[5]=1500+((c/100)%2)*300;
duree_pulse_us[6]=1500+((c/100)%2)*300;
duree_pulse_us[7]=1500+((c/100)%2)*300;
duree_pulse_us[8]=1500+((c/100)%2)*300;
duree_pulse_us[9]=1500;*/
//variante
set_position_degrees(2,0);
set_position_degrees(3,20);
set_position_degrees(4,40);
set_position_degrees(5,60);
set_position_degrees(6,90);
set_position_degrees(7,120);
set_position_degrees(8,160);
set_position_degrees(9,180);
//attendre la fin de la période
while(micros()-start_time<PERIODE_US)
{
//ne rien faire
}
}
Nouvautés :
1) le code est beaucoup plus optimisé : l'écart entre le traitement du premier et du dernier servo est de 7*11 cycles d'horloges (11 cycles par servo), soit 4.8µs, ce qui correspond à 0.8°. La fluctuation est encore bien plus faible (1 cycle d'horloge par servo ayant fini son pulse), soit au maximum 7 cycles d'horloges de fluctuation, soit 0.43ms, soit 0.08°
La plus forte cause de fluctuation est donc la fonction micros, qui a une résolution de 4µs, soit 0.7° de fluctuation sur les angles des servos.
En pratique, on ne remarque pas les fluctuations à l'oeil nu
2) renumérotation des servos : maintenant chaque servo correspon au pin (il y a donc 2 emplacements "vides" dans les tableaux, correspondant aux pins 0 et 1 qui ne sont pas utilisés)
3) il y a maintenant une fonction pour donner la consigne en degrés (il y a des tableaux en début du programme pour ajuster les intervales d'angles et les durées en µs correspondantes : ça peut servir pour corriger les offsets des moteurs, ainsi que pour définir une plage angulaire de notre choix (par exemple -90° à +90°). NB : il n'y a aucune sécurité pour les valeurs hors intervalle.
@Oracid, je penses que tu peux commencer à intégrer ton code sur cette base si tu en as envie
EDIT : sur mon servo de test, je peux mettre PERIODE_US aussi petit que je veux, ça a l'air de toujours marcher correctement (nb : il faut quand même laisser PERIODE_US assez grand pour pouvoir réaliser la période souhaitée, sinon la période n'est plus respectée (mais mon servo conserve quand même la position)