Prothèse myoélectrique

Le projet consiste en la réalisation d’un dispositif mécatronique permettant de reproduire les mouvements de flexion et d’extension exécutée par une personne saine, et cela en réalisant l’acquisition et le traitement du signal EMG de surface à l’aide d’électrodes de surface récolté au niveau du biceps brachial (principal mouvement mis en jeu dans la réalisation des mouvements de flexion et d’extension). Vu la complexité du projet et au nombreux domaines auquel il fait appel, nous avons organisé notre projet de la façon suivante :

Dans un premier temps nous nous sommes basés sur l'électromyographie. Après une étude bibliographique dans le but de faire un état de l’art sur les prothèses myoélectriques, nous nous sommes penchés sur l'origine du signal EMG et ses différentes caractéristiques afin de déterminer la meilleure façon d'en faire l'acquisition. Une étape clef de cette partie était l’étude des recommandation SENIAM (Surface Electromyography for the Non-Invasiv Assessment of Muscles) qui nous a fourni les éléments pour maximiser la qualité et normaliser l'acquisition du signal EMG.

Par la suite, nous nous sommes penchés sur la partie dédiée au traitement du signal EMG et à sa classification. Dans un premier temps, nous avons réalisé une étude bibliographique sur les différents types de classifieurs afin d’en déterminer celui qui sera le plus adapté pour notre application. Cette étape a été suivie par le design du classifieur et la détermination du modèle du classifieur permettant de classer et de différencier les deux mouvements cibles.

Pour finaliser le projet, nous avons effectué une étude de l’anatomie du bras pour déterminer les principales caractéristiques que doit reproduire le système, puis nous sommes passés à la partie dédier à l’implémentation sur microcontrôleur, ou nous avons programmé l’acquisition du signal EMG, implémenter le modèle du classifieur et programmer les différents mouvements que doit exécuter le servo-moteur.

Slides & Videos

Members

NameContribution
Hamid Arslan AMIRAT-Etude bibliographique (EMG, prothèses myoélectrique, classification).
-Réalisation de la base de données.
-Extraction des caractéristiques et entrainement du classifieur sur MATLAB.
-Implémentation sur Arduino (acquisition du signal EMG et implémentation du classifieur).
Ryma BAZIZ -Etude bibliographique ( EMG, classifieur, anatomie du bras).
-Entrainement du classifieur et test des performances du classifieur.
-Implémentation sur carte Arduino (Implémentation du classifieur, commande du servo-moteur).

State of the Art

Business Aspect
Technical Aspect

BOSTON ELBOW

BOSTON ELBOW est une prothèse myoélectrique du coude avec un seul degré de liberté. Elle permet au patient handicapé d’effectuer uniquement la flexion et l’extension du coude. Le coude BOSTON est constitué d’un avant-bras contenant les circuits électroniques et une batterie. Différents terminaux peuvent être fixés à son extrémité (crochet mécanique ou main artificielle passive). Une cavité est utilisée pour accueillir le moignon. C’est au niveau de cette cavité que sont placées des électrodes de surface pour recueillir les signaux EMG du biceps et du triceps. Les signaux EMG sont transmis et traités par un ordinateur pour commander le moteur situé au niveau du coude. La commande est une commande proportionnelle ce qui permet au patient d’effectuer les mouvements de flexion et d’extension à différentes vitesses en faisant varier l’intensité de la contraction. Le coude BOSTON pèse 900 g. Il peut soulever une charge de 2,2 kg et maintenir en position verrouillée avec une charge maximale de 22 kg. L’amplitude des mouvements de flexion-extension est identique à celle d’un bras sain. En effet, la prothèse BOSTON permet une flexion complète de 145° et une extension complète de 0°. Vu les performances du coude BOSTON, la société LTI a utilisé ce dernier pour élaborer la prothèse BOSTON DIGITAL qui est une prothèse myoélectrique modulaire. La prothèse BOSTON DIGITAL repose sur l’utilisation de microprocesseurs permettant le contrôle de 4 dispositifs différents en plus du coude : les mains, les pinces, les rotateurs de poignet et les actionneurs de verrouillage des épaules. Ces différents dispositifs sont sélectionnés de manière séquentielle via une contraction rapide. L’une des particularités de cette prothèse est qu’elle permet d’évaluer le patient afin de déterminer les sites musculaires appropriés, puis tente différentes stratégies de contrôle pour trouver celle qui convient le mieux. Ceci est accompli grâce à un logiciel d’interface qui, une fois la configuration déterminée, transfère cette dernière vers la prothèse.

Le bras artificiel UTAH

Le bras artificiel UTAH a été développé à l’Université de l’Utah dans un laboratoire créé en 1974 par le Dr Stephen C. Jacobsen et appelé maintenant The Center for Engineering Design. La première version du coude myoélectrique a été introduite en décembre 1980, ce qui faisait de la prothèse UTHA la première prothèse pour les amputés huméraux. Cette dernière a été développé, et en 1989, la société MOTION CONTROL a lancé UTHA ARM 2 qui a son tour a été développée en UTHA ARM 3 et distribuée par la même société en 2004. La particularité de la prothèse UTHA est qu’elle peut être connectée à une main ou un poignet myoélectrique OTTO BOCK (société leader dans les prothèses de mains myoélectriques). Ceci la rend capable de réaliser l’ouverture ou la fermeture de la main ainsi que le mouvement de pronation-supination en plus de la flexion et de l’extension du coude. La commande est transférée entre la main et le poignet soit à l’aide d’une contraction musculaire rapide, soit par l’intermédiaire d’un interrupteur externe, selon la version. Elle intègre en plus 2 processeurs ce qui lui permet de réaliser deux fonctions en même temps (flexion/ extension du coude et pronation/supination ou ouverture/ fermeture de la main). Les signaux EMG de la prothèse sont recueillis au niveau du biceps et du triceps à l’aide d’électrodes de surface. Le contrôle des différents moteurs constituant la prothèse se fait par une commande proportionnelle à l’intensité de la contraction musculaire, ce qui permet au patient d’effectuer des mouvements lents ou rapides. La prothèse UTHA pèse environ 900 g, sans la main, et possède un avant-bras dont la longueur peut être raccourcie à 20 cm, ce qui fait d’elle une prothèse évolutive. Elle peut manipuler une charge de 1 kg et supporter une charge maximale de 22,7 kg avec le coude en flexion à 90°. La prothèse permet de réaliser le mouvement flexion/extension en un temps de 1,2 s avec une flexion complète de 135° et une extension complète de 0°. MOTION CONTROL a développé une interface informatique pour effectuer l’étalonnage du bras et facilité l’entrainement du patient handicapé.

Bras CINVESTAV-IPN

 

En 2009, le laboratoire de bioélectronique de CINVESTAV-IPN a développé une prothèse myoélectrique en plus d’une interface d’entrainement pour l’utilisateur.
La prothèse est constituée de 4 actionneurs linéaires montés en parallèle. Ces derniers ont été réalisés spécialement pour cette prothèse, car elle nécessitait des actionneurs linéaires rapides, légers et de haute efficacité. Les 4 actionneurs sont montés en une structure parallèle qui permet d’obtenir une prothèse à 4 degrés de liberté seulement au niveau du coude. En effet, elle permet de réaliser les mouvements de flexion et extension du coude, la pronation et la supination, la préhension ainsi que la rotation humérale. Il est important de noter que les mouvements de pronation et de supination sont effectués au niveau du coude et non au niveau du poignet comme la majorité des prothèses myoélectrique commerciales. Les signaux EMG sont recueillis à l’aide d’électrodes de surface au niveau du biceps et du triceps. Ces derniers sont traités à l’aide d’un réseau de neurones à ondelette développé par pour ensuite générer la commande.

Les dimensions de la prothèse correspondent à celles d’un bras humain adulte. La prothèse complète pèse 1,05 kg et peut manipuler des charges allant jusqu’à 2 kg. Elle intègre une batterie située avec le circuit électronique dans le coude tout en gardant la cavité libre pour recevoir le moignon du patient.
Le mécanisme parallèle de cette prothèse permet d’effectuer des mouvements d’amplitudes suffisantes offrant ainsi une mobilité suffisante pour effectuer les activités de la vie quotidienne (flexion : 115°, extension : 10°, pronation : 90°, supination : -90°, rotation interne de l’humérus : 45°, rotation externe de l’humérus : -45°) .

Bras Jaco

En 2006, la société canadienne KINOVA a conçu un bras robotique dénommé JACO. Ce bras pèse au total 5,7 kg, a un rayon d’action de 90 cm et peu porter une charge allant jusqu’à 1,5 kg lorsque le bras est en demi-extension et jusqu’à 1 kg lorsqu’il est en extension complète. Il est composé de 7 degrés de liberté lui permettant toutes les combinaisons de rotations et de translations dans l’espace. Il possède une main articulée de 3 doigts permettant la saisie de petits objets.
La particularité de ce bras réside dans le fait qu’il est adaptable à un fauteuil roulant motorisé afin d’aider les personnes à mobilité réduite à effectuer leurs actions de la vie quotidienne plus facilement. Le bras robotique permet la saisie d’objets ou d’ouvrir des portes de manière intuitive en n’utilisant qu’une manette de jeu électronique (joystick). Cependant les personnes n’ayant plus suffisamment d’activité musculaire dans les doigts ne peuvent pas profiter de ce progrès.
En 2013, pour répondre à cette demande, Alexandre JUMELINE a adapté l’utilisation du bras JACO aux personnes blessées médullaires en utilisant les signaux électromyographiques (EMG) de quatre muscles résiduels au niveau du cou et de l’épaule.
L’acquisition des signaux EMG a été faite avec des électrodes DELSYS filtrées et préamplifiée en temps-réel à 2 kHz. Les électrodes ont été placées sur quatre muscles présents chez les blessés médullaires de haut niveau : les deux trapèzes ainsi que les deux sterno-cléïdo mastoïdiens. L’énergie de TEAGER-KAISER (TKEO) est utilisée afin de déterminer si une activité musculaire est présente ou non. Chaque mouvement détecté est relié à une action du bras robotisé. Une calibration est effectuée pour chaque muscle afin de définir des seuils de détection personnalisés. Un système de filtrage prédictif en temps réel a été intégré afin d’augmenter la sensibilité du système.

 

Project Description

Problem Definition
le Problème consiste en la réalisation d'un dispositif qui permet d'effectuer les mouvements de flexion et d'extension à partir du signal EMG générer par les muscles. Pour se faire nous devons réaliser une dispositif qui permet d'effectuer l'acquisition d'un signal EMG de bonne qualité. En effet, ce signal représente l'un des signaux biologique les plus complexe à étudier, car il est très difficile de normaliser son acquisition, de plus, les performances finales du dispositif vont fortement dépendre la qualité de l'acquisition. A partir de ce signal nous devons déterminer des caractéristiques du signal EMG spécifiques à chacun des mouvements et pouvant ne permettre de faire la distinction entre eux. A partir de ces caractéristiques, nous pouvons automatiser la distinction entre les deux mouvements à l'aide d'un classifieur qui sera préalablement entrainé avec les caractéristiques déduites précédemment. Un fois le classifieur prêt à l'emploi, nous pouvons déduire un modèle qui sera par la suite implémenter sur un microcontrôleur et obtenir à la fin un dispositif autonome.
Challenges & Motivation
On dénombre dans le monde plus de 4 millions d’amputés. Prés de 30 % sont des amputés du membre supérieur. Ce chiffre augmente de 200 000 personnes chaque année. Vu le nombre de déficits fonctionnels et de problèmes psychologiques que peut engendrer une amputation, nous avons voulu mettre notre savoir au service de l’homme et contribué au développement d’une solution pour remédier à ce problème. Parmi ces solutions on retrouve la prothèse myoélectrique.
Real and Complete Usecases

Une prothèse myoélectrique est un dispositif mécanique automatisé dont la commande est le signal EMG, ce signal est un signal biologique de nature électrique généré au niveau des muscles et représentant l’activité globale de ces derniers. Dans une prothèse myoélectrique on retrouve différents éléments tel que :

  • Des capteur EMG qui vont permettre l’acquisition de l’activité globale du muscle;
  • Des moteurs fixés à la structure de la prothèse pour effectuer les différents mouvements;
  • Une unité de commande qui va traiter le signal reçu via les capteurs et commander par la suite les différents moteurs pour effectuer les mouvement;

Tout se dispositif est alimenté par un batterie afin de le rendre autonome. La figure suivante représente la structure générale d’une prothèse myoélectrique  :

Technical Description

1/Etudes  du signal EMG et des Recommandations SENIAM :

Comme indiqué dans le rapport (Chapitre 1), cette étude est une étape clé dans ce projet. En effet, elle a abouti à la détermination de la nature du signal EMG, de ses caractéristiques, afin de déterminer la meilleure façon d’en faire l’acquisition, de plus l’étude des recommandations SENIAM nous a fourni les éléments pour maximiser la qualité et normaliser l’acquisition du signal EMG.

2/ Acquisition du signal EMG :

Pour l’acquisition du signal EMG nous avons opté pour l’utilisation d’une carte d’acquisition Muscle Sensor V3. Cette dernière permet l’acquisition du signal EMG avec la configuration différentielle (2 électrodes actives pour l’acquisition du signal EMG et une électrode passive qui joue le rôle d’une électrode de référence), cette configuration présente l’intérêt de réduire le bruit en mode commun comparé à la configuration unipolaire. Dans un premier temps, le signal EMG est recueilli à l’aide des électrodes. Le signal EMG recueilli étant de très faible amplitude, il est amplifié via un premier étage d’amplification, cet étage est constitué d’un amplificateur d’instrumentation  dont le gain est réglé à 206. La sortie de l’amplificateur d’instrumentation est reliée directement à un étage redresseur qui va permettre de rendre positive la partie négative du signal EMG et d’obtenir à la sortie de cet étage un signal EMG rectifié. Le signal EMG rectifié et injecté dans un étage de filtrage qui joue le rôle d’un détecteur d’enveloppe qui va permettre de détecter à chaque instant la valeur maximale du signal EMG rectifié. Le signal EMG rectifié est filtré et par la suite amplifier via un amplificateur à gain réglable. la figure suivante représente le signal obtenu après exécution d’un mouvement de flexion puis d’extension : La figure suivante représente les différents étages de la carte d’acquisition Muscle Sensor V3 : 3/ Réalisation de la base de données :

Nous avons réalisé une base de données constituée de 120 signaux de flexions et d’extensions, chacun d’une durée d’une seconde avec une fréquence d’échantillonnage de 5000 Hz. Cette base de données a été découpé en 2 parties: une pour l’entrainement du classifieur (représentant 2/3 des signaux de la base de données),  et une autre pour le test des performances du classifieur (contenant le reste des signaux de la base de données). 4/ Extraction des caractéristiques et entrainement du classifieur :

Pour l’extraction des caractéristiques nous avons opté pour les caractéristiques temporelles suivantes :

  • IEMG (Integrated EMG);
  • MAV (Mean Absolute Value) ;
  • RMS (Root Mean Square);
  • ZC (Zero crossing);
  • WL (Waveform lenght);
  • AMP_MAX (Maximum Amplitude) ;

Ces dernières ont l’intérêt de ne pas être trop gourmandes en temps de calcul, ce sui est idéal pour notre application. Apres traitement via Matlab, nous avons déterminer que les caractéristiques les plus pertinentes étaient les suivantes :

  • IEMG (Integrated EMG);
  • MAV (Mean Absolute Value) ;
  • AMP_MAX (Maximum Amplitude) ;
  • WL (Waveform lenght);

Nous sommes par la suite passés à l’étape dédiée à l’entrainement du classifieur. le classifieur utilisé est les SVM (Support Verctor Machines). Ce type de classifieur présente l’intérêt d’être simple d’utilisation et non gourmand en temps de calcul. Nous avons entrainé ce classifieur avec les caractéristiques précédentes ou la caractéristique WL a permis d’obtenir une précision de 80,3125 %, dans le but d’améliorer les performances nous avons effectué un entrainement avec un combinaison de caractéristiques ou la combinaison WL + AMP_Max, nous a permis d’améliorer la précision à 83,1250 % ce qui représente une précision suffisante  pour notre application. par la suite nous avons déterminer sous MATLAB les coefficients du modèle qui sera implémenter sur le microcontrôleur.

5/Implémentation sur ARDUINO :

Pour l’implémentation sur microcontrôleur nous avons sélectionné la carte ARDUINO MEGA, la figure suivante représente l’organigramme utilisé pour l’implémentation  du code ARDUINO : Après avoir entré les différents paramètres du modèle SVM, la première opération consiste à faire l’acquisition d’un segment de 250 ms du signal EMG et cela à travers une des entrées analogiques de la carte ARDUINO. Les échantillons constituant ce segment seront comparés les uns aux autres dans le but de déterminer l’amplitude maximale du signal EMG contenue dans ce segment, puis le paramètre WL est, par la suite, calculé. L’étape suivante consiste au calcul de la valeur de WL-droite. à partir du modèle SVM déterminé précédemment. Ce calcul va permettre de comparer et de déterminer si la valeur de WL calculée pour un segment est supérieure ou inférieure à la valeur de WL-droite calculée à partir de l’équation de l’hyperplan. En d’autres termes, cela va permettre de déterminer si la valeur de WL du segment est au-dessus ou en-dessous de l’hyperplan séparateur. Le résultat de cette comparaison va permettre de classer le mouvement, tel que si WL < WL-droite, le mouvement est une extension, sinon le mouvement est une flexion. L’étape finale consiste à commander le servomoteur afin d’effectuer le mouvement correspondant à la classe du segment traité. 

6/ Programme Arduino : 

La première partie du programme est dédiée à la déclaration et à l’initialisation des variables utilisées pour les différents calculs. Cette partie contient:

  • l’inclusion de la librairie dédiée au servomoteur;
  • l’initialisation de l’objet servo;
  • la configuration du servomoteur (pin, durées des impulsions dédiées au positionnement du servomoteur);
  • la déclaration et l’initialisation de la variable dédiée au stockage du segment;
  • la déclaration et l’initialisation de la variable dédiée au calcul de la caractéristique WL, du paramètre WL_droite, et de la caractéristique AMP_MAX;
  • l’initialisation des coefficients de la droite de séparation (coefficients de l’hyperplan).

La seconde partie du programme représente une boucle où, les différents paramètres sont calculés et où est opérée la classification. A chaque début de la boucle un segment est acquis à travers l’entrée analogique de la carte à une fréquence d’échantillonnage de 5 000 Hz et est stocké dans la variable dédiée. Les caractéristiques AMP_MAX et WL sont par la suite calculées et enregistrées. A partir de l’équation de l’hyperplan séparateur le paramètre WL_droite est déterminé. L’étape suivante consiste à comparer la valeur de WL_droite avec celle de WL afin de déterminer la classe du segment. La classe étant définie, l’opération finale consiste à commander le moteur afin d’exécuter le mouvement correspondant à la classe.

Il est à noter que la vitesse de rotation du moteur peut être modifiée en ajustant la durée des délais.

Hardware

Materials
ImageNamePart NumberPriceCountLink
Muscle Sensor V3xxxx31,79 euros 1🛒
Arduino Mega 2560xxxx42,00 euros 1🛒
Piles 9V xxxx1,78euros4🛒
Servo-moteurxxxx17,00 euros 1🛒
Electrodes EMG de surfacexxxx20,00 euros20🛒
Câble pour Carte arduino xxxx4 euros 1🛒
kit électronique xxxx7,99 euros 1🛒
Schematic

Software

Arduino Code

clear all
close all
clc
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARTIE DEDIEE A LA BASE D'ENTRAINEMENT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Extraction de siganux contenus dans BASE_X_ENTRAINEMENT2 pour former un tableau 25000*80: 
% (chaque colonne représente un signal, chaque ligne représente un échantillons d'un signal)
x=1;
for z=1:80 % représente le nombre de signaux contenus dans BASE_X_ENTRAINEMENT2
    for y=1:25000 % 25000 représente le nombre d'échantillons contenus dans chaque signal
        signal(y,z)= BASE_X_ENTRAINEMENT2(x,1);
        x=x+1;
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Extraction de la flexion et extension de chaque signal :
for z=1:80;
    for y=1:25000;
        if (y>4999 && y<10000);
            flexion1(y,z)=signal(y,z);
        else flexion1(y,z)=0;
        end
         if (y>14999 && y<20000);
            extension1(y,z)=signal(y,z);
        else extension1(y,z)=0;
         end
        if (y>20000 && y<25000);
            bruit1(y,z)=signal(y,z);
        else bruit1(y,z)=0;
        end
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Decalage des signaux flexion1 et extension1 pour former des signaux de 25000 échantillons :
b=5000;
c=15000;
d=20000;
for z=1:80
    for a=1:5000
        flexion2(a,z)=flexion1(b,z);
        b=b+1;
        extension2(a,z)=extension1(c,z);
        c=c+1;
        bruit2(a,z)=bruit1(d,z);
        d=d+1;
    end
    b=5000;
    c=15000;
    d=20000;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Découpage des signaux flexion2 et extension2 en segments de 250 ms: 
b=0;
d=1;
for c=1:320   % *********** 320 = 80 * nombre de segment dans une seconde 
    for a=1:1250 % ********1250 = 5000 / nombre de segment dans une seconde 
         b=b+1;
        flexion3(a,c)=flexion2(b,d);
        extension3(a,c)=extension2(b,d);
    end 
    if b==5000
        b=0;
        d=d+1;   
    end
end 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Extraction des caractéristiques à partor de la base d'entrainement  :

% (IEMG,WL,MAV,RMS,SSI,SSC,ZC,VAR,AMP_MAX,ECART_TYPE)  

WL_flexion3=zeros(1,320); %***************320= 80 * nombre de segment dans une seconde 
WL_flexion3=WL_flexion3';
WL_extension3=zeros(1,320); %***************320= 80 * nombre de segment dans une seconde 
WL_extension3=WL_extension3';

ZC_flex=0;
ZC_ext=0;

c=0;
d=0;

for a=1:320 %***************320= 80 * nombre de segment dans une seconde 
        IEMG_flexion3(a)=sum(abs(flexion3(:,a)));
        IEMG_extension3(a)=sum(abs(extension3(:,a)));
        
        MAV_flexion3(a) = mean(abs(flexion3(:,a)));
        MAV_extension3(a) = mean(abs(extension3(:,a)));
        
        RMS_flexion3(a) =sqrt(mean(flexion3(:,a).^2));
        RMS_extension3(a) =sqrt(mean(extension3(:,a).^2));
        
        SSI_flexion3(a)=sum(abs(flexion3(:,a).^2));
        SSI_extension3(a)=sum(abs(extension3(:,a).^2));
        
    for b=1:1249 %***************** 1249= (5000 / nombre de segment dans une seconde) - 1
        
        WL_flexion3(a)=WL_flexion3(a)+ abs(flexion3(b+1,a)-flexion3(b,a));
        WL_extension3(a)=WL_extension3(a)+abs(extension3(b+1,a)-extension3(b,a));
        
        if((flexion3(b,a)>0 && flexion3(b+1,a)<0) || (flexion3(b,a)<0 && ...
                 flexion3(b+1,a) > 0))
            ZC_flex=ZC_flex+1;
        end
         
         if((extension3(b,a)>0 && extension3(b+1,a)<0) || (extension3(b,a)<0 && ... 
                extension3(b+1,a)> 0))
            ZC_ext=ZC_ext+1;
         end 
        
    end
    
    for b=2:1249 %***************** 1249= (5000 / nombre de segment dans une seconde) - 1
        
         if (flexion3(b,a)flexion3(b+1,a) && flexion3(b,a)>flexion3(b-1,a))
         c=c+1;
        end  
        if (extension3(b,a)extension3(b+1,a) && extension3(b,a)>extension3(b-1,a))
         d=d+1;
        end  
    end
        ZC_flexion(a,1)=ZC_flex;
        ZC_flex=0;
        ZC_extension(a,1)=ZC_ext;
        ZC_ext=0; 
        
        SSC_flexion3(a)=c;
        SSC_extension3(a)=d;
        c=0;
        d=0;
end     

IEMG_flexion=IEMG_flexion3';
IEMG_extension=IEMG_extension3';

MAV_flexion =MAV_flexion3'; 
MAV_extension=MAV_extension3';

RMS_flexion=RMS_flexion3';
RMS_extension=RMS_extension3';

WL_flexion= WL_flexion3;
WL_extension= WL_extension3;

AMP_MAX_flexion3=max(abs(flexion3(:,:)));
AMP_MAX_extension3=max(abs(extension3(:,:)));
AMP_MAX_flexion=AMP_MAX_flexion3';
AMP_MAX_extension=AMP_MAX_extension3';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Evaluations de la pertinence des caractéristiques en utilisant le boxplot:

IEMG=[IEMG_extension IEMG_flexion];
MAV=[MAV_extension MAV_flexion];
RMS=[RMS_extension RMS_flexion];
ZC=[ZC_extension ZC_flexion];
WL=[WL_extension WL_flexion];
VAR=[VAR_extension VAR_flexion];
SSC=[SSC_extension SSC_flexion];
AMP_MAX=[AMP_MAX_extension AMP_MAX_flexion]; 
ECART_TYPE=[ECART_TYPE_extension ECART_TYPE_flexion];
SSI=[SSI_extension SSI_flexion];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
boxplot(IEMG)
title('IEMG')
figure
boxplot(MAV)
title('MAV')
figure
boxplot(RMS)
title('RMS')
figure
boxplot(ZC)
title('ZC')
figure
boxplot(WL)
title('WL')
figure
boxplot(VAR)
title('VAR')
figure
title('SSC')
figure
boxplot(AMP_MAX)
title('AMP_MAX')
figure
boxplot(ECART_TYPE)
title('ECART_TYPE')
figure
boxplot(SSI)
title('SSI')

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FIN DE LA PARTIE DEDIEE A LA BASE D'ENTRAINEMENT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARTIE DEDIEE A LA BASE DE TEST %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%Extraction des mouvements flexion et extension de la base de donneés BASE_X_TEST2: 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
x=1;
    for z=1:40 % représente le nombre de signaux contenus dans BASE_X_TEST2
        for y=1:25000 % 25000 représente le nombre d'échantillons contenus dans chaque signal
            signal_test(y,z)=BASE_X_TEST2(x,1);% 
            x=x+1;
        end
    end

% Extraction de la flexion et extension de chaque signal :
for z=1:40;
    for y=1:25000;
        if (y>4999 && y<10000);
            flexion1_test(y,z)=signal_test(y,z);
        else flexion1_test(y,z)=0;
        end
         if (y>14999 && y<20000);
            extension1_test(y,z)=signal_test(y,z);
        else extension1_test(y,z)=0;
        end
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
b=5000;
c=15000;
for z=1:40
    for a=1:5000
        flexion2_test(a,z)=flexion1_test(b,z);
        b=b+1;
        extension2_test(a,z)=extension1_test(c,z);
        c=c+1;
    end
    b=5000;
    c=15000;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
b=0;
d=1;
for c=1:160 %********* 160 = 40* nombre de segment dans une seconde
    for a=1:1250 %*********1250 = 5000 / nombre de segment dans une seconde 
         b=b+1;
        flexion3_test(a,c)=flexion2_test(b,d);
        extension3_test(a,c)=extension2_test(b,d);
    end 
    if b==5000
        b=0;
        d=d+1;   
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Extraction des caractéristiques à partir de la base dde test :

WL_flexion3_test=zeros(1,160);%*************** 160 = 40* nombre de segment dans une seconde
WL_flexion3_test=WL_flexion3_test';
WL_extension3_test=zeros(1,160);%*************** 160 = 40* nombre de segment dans une seconde
WL_extension3_test=WL_extension3_test';

c=0;
d=0;

for a=1:160%*************** 160 = 40* nombre de segment dans une seconde
    
        IEMG_flexion3_test(a)=sum(abs(flexion3_test(:,a)));
        IEMG_extension3_test(a)=sum(abs(extension3_test(:,a)));  
        MAV_flexion3_test(a) = mean(abs(flexion3_test(:,a)));
        MAV_extension3_test(a) = mean(abs(extension3_test(:,a)));
        
    for b=1:1249%***************** 1250 = (5000 / nombre de segment dans une seconde) - 1
        
        WL_flexion3_test(a)=WL_flexion3_test(a)+ abs(flexion3_test(b+1,a)-flexion3_test(b,a));
        WL_extension3_test(a)=WL_extension3_test(a)+abs(extension3_test(b+1,a)-extension3_test(b,a));
       
    end
    
     for b=2:1249 %***************** 1249= (5000 / nombre de segment dans une seconde) - 1
        
         if (flexion3_test(b,a)flexion3_test(b+1,a) && flexion3_test(b,a)>flexion3_test(b-1,a))
         c=c+1;
        end  
        if (extension3_test(b,a)extension3_test(b+1,a) && extension3_test(b,a)>extension3_test(b-1,a))
         d=d+1;
        end  
    end
        SSC_flexion3_test(a)=c;
        SSC_extension3_test(a)=d;
        c=0;
        d=0;
end    

IEMG_flexion_test=IEMG_flexion3_test';
IEMG_extension_test=IEMG_extension3_test';

MAV_flexion_test =MAV_flexion3_test'; 
MAV_extension_test=MAV_extension3_test';

WL_flexion_test= WL_flexion3_test;
WL_extension_test= WL_extension3_test;

AMP_MAX_flexion3_test=max(abs(flexion3_test(:,:)));
AMP_MAX_extension3_test=max(abs(extension3_test(:,:)));
AMP_MAX_flexion_test=AMP_MAX_flexion3_test';
AMP_MAX_extension_test=AMP_MAX_extension3_test';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FIN DE LA PARTIE DEDIEE A LA BASE DE TEST %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PARTIE DEDIEE A L'ENTRAINEMENT/TEST DU CLASSIFIEUR %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Cration des classes :
for i=1:320%**************** 320 = 80 * nombre de segment dans une seconde 
    Y(i,1)=-1; %(-1) représente la classe extension
end
for i=321:640%************** 640 = 80 * nombre de segment dans une seconde * 2
    Y(i,1)=1; %(1) représente la classe flexion
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 1) entrainement  :
% WL : 
X1=[WL_extension;WL_flexion]; 
SVM1=fitcsvm(X1,Y);
% MAV : 
X2=[MAV_extension;MAV_flexion];
SVM2=fitcsvm(X2,Y);
% IEMG : 
X3=[IEMG_extension;IEMG_flexion];
SVM3=fitcsvm(X3,Y);
% AMP_MAX : 
X4=[AMP_MAX_extension;AMP_MAX_flexion];
SVM4=fitcsvm(X4,Y);
% WL+IEMG : 
X5=[WL_extension IEMG_extension;WL_flexion IEMG_flexion];
SVM5=fitcsvm(X5,Y);
%WL+MAV : 
X6=[WL_extension MAV_extension;WL_flexion MAV_flexion];
SVM5=fitcsvm(X6,Y);
%WL+AMP_MAX : 
X7=[WL_extension AMP_MAX_extension;WL_flexion WL_flexion];
SVM5=fitcsvm(X7,Y);
% %WL+AMP_MAX +  IEMG : 
X8=[WL_extension AMP_MAX_extension IEMG_extension;WL_flexion WL_flexion IEMG_flexion];
SVM8=fitcsvm(X8,Y);
 %WL+AMP_MAX +MAV : 
X9=[WL_extension AMP_MAX_extension MAV_extension;WL_flexion WL_flexion MAV_flexion];
SVM9=fitcsvm(X9,Y);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 2) test : 
% WL :
X1_test=[WL_extension_test;WL_flexion_test];
label1= predict(SVM1,X1_test);
% MAV :
X2_test=[MAV_extension_test;MAV_flexion_test];
label2= predict(SVM2,X2_test);
% IEMG :
X3_test=[IEMG_extension_test;IEMG_flexion_test];
label3= predict(SVM3,X3_test);
% AMP_MAX :
X4_test=[AMP_MAX_extension_test;AMP_MAX_flexion_test];
label4= predict(SVM4,X4_test);
% WL+IEMG : 
X5_test=[WL_extension_test IEMG_extension;WL_flexion_test IEMG_flexion_test];
label1= predict(SVM5,X5_test);
%WL+MAV : 
X6_test=[WL_extension_test MAV_extension_test;WL_flexion_test MAV_flexion_test];
label6= predict(SVM6,X6_test);
%WL+ AMP_MAX :
X7_test=[WL_extension_test AMP_MAX_extension_test;WL_flexion_test AMP_MAX_extension_test];
label7= predict(SVM7,X7_test);
% 
X8_test=[WL_extension_test AMP_MAX_extension_test IEMG_extension_test ;WL_flexion_test AMP_MAX_extension_test IEMG_flexion_test];
label8= predict(SVM8,X8_test);
% 
X9_test=[WL_extension_test AMP_MAX_extension_test MAV_extension_test;WL_flexion_test AMP_MAX_extension_test MAV_flexion_test];
label9= predict(SVM9,X9_test);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 3) Calcul de la précision :

TP1=0; 
TP2=0; 
TP3=0; 
TP4=0; 
TP5=0; 
TP7=0; 
TP8=0;
TP9=0;

for i=1:160  %**************** 160 = 360 / 2 = (80 * nombre de segment dans une seconde) / 2
    if label1(i,1)==-1
        TP1=TP1+1;
    end
    
    if label2(i,1)==-1
        TP2=TP2+1;
    end
    
    if label3(i,1)==-1
        TP3=TP3+1;
    end
    
    if label4(i,1)==-1
        TP4=TP4+1;
    end
    
    if label5(i,1)==-1
        TP5=TP5+1;
    end
    if label7(i,1)==-1
        TP7=TP7+1;
    end
     if label8(i,1)==-1
        TP8=TP8+1;
     end
     if label9(i,1)==-1
        TP9=TP9+1;
    end
end
for i=161:320 %************* 320 = 80 * nombre de segment dans une seconde 
    
    if label1(i,1)==1
        TP1=TP1+1;
    end
    
     if label2(i,1)==1
        TP2=TP2+1;
     end
     
     if label3(i,1)==1
        TP3=TP3+1;
     end
     
     if label4(i,1)==1
        TP4=TP4+1;
     end
     
     if label5(i,1)==1
        TP5=TP5+1;
     end
     
     if label7(i,1)==1
        TP7=TP7+1;
     end
     if label8(i,1)==1
        TP8=TP8+1;
     end
     if label9(i,1)==1
        TP9=TP9+1;
    end
end

p=[TP1;TP2;TP3;TP4;TP5;TP7];
precision = p*100/320 


//**********************************************************************************************************************************************************
#include  //librérie dédié au servomoteur
Servo monServo; // initialisation de l'objet servo 
//**********************************************************************************************************************************************************

// initialisation des variables :
  float lecture[1250];  // Tableau permettant de stocker un segment de 250 ms, soit 1250 échantillons pour une fréquence d'échantillonnage de 5000 Hz.
  float WL=0.0;         // Variable globale dédiée au calcul de la caractéristiques WL relative au segment.
  float AMP_MAX=0.0;    // Variable globale dédiée au calcul de la caractéristiques AMP_MAX relative au segment.
  int i=0;              // Indice.
  float WL_droite=0.0;  //Variable globale dédiée au calcul de WL-droite.
  
//**********************************************************************************************************************************************************

// Paramétres de l'hyperplan séparateur : 
  const float a=9.5232;    // pante de l'hyperplan séparateur.
  const float b=-15.9775;  // biais de l'hyperplan séparateur.
  
//**********************************************************************************************************************************************************

void setup() {
  
//initialisation du servomoteur (pin et durée de l'état haut des impulsions) : 
  monServo.attach(9,500,2500); 
}

void loop() {
  float WL=0.0;
  float AMP_MAX=0.0;
//***********************************************************************************************************************************************************

// Stockage du segment :
  for (i=0;i<1250;i++){
    lecture[i]=analogRead(A0)*5.0/1023.0; //Acquisition du segment sur l'entrée analogique A0.
    delayMicroseconds(89);                // le délais permet d'obtenir une fréquence d'achantillonnage de 5000 Hz
  }
  
//***********************************************************************************************************************************************************

// Calcul de la caractéristiques AMP_MAX : 
  for(i=199;i<1250;i++){
    if (abs(lecture[i])>=AMP_MAX){
      AMP_MAX=abs(lecture[i]);
      }
    }
    
//************************************************************************************************************************************************************

// Calcul de la caractéristiques WL :
  for(i=199;i<1249;i++){
    WL=WL+abs(lecture[i+1]-lecture[i]);
    }
    
//************************************************************************************************************************************************************

// Calcul de WL_droite :
   WL_droite=a*AMP_MAX+b;
   
//************************************************************************************************************************************************************

// Comparaison et classification du mouvement :  
  if (WL_droite>WL){
    for(int k=120;k>=0;k--){
      monServo.write(k);
      delay(20);
      }
    }  
  else {
    for(int k=0;k<=120;k++){
      monServo.write(k);
      delay(20);
      } 
    }
 }
 
//**********************************************************************************************************************************

External Services

xxxx

xxxx