@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)