Probleme envoi commande en bluetooth

bonjour a tous.
Ceci est mon premier post sur un forum, excusez moi d'avance si tout n'est pas clair.
j'envoi par Bluetooth une commande a mon robot, mon problème est que selon le temps d'appui sur le bouton ma commander mon mouvement est jouer plusieurs fois alors que je veux la jouer une seul fois .je pense que le temps d'appui enregistre dans le buffer plusieurs fois ma commande.
avez vous une solution je vous remercie par avance.


#include <RC100.h>

// **** Global Parameters for DXLs *********
#include <Dynamixel2Arduino.h>
#define DXL_SERIAL_1 Serial1  //Serial1 is for DXL port on OpenRB-150
//#define DEBUG_SERIAL Serial

// **** Global Parameters for DXLs *********
const uint8_t BROADCAST_ID = 254;
const uint8_t DXL_ID1 = 1;
const uint8_t DXL_ID2 = 2;
const uint8_t DXL_ID3 = 3;
const uint8_t DXL_ID4 = 4;
const uint8_t DXL_ID5 = 5;
const uint8_t DXL_ID6 = 6;
const uint8_t DXL_ID7 = 7;
const uint8_t DXL_ID8 = 8;
const uint8_t DXL_ID9 = 9;
const uint8_t DXL_ID10 = 10;
const uint8_t DXL_ID11 = 11;
const uint8_t DXL_ID12 = 12;
const uint8_t DXL_ID13 = 13;
const uint8_t DXL_ID14 = 14;
const uint8_t DXL_ID15 = 15;
const uint8_t DXL_ID16 = 16;

Dynamixel2Arduino dxl_mini(DXL_SERIAL_1);

// Number of DXLs used in robot
const float DXL_PROTOCOL_VERSION = 2.0;
const uint8_t GP_DXL_CNT = 16;                                                                         // nombre de DXL utilisés en mode Contrôle de position
const uint8_t GP_DXL_ID_LIST[GP_DXL_CNT] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };  //ID de servo définis en mode Contrôle de position
const uint16_t ADDR_X_PRESENT_POSITION = 37;                                                           // (XL-320)
const uint16_t LEN_X_PRESENT_POSITION = 2;                                                             //  (XL-320)
const uint16_t ADDR_X_GOAL_POSITION = 30;                                                              // (XL-320)
const uint16_t LEN_X_GOAL_POSITION = 2;                                                                // (XL-320)
const uint16_t ADDR_X_MOVING_SPEED = 32;                                                               // (XL-320)       adress 32 byt 2   0-2047
const uint16_t LEN_X_MOVING_SPEED = 2;                                                                 // (XL-320)
const uint16_t ADDR_X_TORQUE_ENABLE = 24;                                                              // (XL-320)    TORQUE_ENABLE     adress 24   0  off      1 on
const uint16_t LEN_X_TORQUE_ENABLE = 1;
const uint8_t CONTROL_MODE = 2;  //             for XL320  adress 11      byt 1  mode 2 =joint

uint16_t Current_Pose[GP_DXL_CNT] = { 0 };
//uint16_t Step = 10;//   Étape

// ********** RC100 settings *************
#include <RC100.h>
RC100 RC_2;  // Instalation de la télécommande via Serial2
uint16_t RcvData_2 = 0;
bool UP = false;
bool DOWN = false;
bool LEFT = false;
bool RIGHT = false;

// ********** End of Global Parameters Definition

//**** This namespace is required to use Control table item names
//using namespace ControlTableItem;

ParamForSyncWriteInst_t MS_sync_write_param;  // Parameters structure for MS packet
ParamForSyncWriteInst_t GP_sync_write_param;  // Parameters structure for SW GP packet
ParamForSyncReadInst_t GP_sync_read_param;    // Parameters structure for SR GP packet
RecvInfoFromStatusInst_t GP_read_result;      // Structure for results of SR PP command

uint8_t dxl_error = 0;                             // Dynamixel error
int32_t dxl_MOVING_SPEED[GP_DXL_CNT] = { 0 };      // Tableau de position vitesse
int32_t dxl_present_position[GP_DXL_CNT] = { 0 };  //  Tableau de position actuelle
int32_t dxl_goal_position[GP_DXL_CNT] = { 0 };     // Tableau de position d'objectif

bool read_present_positions_OK = false;

// Section MOUVEMENT
bool check_motion();
bool B_6 = false;  /////////////////////////////////////


/*void myDelay (unsigned long combien_de_temps)
  {
  unsigned long start = millis ();
  if (millis () - start <= combien_de_temps)//
    { }  
  } */

int GP_time = dxl_MOVING_SPEED[200];

int _STEP_TIME_0 = millis();
int STEP_TIME_1 = millis();

float pose_init[17] = { 390, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 };

float salut_main[6][17] = { { 50, -0.29, -150, -73.54, 72.36, -0.29, 0.59, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },  // 50  75  100   125 150   275
                            { 25, -0.29, -150, -73.54, 51.27, -0.29, -33.69, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 91.7, -0.29, 32.81, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 51.27, -0.29, -33.69, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 91.7, -0.29, 32.81, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 125, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 } };

float salut_2[6][17] = { {
                           25,
                           -22.27,
                           -44.24,
                           -73.24,
                           73.24,
                           0,
                           0,
                           0,
                           0,
                           -26.37,
                           26.07,
                           29.3,
                           -29.3,
                           13.18,
                           -13.48,
                           0,
                           0,
                         },  //25  75  150  275  350  400
                         { 50, -22.27, -44.24, -62.99, 92.58, -71.78, 58.59, 0, 0, -26.37, 26.07, 29.3, -29.3, 13.18, -13.48, 0, 0 },
                         { 75, -22.27, -69.73, -62.99, 92.58, -71.78, 58.59, 0, 0, -79.39, 82.91, 29.3, -29.3, -10.25, 10.55, 0, 0 },
                         { 125, -22.27, -69.73, -62.99, 92.58, -71.78, 58.59, 0, 0, -79.39, 82.91, 29.3, -29.3, -10.25, 10.55, 0, 0 },
                         { 75, -22.27, -44.24, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.07, 29.3, -29.3, 13.18, -13.48, 0, 0 },
                         { 50, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 } };

// ********** Function prototypes
//int GP_time = dxl_MOVING_SPEED[300]; //////////////////////////////////////
int CalcAngle2Raw(int angle) {
  return (int)(round((angle * 1023.0 / 300.0 + 512.0)));  // return (int)(round((angle * 1023.0 / 300.0 + 512.0)));XL 320
}  // fin de CalcAngle2Raw (angle int)

int i = 16;
int frame_no = 0;
int goal_position_raw = 0;

// Cet espace de noms est requis pour utiliser les noms d'éléments de la table de contrôle
using namespace ControlTableItem;

void setup() {
  int goal_position_raw = 0;  // raw     valeur brute de la position de l'objectif DXL
  Serial.begin(115200);
  while (!Serial)
    ;  // attendez que l'opérateur ouvre Serial Monitor

  // *****Configuration des Dynamixels pour mini ***

  dxl_mini.begin(1000000);  // débit en bauds du port DXL sur 1 Mbps pour XL320
  dxl_mini.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  dxl_mini.scan();
  Serial.println("Fin de la numérisation des DXL du robot ");

  // Préparation du paquet GP SW
  MS_sync_write_param.addr = ADDR_X_MOVING_SPEED;
  MS_sync_write_param.length = LEN_X_MOVING_SPEED;
  MS_sync_write_param.id_count = GP_DXL_CNT;
  for (int i = 0; i < GP_DXL_CNT; i++) {
    MS_sync_write_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet MS SW");

  // Préparation du paquet GP SR
  GP_sync_read_param.addr = ADDR_X_PRESENT_POSITION;  // Present Position of DYNAMIXEL-X series
  GP_sync_read_param.length = LEN_X_PRESENT_POSITION;
  GP_sync_read_param.id_count = GP_DXL_CNT;  // Number of servos in Position Control Mode
  for (int i = 0; i < GP_DXL_CNT; i++) {
    GP_sync_read_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet GP SR");

  // Préparation du paquet GP SW
  GP_sync_write_param.addr = ADDR_X_GOAL_POSITION;
  GP_sync_write_param.length = LEN_X_GOAL_POSITION;
  GP_sync_write_param.id_count = GP_DXL_CNT;
  for (int i = 0; i < GP_DXL_CNT; i++) {
    GP_sync_write_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet GP SW");

  // Configuration des servos GP dans la zone EEPROM : mode contrôle contrôle de position
  // et dans la zone RAM : vitesse  dxl  du profil
  for (int i = 0; i < GP_DXL_CNT; i++) {
    dxl_mini.torqueOff(GP_DXL_ID_LIST[i]);                               // Torque OFF
    dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 0);  // Définition des vitesses de déplacement initiales
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
    dxl_mini.torqueOn(GP_DXL_ID_LIST[i]);  // Torque ON
    delay(100);                            // attendez un peu avant de travailler dans la zone RAM
  }
  Serial.println("Fin de la configuration des servos GP");

  delay(1000);

  Serial.begin(115200);
  RC_2.begin(2);  // RC_2 utilisant Serial2 - Port UART 4 ​​broches - débit en bauds 57 600 bps dans RC100.cpp
  dxl_mini.begin(1000000);
  dxl_mini.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  for (int i = 0; i < GP_DXL_CNT; i++) {
    dxl_mini.ping(GP_DXL_ID_LIST[i]);
    dxl_mini.torqueOff(GP_DXL_ID_LIST[i]);
    //dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
    dxl_mini.torqueOn(GP_DXL_ID_LIST[i]);
    delay(100);  // attendez un peu avant de travailler dans la zone RAM
  }
  Serial.println("Mettre le robot dans la pose initiale");
  // Allouez la valeur brute de chaque position d'objectif dans le paquet GP SW, un DXL à la fois en utilisant les valeurs du tableau global _[1] à _[16]

  for (int i = 0; i < GP_DXL_CNT; i++)  // DXL 1 à 16
  {
    _STEP_TIME_0 = (int)(round(pose_init[0]));  //c'est-à-dire STEP TIME 0 = millis   ///////////////////////////////////////
    //  Réglez le robot sur la pose _ via SyncWrite
    goal_position_raw = CalcAngle2Raw(pose_init[i + 1]);  // convertir l'angle de mouvement en position d'objectif brute [0-1023], _[0] n'est pas utilisé ici
    memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
    dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
  }
  dxl_mini.syncWrite(GP_sync_write_param);  // send GP SW Packet
  delay(1000);
  Serial.println("Fin de la configuration pose init");
}

void loop() {
  // récupérer les positions actuelles des actionneurs
  for (int i = 0; i < GP_DXL_CNT; i++) {
    Current_Pose[i] = dxl_mini.getPresentPosition(GP_DXL_ID_LIST[i]);
  }
  // effacer toutes les commandes du robot de Serial2
  UP = false;
  DOWN = false;
  LEFT = false;
  RIGHT = false;

  RcvData_2 = 0;
  // Traitement des nouveaux boutons RC-100
  if (RC_2.available()) {
    RcvData_2 = RC_2.readData();
    if (RcvData_2 == 0) {
      Serial.println("Tous les boutons libérés via Serial2");
    }

    if ((RcvData_2 & RC100_BTN_U) > 0) {
      Serial.println("Button UP poussé via Serial2");
      UP = true;
    }
    if ((RcvData_2 & RC100_BTN_D) > 0) {
      Serial.println("Button DOWN poussé via Serial2");
      DOWN = true;
    }
    if ((RcvData_2 & RC100_BTN_L) > 0) {
      Serial.println("Button LEFT poussé via Serial2");
      LEFT = true;
    }
    if ((RcvData_2 & RC100_BTN_R) > 0) {
      Serial.println("Button RIGHT poussé via Serial2");
      RIGHT = true;
    }
  }
  // Faire fonctionner le robot selon les commandes de l'opérateur via Serial2
  if (UP == true) {
    Serial.println("jouer salut main");

    for (int frame_no = 0; frame_no < 6; frame_no++)  // 6 images de mouvement ont été définies pour le mouvement bras
    {
      STEP_TIME_1 = (int)(round(salut_main[frame_no][0]));  //c'est-à-dire STEP TIME 1 = millis
      for (int i = 0; i < GP_DXL_CNT; i++)                  // Définition des valeurs GP brutes pour les DXL 1 à 16
      {
        goal_position_raw = (CalcAngle2Raw(salut_main[frame_no][i + 1]));  //convertir l'angle de mouvement en Raw GP
        memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
        dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
        //dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
      }
      dxl_mini.syncWrite(GP_sync_write_param);
      delay(390);  // en attendant que chaque image clé soit jouée en ms
    }
  }
  if (DOWN == true) {
    Serial.println("jouer salut 2");
    for (int frame_no = 0; frame_no < 6; frame_no++)  // 6 images de mouvement ont été définies pour le mouvement bras
    {
      STEP_TIME_1 = (int)(round(salut_2[frame_no][0]));
      for (int i = 0; i < GP_DXL_CNT; i++)  // Définition des valeurs GP brutes pour les DXL 1 à 16
      {
        //STEP_TIME_1  = (int)(round(salut_2[frame_no][0] ));
        goal_position_raw = (CalcAngle2Raw(salut_2[frame_no][i + 1]));  //convertir l'angle de mouvement en Raw GP
        memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
        dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 400);
        // dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);/////////////////////////
      }
      dxl_mini.syncWrite(GP_sync_write_param);

      delay(390);  // en attendant que chaque image clé soit jouée en ms
    }              // fin de pour (numéro de trame)
  }
}

D'abord, tu n'as pas besoin des return ici :

et ici :

Ensuite, pour éviter de jouer les animations plusieurs fois, tu peux essayer de remettre à False tes indicateurs à la fin des actions. Par exemple :

        if(DOWN  == true)  
  {
       Serial.println("jouer salut 2");  
      for (int frame_no = 0; frame_no <6; frame_no++)   // 6 images de mouvement ont été définies pour le mouvement bras
      {
         STEP_TIME_1 = (int)(round(salut_2[frame_no][0] )); 
        for (int i = 0; i < GP_DXL_CNT; i++)  // Définition des valeurs GP brutes pour les DXL 1 à 16
        {
           //STEP_TIME_1  = (int)(round(salut_2[frame_no][0] )); 
          goal_position_raw = (CalcAngle2Raw(salut_2[frame_no][i+1]) );  //convertir l'angle de mouvement en Raw GP 
          memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
          dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 400);
         // dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);/////////////////////////
        }
         dxl_mini.syncWrite(GP_sync_write_param); 
       
        delay(390); // en attendant que chaque image clé soit jouée en ms
      }  // fin de pour (numéro de trame)
    
     DOWN = False ;   // <--- ICI !
   }  

Pour la suite des échanges, ce serait bien que tu formattes correctement ton code, pour en faciliter la lecture : dans l'IDE Arduino, tu fais CTRL T. L'indentation sera revue, et tu pourras remettre ton code sur le forum.

Bonjour
je vous remercie pour votre réponse . mais cela ne fonctionne pas .
les commandes envoyer dans la buffer reste et sont jouer a la suite.
je voudrai vider le buffer une fois le mouvement jouer.

et pour CTRL T que je vient d'apprendre :grinning:

Formatage fait

Merci, tu as mis le code formatté et ôté les return, mais tu n'as pas fait la suggestion que je t'ai faite.

j'ai fait la modification dans mon code pour essai mais cela ne fonctionne pas.



#include <RC100.h>

// **** Global Parameters for DXLs *********
#include <Dynamixel2Arduino.h>
#define DXL_SERIAL_1 Serial1  //Serial1 is for DXL port on OpenRB-150
//#define DEBUG_SERIAL Serial

// **** Global Parameters for DXLs *********
const uint8_t BROADCAST_ID = 254;
const uint8_t DXL_ID1 = 1;
const uint8_t DXL_ID2 = 2;
const uint8_t DXL_ID3 = 3;
const uint8_t DXL_ID4 = 4;
const uint8_t DXL_ID5 = 5;
const uint8_t DXL_ID6 = 6;
const uint8_t DXL_ID7 = 7;
const uint8_t DXL_ID8 = 8;
const uint8_t DXL_ID9 = 9;
const uint8_t DXL_ID10 = 10;
const uint8_t DXL_ID11 = 11;
const uint8_t DXL_ID12 = 12;
const uint8_t DXL_ID13 = 13;
const uint8_t DXL_ID14 = 14;
const uint8_t DXL_ID15 = 15;
const uint8_t DXL_ID16 = 16;

Dynamixel2Arduino dxl_mini(DXL_SERIAL_1);

// Number of DXLs used in robot
const float DXL_PROTOCOL_VERSION = 2.0;
const uint8_t GP_DXL_CNT = 16;                                                                         // nombre de DXL utilisés en mode Contrôle de position
const uint8_t GP_DXL_ID_LIST[GP_DXL_CNT] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };  //ID de servo définis en mode Contrôle de position
const uint16_t ADDR_X_PRESENT_POSITION = 37;                                                           // (XL-320)
const uint16_t LEN_X_PRESENT_POSITION = 2;                                                             //  (XL-320)
const uint16_t ADDR_X_GOAL_POSITION = 30;                                                              // (XL-320)
const uint16_t LEN_X_GOAL_POSITION = 2;                                                                // (XL-320)
const uint16_t ADDR_X_MOVING_SPEED = 32;                                                               // (XL-320)       adress 32 byt 2   0-2047
const uint16_t LEN_X_MOVING_SPEED = 2;                                                                 // (XL-320)
const uint16_t ADDR_X_TORQUE_ENABLE = 24;                                                              // (XL-320)    TORQUE_ENABLE     adress 24   0  off      1 on
const uint16_t LEN_X_TORQUE_ENABLE = 1;
const uint8_t CONTROL_MODE = 2;  //             for XL320  adress 11      byt 1  mode 2 =joint

uint16_t Current_Pose[GP_DXL_CNT] = { 0 };
//uint16_t Step = 10;//   Étape

// ********** RC100 settings *************
#include <RC100.h>
RC100 RC_2;  // Instalation de la télécommande via Serial2
uint16_t RcvData_2 = 0;
bool UP = false;
bool DOWN = false;
bool LEFT = false;
bool RIGHT = false;

// ********** End of Global Parameters Definition

//**** This namespace is required to use Control table item names
//using namespace ControlTableItem;

ParamForSyncWriteInst_t MS_sync_write_param;  // Parameters structure for MS packet
ParamForSyncWriteInst_t GP_sync_write_param;  // Parameters structure for SW GP packet
ParamForSyncReadInst_t GP_sync_read_param;    // Parameters structure for SR GP packet
RecvInfoFromStatusInst_t GP_read_result;      // Structure for results of SR PP command

uint8_t dxl_error = 0;                             // Dynamixel error
int32_t dxl_MOVING_SPEED[GP_DXL_CNT] = { 0 };      // Tableau de position vitesse
int32_t dxl_present_position[GP_DXL_CNT] = { 0 };  //  Tableau de position actuelle
int32_t dxl_goal_position[GP_DXL_CNT] = { 0 };     // Tableau de position d'objectif

bool read_present_positions_OK = false;

// Section MOUVEMENT
bool check_motion();
bool B_6 = false;  /////////////////////////////////////


/*void myDelay (unsigned long combien_de_temps)
  {
  unsigned long start = millis ();
  if (millis () - start <= combien_de_temps)//
    { }  
  } */

int GP_time = dxl_MOVING_SPEED[200];

int _STEP_TIME_0 = millis();
int STEP_TIME_1 = millis();

float pose_init[17] = { 390, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 };

float salut_main[6][17] = { { 50, -0.29, -150, -73.54, 72.36, -0.29, 0.59, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },  // 50  75  100   125 150   275
                            { 25, -0.29, -150, -73.54, 51.27, -0.29, -33.69, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 91.7, -0.29, 32.81, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 51.27, -0.29, -33.69, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 25, -0.29, -150, -73.54, 91.7, -0.29, 32.81, -0.29, -0.29, -26.66, 26.07, 29, -29.59, 12.89, -13.48, -0.29, -0.29 },
                            { 125, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 } };

float salut_2[6][17] = { {
                           25,
                           -22.27,
                           -44.24,
                           -73.24,
                           73.24,
                           0,
                           0,
                           0,
                           0,
                           -26.37,
                           26.07,
                           29.3,
                           -29.3,
                           13.18,
                           -13.48,
                           0,
                           0,
                         },  //25  75  150  275  350  400
                         { 50, -22.27, -44.24, -62.99, 92.58, -71.78, 58.59, 0, 0, -26.37, 26.07, 29.3, -29.3, 13.18, -13.48, 0, 0 },
                         { 75, -22.27, -69.73, -62.99, 92.58, -71.78, 58.59, 0, 0, -79.39, 82.91, 29.3, -29.3, -10.25, 10.55, 0, 0 },
                         { 125, -22.27, -69.73, -62.99, 92.58, -71.78, 58.59, 0, 0, -79.39, 82.91, 29.3, -29.3, -10.25, 10.55, 0, 0 },
                         { 75, -22.27, -44.24, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.07, 29.3, -29.3, 13.18, -13.48, 0, 0 },
                         { 50, 0, 0, -73.24, 73.24, 0, 0, 0, 0, -26.37, 26.37, 29.3, -29.3, 13.18, -13.18, 0, 0 } };

// ********** Function prototypes
//int GP_time = dxl_MOVING_SPEED[300]; //////////////////////////////////////
int CalcAngle2Raw(int angle) {
  return (int)(round((angle * 1023.0 / 300.0 + 512.0)));  // return (int)(round((angle * 1023.0 / 300.0 + 512.0)));XL 320
}  // fin de CalcAngle2Raw (angle int)

int i = 16;
int frame_no = 0;
int goal_position_raw = 0;

// Cet espace de noms est requis pour utiliser les noms d'éléments de la table de contrôle
using namespace ControlTableItem;

void setup() {
  int goal_position_raw = 0;  // raw     valeur brute de la position de l'objectif DXL
  Serial.begin(115200);
  while (!Serial)
    ;  // attendez que l'opérateur ouvre Serial Monitor

  // *****Configuration des Dynamixels pour mini ***

  dxl_mini.begin(1000000);  // débit en bauds du port DXL sur 1 Mbps pour XL320
  dxl_mini.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  dxl_mini.scan();
  Serial.println("Fin de la numérisation des DXL du robot ");

  // Préparation du paquet GP SW
  MS_sync_write_param.addr = ADDR_X_MOVING_SPEED;
  MS_sync_write_param.length = LEN_X_MOVING_SPEED;
  MS_sync_write_param.id_count = GP_DXL_CNT;
  for (int i = 0; i < GP_DXL_CNT; i++) {
    MS_sync_write_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet MS SW");

  // Préparation du paquet GP SR
  GP_sync_read_param.addr = ADDR_X_PRESENT_POSITION;  // Present Position of DYNAMIXEL-X series
  GP_sync_read_param.length = LEN_X_PRESENT_POSITION;
  GP_sync_read_param.id_count = GP_DXL_CNT;  // Number of servos in Position Control Mode
  for (int i = 0; i < GP_DXL_CNT; i++) {
    GP_sync_read_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet GP SR");

  // Préparation du paquet GP SW
  GP_sync_write_param.addr = ADDR_X_GOAL_POSITION;
  GP_sync_write_param.length = LEN_X_GOAL_POSITION;
  GP_sync_write_param.id_count = GP_DXL_CNT;
  for (int i = 0; i < GP_DXL_CNT; i++) {
    GP_sync_write_param.xel[i].id = GP_DXL_ID_LIST[i];
  }
  Serial.println("Fin de la préparation du paquet GP SW");

  // Configuration des servos GP dans la zone EEPROM : mode contrôle contrôle de position
  // et dans la zone RAM : vitesse  dxl  du profil
  for (int i = 0; i < GP_DXL_CNT; i++) {
    dxl_mini.torqueOff(GP_DXL_ID_LIST[i]);                               // Torque OFF
    dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 0);  // Définition des vitesses de déplacement initiales
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
    dxl_mini.torqueOn(GP_DXL_ID_LIST[i]);  // Torque ON
    delay(100);                            // attendez un peu avant de travailler dans la zone RAM
  }
  Serial.println("Fin de la configuration des servos GP");

  delay(1000);

  Serial.begin(115200);
  RC_2.begin(2);  // RC_2 utilisant Serial2 - Port UART 4 ​​broches - débit en bauds 57 600 bps dans RC100.cpp
  dxl_mini.begin(1000000);
  dxl_mini.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
  for (int i = 0; i < GP_DXL_CNT; i++) {
    dxl_mini.ping(GP_DXL_ID_LIST[i]);
    dxl_mini.torqueOff(GP_DXL_ID_LIST[i]);
    //dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
    dxl_mini.torqueOn(GP_DXL_ID_LIST[i]);
    delay(100);  // attendez un peu avant de travailler dans la zone RAM
  }
  Serial.println("Mettre le robot dans la pose initiale");
  // Allouez la valeur brute de chaque position d'objectif dans le paquet GP SW, un DXL à la fois en utilisant les valeurs du tableau global _[1] à _[16]

  for (int i = 0; i < GP_DXL_CNT; i++)  // DXL 1 à 16
  {
    _STEP_TIME_0 = (int)(round(pose_init[0]));  //c'est-à-dire STEP TIME 0 = millis   ///////////////////////////////////////
    //  Réglez le robot sur la pose _ via SyncWrite
    goal_position_raw = CalcAngle2Raw(pose_init[i + 1]);  // convertir l'angle de mouvement en position d'objectif brute [0-1023], _[0] n'est pas utilisé ici
    memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
    dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
    dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
  }
  dxl_mini.syncWrite(GP_sync_write_param);  // send GP SW Packet
  delay(1000);
  Serial.println("Fin de la configuration pose init");
}

void loop() {
  // récupérer les positions actuelles des actionneurs
  for (int i = 0; i < GP_DXL_CNT; i++) {
    Current_Pose[i] = dxl_mini.getPresentPosition(GP_DXL_ID_LIST[i]);
  }
  // effacer toutes les commandes du robot de Serial2
  UP = false;
  DOWN = false;
  LEFT = false;
  RIGHT = false;

  RcvData_2 = 0;
  // Traitement des nouveaux boutons RC-100
  if (RC_2.available()) {
    RcvData_2 = RC_2.readData();
    if (RcvData_2 == 0) {
      Serial.println("Tous les boutons libérés via Serial2");
    }

    if ((RcvData_2 & RC100_BTN_U) > 0) {
      Serial.println("Button UP poussé via Serial2");
      UP = true;
    }
    if ((RcvData_2 & RC100_BTN_D) > 0) {
      Serial.println("Button DOWN poussé via Serial2");
      DOWN = true;
    }
    if ((RcvData_2 & RC100_BTN_L) > 0) {
      Serial.println("Button LEFT poussé via Serial2");
      LEFT = true;
    }
    if ((RcvData_2 & RC100_BTN_R) > 0) {
      Serial.println("Button RIGHT poussé via Serial2");
      RIGHT = true;
    }
  }
  // Faire fonctionner le robot selon les commandes de l'opérateur via Serial2
  if (UP == true) {
    Serial.println("jouer salut main");

    for (int frame_no = 0; frame_no < 6; frame_no++)  // 6 images de mouvement ont été définies pour le mouvement bras
    {
      STEP_TIME_1 = (int)(round(salut_main[frame_no][0]));  //c'est-à-dire STEP TIME 1 = millis
      for (int i = 0; i < GP_DXL_CNT; i++)                  // Définition des valeurs GP brutes pour les DXL 1 à 16
      {
        goal_position_raw = (CalcAngle2Raw(salut_main[frame_no][i + 1]));  //convertir l'angle de mouvement en Raw GP
        memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
        dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 200);
        //dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);
      }
      dxl_mini.syncWrite(GP_sync_write_param);
      delay(390);  // en attendant que chaque image clé soit jouée en ms
    }
    UP = false;
  }
  if (DOWN == true) {
    Serial.println("jouer salut 2");
    for (int frame_no = 0; frame_no < 6; frame_no++)  // 6 images de mouvement ont été définies pour le mouvement bras
    {
      STEP_TIME_1 = (int)(round(salut_2[frame_no][0]));
      for (int i = 0; i < GP_DXL_CNT; i++)  // Définition des valeurs GP brutes pour les DXL 1 à 16
      {
        //STEP_TIME_1  = (int)(round(salut_2[frame_no][0] ));
        goal_position_raw = (CalcAngle2Raw(salut_2[frame_no][i + 1]));  //convertir l'angle de mouvement en Raw GP
        memcpy(GP_sync_write_param.xel[i].data, &goal_position_raw, sizeof(goal_position_raw));
        dxl_mini.writeControlTableItem(MOVING_SPEED, GP_DXL_ID_LIST[i], 400);
        // dxl_mini.setOperatingMode(GP_DXL_ID_LIST[i], OP_POSITION);/////////////////////////
      }
      dxl_mini.syncWrite(GP_sync_write_param);

      delay(390);  // en attendant que chaque image clé soit jouée en ms
    }              // fin de pour (numéro de trame)
    DOWN = false;
  }
}

je pense qu'il faut que la premier commande soit valider est les autres ignorées .puis vide le buffer
et repartir de zero mais cela je ne s'ait pas le faire. le temps d'appui sur la commande s enregistre plusieurs fois .ce temps n'est jamais le même puisque un appui sur une touche est fait par un moi .
toutes suggestions est la bienvenu ou un exemple dans un autre code que je pourrai adapter.

Il suffit de mémoriser la dernière commande traitée et de la comparer avec la commande que tu reçois si elles sont identiques tu l'ignores.

Peut-être mettre une temporisation la-dessus sinon cela t'interdira de faire 2 fois de suite la même chose.

Merci pour la réponse mais je début auriez vous un exemple .
pas de temporisation car le temps de l'appui sur la commande n'est jamais le meme
Merci d'avance

Une autre solution serait de vider le buffer de communication à la fin de chaque action. Ce serait fait par une fonction :

void RC100Vide (RC100 RC) {
   while (RC.available()) RC.readData();
}

L'appel se ferait par :
RC100Vide (RC_2);

A mettre à la place des lignes que je t'ai fait ajouter (qui ne servent à rien, je n'avais pas vu que c'est déjà fait plus haut) :

UP = false;
DOWN = false;

Merci de votre réponse je vient d'essayer mais cela ne fonctionne pas, toujours un ou plusieurs mouvement jouer selon le temps d'appui sur la commande.je pense que le buffer se vide mais une fois tous les mouvements fait.(je précise que la répétition des mouvement sont fait les un derrière les autre sans interruptions).

C'est bien pour cela que je propose d'ignorer les commandes identiques sur une période de temps donnée.

pouvez vous me donner un exemple .je ne sait pas faire cela. Merci d'avance

Il suffit de mettre la dernière commande exécutée dans une variable et de la comparer avec celle que tu reçois.

Merci de votre réponse .mais comme je suis novice il me faudrait un un exemple concret que je puisse adapté a mon code . je précise que sur ma télécommande virtuel quand j appui sur up c'est 1 qui est envoyer au robot down c est deux.Je vous remercie par avance.

Je pense qu'il serait bien plus bénéfique pour tu arrives à décortiquer ce que t'indique @fdufnews
Soit en suivant des cours de C/C++
Soit en nous disant ce que tu ne connais/comprends pas dans l'indication de @fdufnews

Merci pour vos réponses .J'ai 60 ans je ne vais pas prendre de cours je vous remercie .je préfère apprendre par l'exemple qui est plus simple pour moi.je connais les Base Arduino.(constante .variable fonction). mais dans l'explication je ne comprend pas le principe fonctionnement .
"dernier commande exécuter" qui pour moi ne fonctionne pas puisque qu'avec cette commande mon robot joue plusieurs mouvement.

Le robot n'exécute pas une commande mais plusieurs à la suite.
Donc lorsque tu exécutes UNE commande tu places cette commande dans une variable.
Lorsque tu reçois la suivante tu compares la commande que tu avais exécutée précédemment avec celle que tu viens de recevoir et si c'est la même tu ne fais rien.

Je ne vois pas trop ce que l'age à faire là-dedans, sinon pourquoi apprendre l'Arduino à cet age avancé :slight_smile:
Je parle de lire des cours ou articles, pas forcément de prendre des cours à l'école non plus :thinking:

Malheureusement l'apprentissage par l'exemple est bien plus long et permet une autonomie bien plus réduite, la preuve.
Après je comprends par contre que tu peux avoir l'impression que c'est plus simple.
Mais tu peux aussi te fier aux conseil de plus expérimenter comme tu te fie à des exemples que l'on pourrait te donner.

Si tu connais les Bases de la programmation Arduino, il n'y a pas de raison que tu n'arrive pas à adapter ton programme en conséquence, il suffit d'exposer ce que tu trouve pas très claire.

Merci pour votre aide. En écrivant le commentaire pour vous demander plus d'explication je vient de comprendre la variable qu'il me faut.je n'ai pas compris ce qu'il faillait dans cette variable. je vient de comprendre qu'il me faut la variable d'exécution du mouvement et non l'appui sur mon bouton "qui me donne plusieurs donnée .
Merci

Il y a aussi l'aspect 'période de temps donnée' qui complique la chose.
Sur Arduino, le temps écoulé se mesure avec l'instruction millis(), qui fournit le nombre de millisecondes écouées depuis le lancement du code. Il faut alors créer une variable globale (un unsigned long) qui servira de chrono pour stocker le temps passé.

Tu vas donc créer une variable globale qui contiendra la valeur de la dernière commande reçue. Il faudra la coder pour que ce soit plus simple, par exemple 0 pour UP, 1 pour DOWN, etc.

A chaque fois que tu exécutes une action, il faut réinitialiser le chrono en faisant :
chrono = millis();
et stocker la valeur de la commande :
oldCommande = 0; // Cas du UP

Mais tu ne dois pas exécuter de nouvelle commande avant qu'un certain délai soit écoulé. Il faut donc imaginer un test et savoir comment le positionner dans la loop pour faire cette vérification et autoriser ou non l'action correspondant à la commande reçue. C'est là que se situe la difficulté pour toi.

Je te laisse réfléchir à tout ça...

1 Like