Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Composants et fournitures

Dispositif uECG ×3
Main InMoov ×1
Arduino Nano R3 ×1
Pilote PWM 16 canaux Adafruit PCA9685 ×1
Module nRF24 (générique) ×1

À propos du projet

Notre équipe a une longue histoire avec les mains robotiques. Pendant un moment, nous avons essayé de créer une main prosthétique fiable, mais pour ce projet j'utilise un bon exemple de main open source existante : InMoov.

Je ne détaillerai pas l'assemblage de la main – c'est bien décrit sur le site du projet et c'est assez complexe. Je me concentrerai sur le contrôle, qui est complètement nouveau :)
Découvrez aussi comment cette technologie a évolué dans le projet suivant : Voir les muscles au travail – EMG 8 canaux avec LEDs

1. Traitement du signal

Le contrôle repose sur l'EMG – l'activité électrique des muscles. Le signal EMG est obtenu par trois dispositifs uECG (conçus à l'origine pour l'ECG, mais basés sur un ADC générique, ils peuvent mesurer tout biosignal, dont l'EMG). Pour le traitement EMG, uECG dispose d'un mode spécial envoyant des données spectrales à 32 bins, et une moyenne « fenêtre musculaire » (intensité spectrale moyenne entre 75 et 440 Hz). Les images spectrales ressemblent à ceci :

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Ici la fréquence est sur l'axe vertical (sur chaque graphique, basses fréquences en bas, hautes en haut – 0 à 488 Hz par pas de ~15 Hz), le temps sur l'horizontal (données anciennes à gauche, ~10 secondes affichées). L'intensité est codée en couleur : bleu = faible, vert = moyen, jaune = fort, rouge = très fort.

Pour une reconnaissance de gestes fiable, un traitement PC approfondi de ces images est requis. Mais pour une simple activation des doigts de la main robotique, il suffit d'utiliser la valeur moyenne sur 3 canaux – uECG la fournit commodément à certains octets du paquet pour que le sketch Arduino la parse. Ces valeurs sont bien plus simples :

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Les courbes rouge, verte, bleue sont les valeurs brutes des uECG sur différents groupes musculaires quand je presse pouce, annulaire et majeur. Pour notre œil ces cas sont clairement différents, mais il faut transformer ces valeurs en « score de doigt » pour que le programme pilote les servos. Le problème : les signaux des groupes musculaires sont « mélangés ». Dans les cas 1 et 3, l'intensité du signal bleu est similaire – mais rouge et vert diffèrent. Dans les cas 2 et 3, les signaux verts sont identiques – mais bleu et rouge diffèrent. Pour les « démélanger », j'ai utilisé une formule relativement simple :

S0 = V0² / ((V1 × a0 + b0)(V2 × c0 + d0))

où S0 = score canal 0, V0,V1,V2 = valeurs brutes canaux 0,1,2, et a,b,c,d = coefficients ajustés manuellement (a et c entre 0,3 et 2,0, b et d = 15 et 20 – à adapter selon votre placement de capteurs). Le même score est calculé pour les canaux 1 et 2. Après cela, les courbes deviennent presque parfaitement séparées :

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Pour les mêmes gestes (annulaire, majeur, puis pouce), les signaux sont clairs et peuvent être traduits en mouvements de servos par simple comparaison avec un seuil.

2. Schémas

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Le schéma est simple : module nRF24, contrôleur PWM I2C PCA9685 (ou similaire), et alimentation 5V forte capacité pour mouvoir tous les servos à la fois (au moins 5A nominal pour fonctionnement stable).

Liste des connexions :

3. Placement des capteurs EMG

Pour obtenir des lectures exploitables, il est crucial de placer les dispositifs uECG (enregistrant l'activité musculaire) aux bons endroits. Bien que de nombreuses options soient possibles, chacune requiert une approche de traitement différente – voici ce que j'ai utilisé :

Main Robotique EMG Précise : Intégration InMoov et Guide de Construction

Contre-intuitivement, le signal du muscle du pouce est mieux visible du côté opposé du bras, donc un capteur y est placé, et tous sont près du coude (les muscles ont leur masse là, mais vérifiez où se trouvent les vôtres – grandes différences individuelles).

4. Code

Avant d'exécuter le programme principal, il faut trouver les IDs d'unité de vos uECG (en décommentant ligne 101 et allumant les dispositifs un par un) et les renseigner dans le tableau unit_ids (ligne 37).

#include <SPI.h>
#include <RF24.h>
#include <RF24_config.h>
#include <nRF24L01.h>
#include <Adafruit_PWMServoDriver.h>
#include <Wire.h>

#define SERVOMIN 150
#define SERVOMAX 600

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
int rf_cen = 9;
int rf_cs = 8;
RF24 rf(rf_cen, rf_cs);

uint8_t pipe_rx[8] = {0x0E, 0xE6, 0x0D, 0xA7, 0, 0, 0, 0};

uint8_t swapbits(uint8_t a) {
  uint8_t v = 0;
  if(a & 0x80) v |= 0x01;
  if(a & 0x40) v |= 0x02;
  if(a & 0x20) v |= 0x04;
  if(a & 0x10) v |= 0x08;
  if(a & 0x08) v |= 0x10;
  if(a & 0x04) v |= 0x20;
  if(a & 0x02) v |= 0x40;
  if(a & 0x01) v |= 0x80;
  return v;
}

long last_servo_upd = 0;
byte in_pack[32];
unsigned long unit_ids[3] = {4294963881, 4294943100, 28358};
int unit_vals[3] = {0, 0, 0};
float tgt_angles[5];
float cur_angles[5];
float angle_open = 30;
float angle_closed = 150;

void setup() {
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  for(int x = 0; x < 8; x++) pipe_rx[x] = swapbits(pipe_rx[x]);
  
  rf.begin();
  rf.setDataRate(RF24_1MBPS);
  rf.setAddressWidth(4);
  rf.setChannel(22);
  rf.setRetries(0, 0);
  rf.setAutoAck(0);
  rf.disableDynamicPayloads();
  rf.setPayloadSize(32);
  rf.openReadingPipe(0, pipe_rx);
  rf.setCRCLength(RF24_CRC_DISABLED);
  rf.disableCRC();
  rf.startListening();
  
  Serial.begin(115200);
  pwm.begin();
  pwm.setPWMFreq(60);
  for(int i = 0; i < 5; i++) {
    tgt_angles[i] = angle_open;
    cur_angles[i] = angle_open;
  }
}

void setAngle(int n, float angle) {
  pwm.setPWM(n, 0, SERVOMIN + angle * 0.005556 * (SERVOMAX - SERVOMIN));
}

float angle_speed = 15;
float v0 = 0, v1 = 0, v2 = 0;

void loop() {
  if(rf.available()) {
    rf.read(in_pack, 32);
    byte u1 = in_pack[3], u2 = in_pack[4], u3 = in_pack[5], u4 = in_pack[6];
    unsigned long id = (u1<<24) | (u2<<16) | (u3<<8) | u4;
    if(in_pack[7] != 32) id = 0;
    int val = in_pack[10];
    if(val != in_pack[11]) id = 0;
    for(int n = 0; n < 3; n++)
      if(id == unit_ids[n]) unit_vals[n] = val;
  }
  
  long ms = millis();
  if(ms - last_servo_upd > 20) {
    last_servo_upd = ms;
    for(int n = 0; n < 5; n++) {
      if(cur_angles[n] < tgt_angles[n] - angle_speed/2) cur_angles[n] += angle_speed;
      if(cur_angles[n] > tgt_angles[n] + angle_speed/2) cur_angles[n] -= angle_speed;
    }
    for(int n = 0; n < 5; n++) setAngle(n, cur_angles[n]);
    
    v0 = v0*0.7 + 0.3*(float)unit_vals[0];
    v1 = v1*0.7 + 0.3*(float)unit_vals[1];
    v2 = v2*0.7 + 0.3*(float)unit_vals[2];
    
    float scor0 = 4.0*v0*v0/((v1*0.3 + 20)*(v2*1.3 + 15));
    float scor1 = 4.0*v1*v1/((v0*2.0 + 20)*(v2*2.0 + 20));
    float scor2 = 4.0*v2*v2/((v0*1.2 + 20)*(v1*0.5 + 15));
    
    Serial.print(scor0); Serial.print(' '); Serial.print(scor1); Serial.print(' '); Serial.println(scor2);
    
    if(scor2 < 0.5) tgt_angles[0] = angle_open;
    if(scor2 > 1.0) tgt_angles[0] = angle_closed;
    if(scor1 < 0.5) { tgt_angles[1] = angle_open; tgt_angles[2] = angle_open; }
    if(scor1 > 1.0) { tgt_angles[1] = angle_closed; tgt_angles[2] = angle_closed; }
    if(scor0 < 0.5) { tgt_angles[3] = angle_open; tgt_angles[4] = angle_open; }
    if(scor0 > 1.0) { tgt_angles[3] = angle_closed; tgt_angles[4] = angle_closed; }
  }
}

5. Résultats

Après environ 2 heures d'expérimentation, j'ai obtenu un fonctionnement assez fiable (la vidéo montre un cas typique) :

Le comportement n'est pas parfait et ce traitement ne reconnaît que doigts ouverts/fermés (et pas même les 5 individuellement – seulement 3 groupes musculaires : pouce, index+majeur ensemble, annulaire+auriculaire ensemble). Mais l'« IA » qui analyse le signal ne prend que 3 lignes de code ici et utilise une seule valeur par canal. Je pense qu'on pourrait faire bien plus en analysant les images spectrales à 32 bins sur PC ou smartphone. Cette version utilise seulement 3 uECG (3 canaux EMG). Avec plus de canaux, la reconnaissance de motifs complexes devrait être possible – mais c'est le but du projet : fournir un point de départ pour quiconque s'intéresse :) Le contrôle de main n'est pas la seule application pour un tel système.

Code source

Schémas

nrf24_hand_control_5jcEeCP8a3.fzz

Processus de fabrication

  1. La pilule contraceptive : histoire, avantages, risques et production
  2. Construire un véhicule robotique sans fil piloté par capteur IR
  3. Trinamic et Maxim Integrated publient un design de référence pour accélérer le développement d'outils de bout de bras en robotique industrielle
  4. Système de contrôle de température basé LM35 avec microcontrôleur AT89S52
  5. Puces photoniques pilotées par l'IA façonnent la lumière large bande pour l'optique intelligente
  6. Rationaliser l'Automatisation Robotique avec le Logiciel de Simulation Robotique Avancé 3DG
  7. Contrôle Automatique de Train Miniature Arduino – Simple, Fiable et Personnalisable
  8. Construire une télécommande Android universelle avec Arduino, 1Sheeld et contrôle IR
  9. Des étudiants construisent un système robotique de tri des déchets avancé propulsé par B&R