Rapport final - uqac.ca

151
1 Université du Québec à Chicoutimi Module d’ingénierie Programme : Génie électrique. Projet de synthèse en ingénierie 6GIN555 Rapport final Projet d’amélioration de l’outil de réadaptation A.M.E. Présenté par : Frédérick Morin Benoît Côté Pour : Martin Gravel C.E.M.E. Le 23 avril 2010 Coordonnateur : Jacques Paradis Conseiller : Hung Tien Bui

Transcript of Rapport final - uqac.ca

Page 1: Rapport final - uqac.ca

1

Université du Québec à Chicoutimi Module d’ingénierie

Programme : Génie électrique.

Projet de synthèse en ingénierie 6GIN555

Rapport final

Projet d’amélioration de l’outil de réadaptation A.M.E.

Présenté par :

Frédérick Morin

Benoît Côté

Pour :

Martin Gravel C.E.M.E.

Le 23 avril 2010

Coordonnateur : Jacques Paradis

Conseiller : Hung Tien Bui

Page 2: Rapport final - uqac.ca

2

Table des matières I. Introduction ................................................................................................................. 6

II. Présentation du projet ................................................................................................. 7

II.1 Description de l’entreprise .................................................................................. 7

II.2 Description de l’équipe de travail ....................................................................... 8

II.3 Problématique et état de l’art relié au projet ....................................................... 9

II.4 Objectifs généraux et spécifiques du projet ........................................................ 9

III. Aspects techniques et éléments de conception relatifs au projet .............................. 10

III.1. Méthodologie utilisée .............................................................................. 10

III.2. Éléments de conception ........................................................................... 14

III.2.a. Acquisition de données....................................................................... 14

III.2.b. Cellule de charge ................................................................................ 14

III.2.c. SPI logiciel ......................................................................................... 21

� Fonction d’initialisation du port SPI 2 ................................................ 22

� Fonction d’envoi du port SPI 2............................................................ 23

� Fonction de réception du port SPI 2 .................................................... 24

III.2.d. Capteur EMG ..................................................................................... 26

III.2.e. Routine de communication avec le variateur de vitesse ..................... 31

� Configuration ....................................................................................... 31

� Architecture de la transmission de donnée .......................................... 32

� Validation des données ........................................................................ 34

� Conversion et traitement de la valeur reçue ou envoyée ..................... 35

Approbation du rapport final pour diffusion

Nom du conseiller : Hung Tien Bui ing.

Date : 23 avril 2010

Signature :

Page 3: Rapport final - uqac.ca

3

� Résumé des étapes d’envoi .................................................................. 36

� Architecture de la réception de donnée ............................................... 36

� Résumé des étapes d’envoi .................................................................. 36

� Gestion des erreurs de commande ....................................................... 37

III.2.f. Architecture du programme ................................................................ 38

� Initialisation et étapes préliminaires à l’utilisation .............................. 38

� Routine d’asservissement en fonctionnement normal ......................... 43

III.2.g. Interface d’opération .......................................................................... 46

IV. Bilan des activités ..................................................................................................... 53

IV.1 Arrimage formation pratique/universitaire ................................................... 53

IV.2 Travail d’équipe ............................................................................................ 55

IV.3 Respect de l’échéancier................................................................................. 56

IV.4 Analyse et discussion .................................................................................... 58

V. Conclusion et recommandations ............................................................................... 60

VI. Bibliographie............................................................................................................. 62

Annexe A : Nouvelle approche ......................................................................................... 66

Annexe B : Plans électriques ............................................................................................ 69

Annexe C : Programmation

Page 4: Rapport final - uqac.ca

4

Liste des figures :

Figure 1 : Circuit de développement MicroChip .............................................................. 11

Figure 2 : Amplificateur Myoscan branché sur une triode. .............................................. 12

Figure 3 : Logique du programme .................................................................................... 13

Figure 4 : Localisation de la cellule de charge.................................................................. 14

Figure 5 : Cellule de charge et sa configuration ............................................................... 15

Figure 6 : Représentation du système de forces de l’appareil........................................... 16

Figure 7 : Représentation de la puce électronique de conversion AD7798 ...................... 18

Figure 8 : Représentation de la séquence de transfert de l’AD7798................................. 19

Figure 9 : Schématisation de la configuration du convertisseur de la cellule ................... 21

Figure 10 : Initialisation du port SPI 2.............................................................................. 22

Figure 11 : Structure du temporisateur 1 du dsPIC30f4011 ............................................. 23

Figure 12 : Fonction d’envoi du port SPI 2 ...................................................................... 23

Figure 13 : Fonction de réception du port SPI 2 ............................................................... 24

Figure 14 : Triode musculaire ........................................................................................... 26

Figure 15 : Amplificateur RMS et son signal de sortie .................................................... 26

Figure 16 : Configuration des deux registres nécessaires à la communication série SPI . 28

Figure 17 : Séquence à suivre pour une conversion et un transfert adéquat ..................... 28

Figure 18 : Schématisation du branchement entre le microcontrôleur et l’AD7680 ........ 29

Figure 19 : Séquence de conversion des données provenant de l’AD7680 ...................... 30

Figure 20 : Identification du port de communication série sur le variateur de vitesse ..... 31

Figure 21 : Routine de contrôle principale ....................................................................... 38

Figure 22 : Séquence d’initialisation du microcontrôleur................................................. 39

Figure 23 : Séquence d’initialisation de la machine ......................................................... 40

Figure 24: Séquence de réception des consignes provenant de l’interface de contrôle. ... 41

Figure 25: Séquence de positionnement du bras à l’angle initial ..................................... 42

Figure 26: Séquence d’asservissement de la vitesse du moteur. ...................................... 43

Figure 27: Interface d’opération. ...................................................................................... 46

Figure 28: Boucle de l’interface d’opération. ................................................................... 47

Figure 29: Consigne d’angle initial de l’interface. ........................................................... 48

Figure 30: Consigne de charge. ........................................................................................ 48

Page 5: Rapport final - uqac.ca

5

Figure 31: Consigne de l’EMG et valeur isométrique. ..................................................... 49

Figure 32: Control de l’entraînement. ............................................................................... 49

Figure 33: Affichage du graphique de l’EMG. ................................................................. 51

Figure 34: Affichage du graphique de l’EMG à partir du fichier Entraînement.xls ......... 51

Figure 35: Paramètre du port RS-232 et remise à zéro ..................................................... 52

Figure 36: Affichage des valeurs reçues et converties en temps réel. .............................. 52

Figure 37 : Diagramme de Gantt de la planification du projet ......................................... 56

Figure 38 : Schéma du bras de A.M.E. avec la force appliquée ....................................... 66

Liste des tableaux :

Tableau 1: Configuration du port série ............................................................................. 31

Tableau 2: Valeur décimale de certains caractères ASCII................................................ 34

Tableau 3 : Comparaison du prix des équipements .......................................................... 59

Page 6: Rapport final - uqac.ca

6

I. Introduction

L’équipe du Centre d’Ergonomie et de Mieux Être (C.E.M.E) s’apprête à

commercialiser A.M.E. (appareil multifonctionnel d’entraînement), un

équipement d’entraînement révolutionnaire permettant d’accélérer la

réhabilitation des personnes blessées au travail. Il existe présentement un

prototype de l’appareil qui a servi à démontrer et valider avec succès le

fonctionnement de celui-ci.

Avant de commercialiser A.M.E., plusieurs parties de l’appareil doivent être

améliorées afin d’augmenter les performances et diminuer les coûts de

production. En effet, le prototype est très efficace pour la réhabilitation, mais si

l’équipement est soumis à des mouvements rapides, pour l’entraînement en force

par exemple, l’efficacité de l’appareil diminue. De plus, le système permettant le

contrôle de l’équipement est très coûteux et donc pourrait limiter la clientèle pour

cet équipement. De façon générale, le but du projet est donc de réduire les coûts

de production de l’équipement ainsi que d’améliorer ses performances en termes

de temps de réaction.

Page 7: Rapport final - uqac.ca

7

II. Présentation du projet

II.1 Description de l’entreprise

CEME intervient dans les problématiques liées à la santé et la sécurité au travail

de la main-d’œuvre, et ce, dans tous les secteurs de l'activité économique.

Adoptant une approche multidisciplinaire, globale et intégrée face aux

problématiques qui lui sont présentées, leurs consultants s'appuient sur les toutes

nouvelles technologies et leur vaste expérience du milieu de travail pour identifier

les situations à risque et pour concevoir les correctifs à apporter.

Selon la nature et la complexité des problématiques rencontrées, CEME peut faire

appel à l'une ou l'autre, ou encore à plusieurs des expertises suivantes :

ergonomes, éducateurs physiques, ergothérapeutes, kinésiologues,

physiothérapeutes, médecins, ingénieurs, designers industriels, etc. 1

1 http://www.ceme.qc.ca/Questceque.htm

Page 8: Rapport final - uqac.ca

8

II.2 Description de l’équipe de travail

� Équipe de travail :

Benoît Côté,

Frédérick Morin

� Support technique externe :

Le Centre de Production Automatisé (CPA)

� Support technique interne :

Richard Martin

Francis Deschenes

� Superviseur (conseiller) :

Hung-Tien Bui

� Promoteur :

Martin Gravel (Président de la compagnie C.E.M.E.)

Page 9: Rapport final - uqac.ca

9

II.3 Problématique et état de l’art relié au projet

L’appareil multifonctionnel d’entraînement a été conçu pour la réadaptation

physique. Cet appareil doit donc être performant, mais, surtout fiable et

sécuritaire afin de ne pas aggraver l’état de l’utilisateur.

Il existe un équipement qui peut se comparer en partie avec A.M.E. Cet

équipement, Ikarus de la compagnie BFMC, permet l’entraînement et la

réhabilitation des membres supérieurs avec une rétroaction sur la charge.

Là où A.M.E. révolutionne ce type d’équipement, c’est dans la rétroaction

musculaire. La rétroaction au niveau de la charge permet de simuler la charge

voulue et la rétroaction musculaire permet d’ajuster la charge en fonction du seuil

de tolérance maximal du patient. De cette façon, le patient peut compléter un

mouvement sans surpasser l’effort que le muscle peut fournir et par le fait même

éviter de rallonger le temps de réadaptation du muscle.

II.4 Objectifs généraux et spécifiques du projet

L’objectif principal du projet était de faire la démonstration que le contrôle du

système pouvait être pris en charge par un microcontrôleur. Il s’agissait, en autre,

de réviser l’asservissement des moteurs simulant la charge, les systèmes

d’acquisitions de données et de calculs qui se font actuellement sur automate et

ordinateur. De plus, les modifications devaient favoriser la mise en marché du

produit et permettre son adaptation pour différentes applications futures.

Page 10: Rapport final - uqac.ca

10

III. Aspects techniques et éléments de conception relatifs au

projet

III.1. Méthodologie utilisée

Il a été déterminé que le variateur de vitesse du moteur actuel serait conservé pour

le contrôle de la vitesse et l’asservissement de celui-ci. La communication entre le

variateur et le système de contrôle s’effectuerait à l’aide d’une communication

série RS-232. La facilité d’utilisation de ce protocole de communication a

fortement influencé la décision du protocole à utiliser. Il a été déterminé que, pour

l’affectation présente du variateur, la vitesse de communication série serait

suffisante. En effet, la vitesse de communication du port série est de 38400 bauds.

Pour réaliser l’asservissement de la machine, une chaîne de caractères de 368 à

592 bits doit être envoyée au variateur de vitesse. Donc, il est possible d’affirmer

que le rafraîchissement de l’asservissement pourra se faire entre 50 et 103 fois par

seconde. Avec cette vitesse de communication, est possible d’obtenir des

performances équivalentes à celles du prototype déjà en fonction.

Le contrôleur utilisé pour le traitement des données et le contrôle de l’équipement

sera une carte électronique de développement ayant comme unité de traitement un

microcontrôleur DSPic (Microchip). La carte de développement possède déjà des

entrées/sorties numériques et analogiques, des entrées/sorties pour différents

protocoles de communication dont ceux nécessaires au bon fonctionnement du

système et un afficheur LCD.

Page 11: Rapport final - uqac.ca

11

Figure 1 : Circuit de développement MicroChip

Pour communiquer avec les composantes externes du système, deux circuits

contenant des convertisseurs analogiques à numérique ont été développés pour

transférer les signaux analogiques provenant de la cellule de charge et du capteur

électromyogramme (EMG). Ces interfaces communiquent via un port série SPI et

possèdent des convertisseurs analogiques à numérique choisis spécialement pour

chacune des deux applications.

Pour l’acquisition des signaux électriques provenant du système musculaire

humain, un amplificateur conçu par une compagnie spécialisée dans la fabrication

d’équipements biomédicaux sera mis à l’essai et utilisé sur le nouveau prototype.

Cet amplificateur se branche directement sur la triode qui est collée sur le bras du

patient (figure 2). Le signal de sortie de cet amplificateur est une valeur

analogique efficace amplifiée du signal envoyé par le corps humain lors d’une

contraction musculaire.

Page 12: Rapport final - uqac.ca

12

Figure 2 : Amplificateur Myoscan branché sur une triode.

Trois routines de communication ont été développées pour les deux protocoles

séries utilisés. La première routine utilise le module SPI intégré du

microcontrôleur et permet de transférer les données du convertisseur analogique à

numérique du EMG. La deuxième routine de communication est un port SPI

émulé permettant cette fois d’obtenir les valeurs provenant du convertisseur de la

cellule de charge. Une troisième routine utilisant le module de communication

RS-232 du circuit de développement permet de transmettre les consignes et de

recevoir les valeurs du variateur de vitesse. Les liens entre les différents modules

sont présentés à la figure 3

Un autre segment de programmation a été réalisé pour permettre la

communication entre le microcontrôleur et l’interface graphique de l’ordinateur.

Le module intégré de communication du dsPIC sera utilisé pour l’envoi et la

réception des informations. Un module de communication UART/USB permet de

faire le lien entre le microcontrôleur et l’ordinateur.

Par la suite, pour le contrôle de la charge, une routine d’asservissement de vitesse

des moteurs a été conçue. Cette routine permet un contrôle de vitesse en fonction

de la charge perçu sur la poignée. Cette routine permet aussi un ajustement de

consigne de charge en fonction des données recueillies par l’EMG.

Page 13: Rapport final - uqac.ca

13

Il est aussi important de mentionner que beaucoup d’envois de données vers

l’interface de contrôle sont faits dans l’asservissement. Donc toutes les données

converties et recueillies sont traitées dans cette routine.

Figure 3 : Logique du programme

Le dernier segment de programmation développé a été la routine principale. Cette

routine est simple et permet au système de s’initialiser et de prendre sa position de

départ, initialement entrée dans l’interface de contrôle. Elle permet aussi de faire

appel, de manière séquentielle, aux nombreuses routines précédemment

développées, c'est-à-dire les conversions et les traitements de données.

Finalement, des essais ont été faits sur l’équipement pour implanter et valider tous

les systèmes développés lors du projet. Ces essais ont permis d’optimiser le

fonctionnement et atteindre au maximum les objectifs fixés lors de l’élaboration

du plan de travail.

Page 14: Rapport final - uqac.ca

14

III.2. Éléments de conception

III.2.a. Acquisition de données

Toutes les données externes nécessaires au fonctionnement de l’appareil de

réadaptation sont de types analogiques. Le microcontrôleur possède des entrées

analogiques à digitale, mais pour des raisons de précision, ceux-ci n’ont pas été

utilisés. Il a donc été nécessaire de concevoir des interfaces d’acquisitions qui

convertissent les signaux analogiques en numérique. Au total, deux interfaces

utilisant chacune des composantes de conversion spécifiques ont été conçues.

III.2.b. Cellule de charge

La première interface sert à la conversion des signaux de la cellule de charge. La

cellule de charge est une composante du système servant à mesurer la force

appliquée sur le bras de l’appareil. Elle est fixée directement au bas du bras à

l’endroit où se trouvent les poignées. Le positionnement de la cellule permet donc

une lecture de la force appliquée sur le bras de l’appareil en temps réel.

Figure 4 : Localisation de la cellule de charge.

Page 15: Rapport final - uqac.ca

15

La cellule utilisée présentement sur l’équipement est composée de quatre jauges

de contraintes dans une configuration de pont de Wheatstone (figure 5) et possède

une capacité maximale de 30 KG. Le pont possède un facteur nominal de sortie de

2 mV/V par rapport à sa source d’alimentation qui est de 5Vcc. La plage de sortie

sera donc de -10 mV à +10 mV où -10 mV correspond à un poids de 30 KG dans

une direction et +10 mV correspond a 30 KG dans l’autre direction. Pour trouver

cette plage de sortie, il faut multiplier le facteur nominal de sortie par la tension

appliquée au pont. La tension de sortie du pont est donnée par la formule

suivante : 2

3 20

3 4 1 2

EX

R RV V

R R R R

= − •

+ +

Figure 5 : Cellule de charge et sa configuration

En se basant sur le facteur nominal de sortie, il est possible de déterminer la

relation qui existe entre la charge appliquée et la tension à la sortie. La cellule

donnera donc une différence de potentiel à la sortie de :

[ ]

[ ]0 _

2 5Facteur de sortie V

0.333Capacité de la Cellule 30

CCEX

KG

mVV

mVVV

KG KG

• •

= = =

2 ftp://ftp.ni.com/pub/branches/france/mesures_courantes_2.pdf

Page 16: Rapport final - uqac.ca

16

Il est nécessaire de convertir cette valeur représentant une tension pour chaque

kilogramme en tension pour une force équivalente à une masse statique de X

kilogrammes. Le but visé étant de simuler une masse de types poulie (figure 6), il

est donc nécessaire d’effectuer cette conversion afin d’obtenir la valeur voulue.

Comme il est démontré dans la figure suivante, la force à appliquer sur la cellule

sera l’équivalent de la force d’attraction terrestre appliquée sur une masse X. 3

Figure 6 : Représentation du système de forces de l’appareil.

Le gain actuel donne une relation entre une masse simulée et la tension de sortie

de la cellule de charge. Cependant, il est impossible de mesurer directement la

masse, et donc le système doit donc utiliser la force appliquée à la cellule de

charge pour en déduire une masse. Puisque la force est égale à (masse x

accélérations) et que l’accélération terrestre est de 9.81 m/s², il faut ensuite diviser

le potentiel aux bornes de la cellule de charge par 9.81. Cette valeur peut être

trouvée de la manière suivante :

Dû à la force d’attraction terrestre, la force générée par un poids sera de 9.81N/Kg

[ ]

( ) [ ]2 29.81 1 9.81 9.81gravitation

F mA N

m mA F Kg N

s s

=

= → = =

i

3 Mécanique de l’ingénieur : STATIQUE, Traduction et adaptation de Engineering Mechanics,

STATICS, Vol.1, 3e édition, version SI, par J.L. Meriam et L.G. Kraige

Page 17: Rapport final - uqac.ca

17

Puisque le système donne 0.33mV/Kg la tension de sortie sera 0.03398mV/ N de

force.

0_

0 _0_

_

0.3333

0.33330.03398

9.81

KG

KGN

PAR KILO

mVV

KG

mVV mVKG

VNF N

KG

=

= = =

C’est avec le signal de sortie de la cellule de charge qu’il sera possible de donner

une consigne de vitesse au moteur pour le maintien de la force simulée.

Cependant, puisque le signal de sortie de la cellule de charge est analogique et que

le microcontrôleur effectue un traitement de type numérique, une interface a été

créée incluant un convertisseur analogique à numérique. Ce convertisseur a été

choisi en fonction de la tâche à accomplir. En effet, après plusieurs recherches, le

choix s’est arrêté sur un convertisseur fabriqué par la compagnie Analog Device

qui possède les caractéristiques voulues. 4 Ce circuit permet une conversion de

son entrée analogique en une sortie numérique de 16 bits. Puisque la vitesse du

signal est très lente et qu’une grande précision est requise, le type de convertisseur

qui est le mieux adapté aux besoins de l’appareil est de type sigma-delta. La

valeur de sortie est stockée dans un registre interne des circuits intégrés et peut-

être transférée via un port série sous le protocole SPI.

Pour effectuer le transfert entre le convertisseur et le microcontrôleur, une routine

de communication ainsi qu’un programme d’acquisition ont été développés et mis

à l’essai. Le microcontrôleur possède un port intégré permettant le transfert de

données via port série SPI. Toutefois, ce port de communication ne sera pas utilisé

pour le transfert de données entre le convertisseur de la cellule de charge et le

microcontrôleur pour des raisons d’incompatibilité. Il est habituellement possible

d’utiliser le port SPI pour communiquer avec plusieurs composantes possédant ce

protocole de transfert de données. 4 http://www.analog.com/static/imported-files/data_sheets/AD7798_7799.pdf

Page 18: Rapport final - uqac.ca

18

Cependant, dans le cas du projet, les deux convertisseurs utilisés ne

fonctionneront pas aux mêmes vitesses en plus de ne pas posséder les mêmes

protocoles de transfert. En effet, le circuit intégré de conversion AD7798 transfère

les données converties via sa sortie DOUT/RDY illustrée à la figure 7, à des

vitesses de 4.17 à 470 Hz qui sont nettement inférieures au convertisseur de

l’EMG.

Figure 7 : Représentation de la puce électronique de conversion AD7798

Le problème est que lorsque le circuit intégré est en conversion, la sortie devient

‘1’ (5Vcc) jusqu’à ce que la conversion se termine. Deux convertisseurs

analogiques à numérique pourrait théoriquement communiquer par le même port

SPI, mais vu la caractéristique du convertisseur AD7798, le bus SPI devient

inutilisable pendant la conversion. Les données provenant alors du convertisseur

EMG deviennent donc erronées entre chaque conversion de l’AD7798. Les deux

convertisseurs devaient donc être utilisés avec deux ports SPI séparés. Toutefois,

le microcontrôleur utilisé ne possède qu’un seul port SPI. Pour résoudre ce

problème, une routine simulant un port SPI a été programmée dans le

microcontrôleur. Des entrées/sorties logiques génériques du microcontrôleur ont

été utilisées pour le transfert. Cette routine a été programmée en suivant une

logique de transfert spécifique au convertisseur choisi.

Page 19: Rapport final - uqac.ca

19

Cette logique est très importante pour le bon fonctionnement du système, car les

spécifications du constructeur de la puce doivent être suivies pour un transfert de

donnée précise et sans perte d’information. Cette logique de programmation s’est

faite en se basant sur la figure 8, illustrant la séquence temporelle à utiliser lors du

transfert. Comme la figure le démontre, le transfert s’effectue en synchronisation

avec une d’horloge passant du mode repos (5vcc) à actif (0Vcc). Cette horloge

doit être envoyée à la puce sur l’entrée SCLK pendant que l’entrée CS��� est

sélectionnée, c'est-à-dire pendant qu’elle est égale à 0 (0Vcc).

Figure 8 : Représentation de la séquence de transfert de l’AD7798

L’AD7798 doit être configuré avant d’être utilisé. Comme la figure 9 le démontre,

une structure bien précise de transmission et de réception doit être respectée afin

de bien communiquer avec le convertisseur. La fiche technique du constructeur

explique et énumère les différentes configurations possibles ainsi que la manière

de les effectuer.

Page 20: Rapport final - uqac.ca

20

Pour procéder à la configuration, il est nécessaire d’envoyer différents groupes de

données d’une longueur de huit bits. Chacun de ces groupes de données doit être

synchronisé avec l’horloge, car le convertisseur fait l’acquisition de chacun des

bits sur un cycle d’horloge. Un premier groupe de données d’une longueur de huit

bits doit être envoyé pour déterminer l’adresse du registre interne de la puce à

modifier ou lire, suivi d’un groupe d’une longueur de seize bits servant à

configurer le registre. Entre chacun de ces envois, l’entrée CS doit être maintenue

à 0 (0Vcc).

La dernière configuration qui doit être envoyée est une configuration permettant à

la puce d’effectuer des conversions continues à la vitesse sélectionnée. Après que

cette configuration soit terminée, il n’est plus nécessaire d’utiliser l’entrée de la

puce. En effet, la sortie de celle-ci deviendra 0 (0Vcc) à chaque fois qu’une

conversion sera terminée et une série de seize horloges devra être envoyée à la

puce à ce moment à une vitesse pouvant aller jusqu’à 1Mhz pour transférer les

données.

Page 21: Rapport final - uqac.ca

21

Pour simplifier l’explication, seulement les configurations utilisées sont

énumérées ci-dessous.

Figure 9 : Schématisation de la configuration du convertisseur de la cellule

III.2.c. SPI logiciel

Afin de communiquer avec la cellule de charge, un deuxième port SPI était requis.

Comme le dsPic30f4011 ne possède qu’un seul port SPI intégré, il était nécessaire

d’en concevoir un deuxième entièrement programmé.

Page 22: Rapport final - uqac.ca

22

� Fonction d’initialisation du port SPI 2

La première fonction consiste à initialiser et à configurer le

temporisateur 1 (figure 10). Ce temporisateur est utilisé pour

synchroniser la transmission des données.

Cette fonction débute en configurant les paramètres du

temporisateur. Comme le temporisateur utilise l’horloge

interne pour incrémenter le temps, il est possible de réduire le

nombre de cycles d’horloge en utilisant une mise à l’échelle

(Prescaler). Ce paramètre permet d’envoyer une impulsion à

tous les 1, 8, 64, ou 256 cycles d’horloge (figure 11). Pour le

SPI 2, la mise à l’échelle a été ajustée à 1. Ensuite un

compteur permet de relever le nombre d’impulsions envoyé

par le «Prescaler». Lorsque la valeur du compteur atteint la

valeur voulue (période «Pr1»), le drapeau signale la fin de la

temporisation. Le compteur se réinitialise et change l’état de la

sortie de l’horloge du port SPI 2. Un cycle d’horloge SPI 2

nécessite donc deux périodes complètes du temporisateur 1.

Figure 10 : Initialisation du port SPI 2

La valeur de la fréquence de l’horloge du SPI2 est donc définie par la formule

suivante, où la période est de 6 :

( ) ( )2

Pr 1 Période

Ps=Valeur du Prescaler

Fosc=Fréquence du cris ta l

8 / 4 7.328 8 / 4/ 2 / 2 1.22

P r1 1 6os c

SP I

f M Hzf M Hz

P s

=

• • = = =

• •

Page 23: Rapport final - uqac.ca

23

Finalement, le mode d’interruption est désactivé, le temporisateur est désactivé

(en attente) et la valeur du drapeau est initialisée à la valeur 0.

Figure 11 : Structure du temporisateur 1 du dsPIC30f4011

� Fonction d’envoi du port SPI 2

La fonction d’envoi du port SPI 2 permet d’envoyer

un mot binaire d’une longueur déterminée (figure 13).

L’appel de la fonction TXLoadC (mot,longueur)

débute en activant et en faisant la mise à zéro du

temporisateur 1. La première valeur du mot binaire

est immédiatement appliquée à la sortie du port SPI 2.

La boucle attend alors le drapeau du temporisateur 1.

Lorsque que le drapeau signale que le temps est

atteint, la valeur de la sortie de l’horloge du SPI 2

passe de 1 vers 0. La valeur de sortie du SPI 2 change

de valeur seulement après deux changements d’état

(un cycle d’horloge complet).

Figure 12 : Fonction d’envoi du port SPI 2

Page 24: Rapport final - uqac.ca

24

Il est important de noter que la valeur de la sortie du port SPI 2 est rafraîchie sur

le front descendant du signal d’horloge du port SPI 2. Finalement, un compteur

permet de vérifier si la longueur du mot est atteinte. Si la longueur du mot est

atteinte, la transmission est terminée. Sinon, la séquence attend de nouveau le

drapeau du temporisateur1.

� Fonction de réception du port SPI 2

La fonction de réception du port SPI 2

(figure 13) permet de recevoir un mot de

16 bits. La fonction débute par la remise à

zéro du temporisateur 1 et son activation.

Ensuite le programme attend le drapeau du

temporisateur. Lorsque le drapeau s’active,

la valeur appliquée à l’entrée du port SPI 2

est enregistrée dans le registre de réception

à tous les cycles d’horloge.

Il est donc important de noter que la

sauvegarde de l’état de l’entrée du port SPI

2 se fait sur le front montant du cycle de

l’horloge.

Figure 13 : Fonction de réception du port SPI 2

Page 25: Rapport final - uqac.ca

25

Un compteur permet de détecter la fin du mot à enregistrer. Si la réception n’est

pas terminée, le cycle attend de nouveau le drapeau du temporisateur. Pour le bon

fonctionnement de la puce, il est nécessaire de construire une interface possédant

les alimentations nécessaires et la filtration adéquate des entrées et sorties. Pour ce

faire, une lecture approfondie de la fiche technique du convertisseur AD7798

permet la conception d’un circuit permettant un fonctionnement optimal de

l’équipement.5 Dans cette fiche, tous les niveaux de tensions d’alimentation et les

valeurs de composantes pour les filtres sont mentionnés selon les fréquences et

types de signaux traités. Le circuit développé est illustré en annexe de ce

document.

5 http://www.analog.com/static/imported-files/data_sheets/AD7798_7799.pdf

Page 26: Rapport final - uqac.ca

26

III.2.d. Capteur EMG

Dans le système proposé, il existe une deuxième interface qui sert à la conversion

des signaux provenant des contractions musculaires. Ces signaux sont captés avec

une triode qui est collée sur la peau comme illustrée à la figure 14.

Figure 14 : Triode musculaire

Les signaux à la sortie de la triode sont de l’ordre du micro volt. L’utilisation d’un

appareil servant à amplifier le signal musculaire sera donc nécessaire pour le

traitement des signaux. La compagnie qui fabrique ce système est Thought

Technology Ltd et le numéro de produit de l’amplificateur est le MyoScan-Pro

(SA9401M). Cet amplificateur se branche directement sur la triode ce qui a pour

impact d’amplifier un signal ayant beaucoup moins de bruits parasites. Le signal

de sortie de cet amplificateur sera de l’ordre du millivolt jusqu’au volt ce qui

facilitera le traitement. En plus d’amplifier le signal, cet appareil le traite et envoie

sa valeur efficace à la sortie, ce qui est très avantageux pour l’application

présente. L’amplificateur et un exemple de la forme de son signal de sortie sont

illustrés à la figure 15.

Figure 15 : Amplificateur RMS et son signal de sortie

Page 27: Rapport final - uqac.ca

27

Au début de chaque séance, un essai préliminaire est effectué sur chaque patient

pour déterminer la force maximale que celui-ci est capable de fournir. Le signal

émis par les muscles est ensuite enregistré et un seuil maximal est déterminé pour

une bonne réadaptation. Ce seuil représente environ 30% de la force maximale

précédemment enregistrée.

Par la suite, le patient commence à faire les mouvements prescrits et à chaque fois

que les signaux musculaires émis sont supérieurs au maximum déterminé, la

consigne de charge diminuera jusqu’à ce que les signaux musculaires passent en

dessous du seuil établi. Comme les signaux à traiter sont de types analogiques, ils

doivent être convertis en signaux numériques pour être traités dans le

microcontrôleur. Pour ce faire, une interface semblable à l’interface de la cellule

de charge a été conçue. Cependant, le circuit intégré servant à la conversion est

différent, car les seuils de tension sont différents. Après plusieurs recherches, le

choix s’est arrêté sur un convertisseur fabriqué par la compagnie Analog Device

qui possède des caractéristiques désirées pour cette application. 6 Tout comme le

circuit intégré de la cellule de charge, celui-ci permet une conversion de son

entrée analogique en une sortie numérique de 16 bits. La conversion se fait avec

une horloge externe et les données sont transférées au microcontrôleur par port

SPI.

Suite à la lecture des documents technique du convertisseur AD7680, il a été

possible de concevoir un circuit permettant la filtration adéquate des entrées

sorties tout en optimisant la précision de l’acquisition de données. Le transfert de

données entre le circuit intégré de conversion de l’EMG et le microcontrôleur se

fait par communication série SPI. Cette fois-ci, le port interne du microcontrôleur

est utilisé. Ce port série nécessite une configuration de plusieurs registres internes

qui déterminent la vitesse de transfert, le type d’horloge à utiliser et la longueur

des données lors du transfert. Les configurations des registres nécessaires pour

6 http://www.analog.com/static/imported-files/Data_Sheets/AD7680.pdf

Page 28: Rapport final - uqac.ca

28

l’application présente sont illustrées dans la figure 16 (se référer à la fiche

technique du manufacturier pour la description détaillée de chacun des registres)7.

Figure 16 : Configuration des deux registres nécessaires à la communication série SPI

Cette configuration du microcontrôleur assigne au port SPI une vitesse d’horloge

de transfert de 3.685 MHz, configure le microcontrôleur en mode maître et

assigne la longueur des données transférées à huit bits. Cette configuration permet

aussi d’ajuster les paramètres de l’horloge pour qu’ils soient compatibles avec le

convertisseur. La figure 17 démontre la séquence à suivre pour que la puce

effectue une conversion adéquate sans perte de données.

Figure 17 : Séquence à suivre pour une conversion et un transfert adéquat

Comme il est illustré, pour effectuer une conversion adéquate, le convertisseur

nécessite un envoi de 24 cycles d’horloges consécutifs pendant que son sélecteur

(CS���) est à 0 (0Vcc). Puisque la communication à l’intérieur du microcontrôleur a

été configurée pour envoyer et recevoir huit bits à la fois, les données reçues par

le microcontrôleur sont donc trois caractères de cette longueur.

7 http://www.analog.com/static/imported-files/Data_Sheets/AD7680.pdf

Page 29: Rapport final - uqac.ca

29

Pour démarrer l’horloge, une donnée quelconque doit être écrite dans le registre

tampon (SPI1BUF) du microcontrôleur. Celui-ci démarrera ensuite l’horloge de

communication (SCK1) et transmettra ce qui est à l’intérieur du registre tampon

sur son bus de sortie (SDO1). Cependant, pour cette application, le bus de

transmission série n’est pas utilisé. En effet, seul le bus d’entrée (SDI1) est utilisé

par le microcontrôleur puisque le convertisseur analogique à numérique utilisé ne

nécessite aucune configuration ou envoi de consigne. Celui-ci nécessite seulement

un envoi de 24 cycles d’horloge consécutif.

La conversion se fait durant les quatre premiers cycles d’horloges, les 16 autres

cycles permettront le transfert des données significatives de la conversion pour

ensuite se terminer par un envoi de quatre zéros par le convertisseur à la fin de la

communication. La figure 18 illustre le branchement entre l’AD7682 et le

« CPU ».

Figure 18 : Schématisation du branchement entre le microcontrôleur et l’AD76808

8 http://www.analog.com/static/imported-files/Data_Sheets/AD7680.pdf

Page 30: Rapport final - uqac.ca

30

Une séquence a donc été programmée à l’intérieur du microcontrôleur pour la

réception des trois caractères qui, après un traitement mathématique et leurs

recombinaisons, donnent une seule valeur sur 16 bits.

Pour effectuer la recombinaison des trois caractères, il a été nécessaire de faire des

déplacements dans les caractères reçus pour ensuite les additionner ensemble.

Cette manipulation est illustrée dans la figure 19.

Figure 19 : Séquence de conversion des données provenant de l’AD7680

Page 31: Rapport final - uqac.ca

31

III.2.e. Routine de communication avec le variateur de vitesse

Le variateur de vitesse Allen Bradley Ultra 3000 possède un port de

communication RS-232 permettant la configuration et le contrôle de l’appareil

(figure 20). Toute l’information est contenue dans la publication de Rockwell

Automation 2098-RM003A-EN-P. 9

Figure 20 : Identification du port de communication série sur le variateur de vitesse

� Configuration

La communication du variateur de vitesse RS-232 se fait sous la configuration

suivante :

Tableau 1: Configuration du port série

Vitesse de transfert : 38400 bauds

Parité : aucune

Stop bits : 1

Nombre de bits : 8

Contrôle du flux: aucun

9 http://samplecode.rockwellautomation.com/idc/groups/literature/documents/rm/20 98-rm003_-en-p.pdf

Page 32: Rapport final - uqac.ca

32

La configuration des paramètres de communication UART du dsPic30F4011 a dû

être effectuée à l’intérieur du programme afin de permettre la communication

entre le contrôleur et le variateur de vitesse.

� Architecture de la transmission de donnée

L’architecture de communication est basée sur l’envoi d’une série de caractères

ASCII (8bits) permettant de spécifier le numéro du variateur, l’action à effectuer

(lecture, écriture), le paramètre à accéder (ex. vitesse, position, courant…), la

valeur à envoyer (16 à 32 bits) et la validation des caractères envoyés ou reçus

(Checksum). La communication est amorcée en envoyant le caractère (:) et se

termine par un Retour de chariot. Une donnée typique se trouve sous la forme

suivante :

« : NN PPP A VVVVVVVV CC <cr> »

(:) Initialisation de la communication

(NN) : Adresse du variateur de vitesse

(PPP) : Paramètre à lire ou à écrire

(A): Commande lecture, écriture

(VVVVVVVV): Valeur de lecture ou d’écriture

(CC) : Valeur des deux derniers caractères du ‘Checksum’

<cr> : Retour de chariot (Fin de la communication)

La valeur des caractères est envoyée sous la forme de caractères ASCII. Chaque

caractère numérique peut prendre des valeurs de 0 à F en hexadécimal.

Le numéro du variateur est égal à 0 pour l’utilisation du servomoteur du côté

gauche de l’appareil. Pour communiquer avec le variateur du côté droit, il suffit

de remplacer l’adresse par 1. Pour les essais de ce projet seulement le côté gauche

est utilisé donc l’adresse restera égale à 0.

Page 33: Rapport final - uqac.ca

33

« : 00 PPP A VVVVVVVV CC <cr> »

Les paramètres du variateur sont définis de 000 à FFF. Par exemple pour

modifier le paramètre de la consigne de vitesse, l’adresse est égale à 0x06D.

« : 00 06D A VVVVVVVV CC <cr> »

Les commandes valides pour l’adresse 0x06D sont les suivantes :

0x0 : Lire la valeur dans le variateur de vitesse

0x1 : Écrire la valeur dans le variateur de vitesse

0x8: Lire la valeur minimum dans le variateur de vitesse

0x9 : Lire la valeur maximum dans le variateur de vitesse

« : 00 06D 1 VVVVVVVV CC <cr> »

La valeur pouvant être envoyée vers le variateur de vitesse est de 0x0000000 à

0xFFFFFFFF. Cette valeur représente la consigne de vitesse du variateur en

comptes/seconde.

Ex. :

65535

1 Révolution par minute (RPM) = 8000 Comptes/minute

1 Révolution par minute (RPM) = 155 Comptes/seconde

65535422.8 Rpm

155

h DFFFF =

=

« : 00 06D 1 0000FFFF CC <cr> »

Page 34: Rapport final - uqac.ca

34

� Validation des données

Afin de vérifier l’intégrité de la chaîne de caractères, un algorithme calcule la

SOMME DES DONNÉES (checksum). Ce calcul consiste à faire l’addition de la

valeur décimale de chaque caractère après l’initialisation de la communication.

Ensuite la valeur de la somme est soustraite de 256 et le résultat est converti en

hexadécimal

(256 )ASCII hexadecimal− ⇒∑

Ex. : « : 00 06D 1 0000FFFF CC <cr> »

Tableau 2: Valeur décimale de certains caractères ASCII

Caractère ASCII Valeur décimale

0 48

1 49

6 54

D 68

F 70

(256 )

(48 48 48 54 68 49 48 48 48 48 70 70 70 70)

787

256 787 531

531

d

d d d

d h

ASCII hexadecimal

ASCII

ASCII

FFFFFDED

− ⇒

= + + + + + + + + + + + + +

=

− = −

− →

∑∑∑

Les deux derniers caractères de la réponse hexadécimale forment le ‘checksum’ et

doivent être envoyés vers le variateur de vitesse. Dans le cas de l’exemple

précédant la valeur du “CheckSum” sera ED. Un exemple est présenté à la page

168 du document 2098-RM003A-EN-P de Rockwell automation. 10

« : 00 06D 1 0000FFFF ED <cr> »

10 http://samplecode.rockwellautomation.com/idc/groups/literature/documents/rm/20 98-rm003_-en-p.pdf

Page 35: Rapport final - uqac.ca

35

� Conversion et traitement de la valeur reçue ou envoyée

L’asservissement de la vitesse du bras permet d’ajuster la charge simulée sur la

poignée. La valeur de la vitesse est calculée par le contrôleur et est écrite dans un

registre de 32 bits. Afin d’isoler chaque caractère hexadécimal du mot de 32 bits,

il suffit d’utiliser la fonction de décalage « shift register » permettant d’isoler

chaque groupe de 4 bits du groupe de 32bits. Chaque caractère hexadécimal isolé

est converti en code ASCII 11 et ensuite envoyé dans l’emplacement de la valeur

à écrire.

Ex. : 0000FFFF (hexadécimal) = 00000000000000001111111111111111 (binaire)

b

b

1111

0000 0h

h

F→

Pour convertir la valeur hexadécimale de �� en code ASCII il

suffit d’ajouter 37� pour les valeurs de A à F et 30� de 0 à 9.

F +37 =46

0 +30 =30 h h h

h h h

La valeur correspondante obtenue sera F et 0 en code ASCII.

« : 00 06D 1 0000FFFF ED <cr> »

Finalement, une routine permet d’envoyer un caractère à la fois la chaîne de

caractère qui a été construite dans la séquence. Cette routine transmet tous les

caractères jusqu’à ce qu’elle rencontre la fin de la chaîne. De plus si la

communication est occupée, la routine attend avant d’envoyer un autre caractère.

Ceci permet d’éviter des erreurs d’écrasement de données.

11 http://www.asciitable.com/

Page 36: Rapport final - uqac.ca

36

� Résumé des étapes d’envoi

1- Inscription des paramètres dans la chaîne de caractère (Adresse, paramètre et

commande).

2- Conversion de la valeur à envoyer en caractère ASCII et inscription de ces

caractères dans la chaîne.

3- Calcul du ‘checksum’ et inscription de ces caractères dans la chaîne.

4- Envoi de la chaîne de caractères.

� Architecture de la réception de donnée

Le principe de réception est basé sur la même architecture que celle utilisée pour

la transmission. La différence se situe dans la partie commande où il suffit

d’inscrire la demande de lecture.

« : NN PPP 0 VVVVVVVV CC <cr> »

Il faut donc envoyer une chaîne semblable à une commande d’écriture à la

différence près que la zone allouée à la valeur à envoyer n’est pas transmise.

« : NN PPP A ________ CC <cr>

Il suffira ensuite de recevoir la réponse avec une routine de réception qui fera les

étapes inverses de l’envoi et enregistrera la valeur voulue dans le registre spécifié.

� Résumé des étapes d’envoi

1- Réception caractère par caractère (ASCII)

2- Calcul du ‘Checksum’ et vérification de la concordance des données

3- Conversion des caractères ASCII de la valeur envoyée en mots de 32bits.

Page 37: Rapport final - uqac.ca

37

� Gestion des erreurs de commande

Lorsqu’une commande de lecture ou d’écriture est envoyée au variateur de

vitesse, une série de code d’erreur peut être renvoyée par le variateur.

Par exemple, les réponses d’erreur possibles pour une commande à l’adresse

0x06D sont les suivantes :

0x04 = Valeur en dessous du minimum

0x08 = Code de fonction invalide

Pour chaque commande il existe des codes d’erreur qui lui sont associés. Il faut

donc s’assurer que la valeur envoyée soit valide, car présentement aucune boucle

n’a été programmée pour détecter les erreurs à la suite d’une commande.

Page 38: Rapport final - uqac.ca

38

III.2.f. Architecture du programme

� Initialisation et étapes préliminaires à l’utilisation

Le programme principal (figure 21) est

constitué de trois parties : l’initialisation

du microcontrôleur, l’initialisation de la

machine et l’asservissement de la vitesse.

Lorsque l’initialisation du contrôleur et

de la machine a été effectuée, le système

attend la consigne de démarrer

l’entraînement. La consigne provient de

l’interface de l’opérateur lorsque le client

est bien positionné et prêt à commencer

l’entraînement.

Pour terminer l’entraînement, l’opérateur

doit appuyer sur le bouton « Arrêt » de la

console d’opération.

Figure 21 : Routine de contrôle principale

Page 39: Rapport final - uqac.ca

39

L’initialisation du microcontrôleur consiste à

configurer et activer les périphériques utilisés

dans le contrôle de la machine (figure 22).

Dans l’ordre l’initialisation des « UART»

(Universal Synchronous & Asynchronous

Receiver Transmitter), permet de spécifier les

paramètres de communication tels que la vitesse,

la parité, le nombre de bits d’arrêt ainsi que la

configuration des interruptions générées par la

transmission ou la réception.

Figure 22 : Séquence d’initialisation du microcontrôleur.

Ensuite, il faut initialiser le port SPI 1 pour ajuster le type d’horloge utilisé et la

vitesse de communication. Pour le port SPI 2, il s’agit d’un port émulé, il faut

donc initialiser le temporisateur utilisé pour la communication ainsi que les

entrées et sorties dédiées pour transmettre et recevoir les signaux de l’échange de

donnée. Une fois les ports de communication initialisés et configurés, il faut

assigner la fonction de chacun des ports A, B, C, D, E, utilisés soit en entrée ou en

sortie et définir leurs valeurs initiales.

Lorsque l’initialisation des périphériques internes au microcontrôleur est

terminée, il faut ensuite procéder à l’initialisation des périphériques externes. Le

convertisseur A/D de la cellule de charge est donc configuré pour effectuer la

conversion à la vitesse voulue et de façon à envoyer des données en continu.

INITIALISATION DU

MICROCONTROLLEUR

INITIALISATION DU UART1

INITIALISATION DU UART2

INITIALISATION DU SPI 1

INITIALISATION DU TEMPORISATEUR #1

(SPI2)

INITIALISATION DES ENTRÉES / SORTIES

INITIALISATION DU A/D 2

INITIALISATION DU VARIATEUR DE VITESSE

Page 40: Rapport final - uqac.ca

40

Finalement, une configuration initiale est envoyée au variateur de vitesse pour

l’activer en mode asservissement de vitesse avec une consigne initiale de 0 RPM.

INITIALISATION DE LA

MACHINE

POSITIONNEMENT DU BRAS À LA CONSIGNE DE

L’INTERFACE LECTURE DE LA CONSIGNE DE FORCE DE L’INTERFACE

LECTURE DU SEUIL MAXIMAL DE FORCE DU

CLIENT (EMG)

CALCUL DU SEUIL DE 30%EMG MAX.

ATTENTE

CONSIGNE ANGULAIRE OK =0

CONSIGNE ANGULAIRE OK =1

ATTENTE

CONSIGNE CHARGE OK =0

CONSIGNE CHARGEOK=1

LECTURE DE LA CELLULE DE CHARGE

SAUVEGARDE DU ZÉRO DE LA CELLULE DE CHARGE

MAX EMG =1

LECTURE EMG

MAX EMG=0

Figure 23 : Séquence d’initialisation de la machine

L’initialisation de la machine vise à ajuster les paramètres qui sont propres au

client qui utilise la machine (figure 23).

La première étape consiste à ajuster l’angle de départ auquel le client débute son

exercice. L’angle est défini par l’entraîneur et doit être entré dans la console

d’opération. À la réception de cette consigne par le microcontrôleur, elle doit être

traitée, car cette consigne est en ASCII représentant un nombre décimal et de

longueur pouvant varier d’un à quatre caractères. En plus, pour indiquer que la

consigne est celle qui est attendue, elle est précédée d’une lettre indicatrice.

Page 41: Rapport final - uqac.ca

41

Une routine à l’intérieur du microcontrôleur a donc été développée pour ramener

cette valeur en hexadécimale sur 16 bits, ce qui permet le traitement de celle-ci. Il

est possible de visualiser les étapes de transformation de la variable dans la figure

24, qui servira pour toutes les réceptions de consigne.

Figure 24: Séquence de réception des consignes provenant de l’interface de contrôle.

Une fois la consigne inscrite, il faut activer la fonction de positionnement pour

que le bras mécanique de l’appareil se positionne à l’angle inscrit. Cette fonction

est en fait une boucle qui envoie une vitesse lente au variateur de vitesse et envoie

ensuite des consignes de lecture de position en boucle ce qui permet de savoir la

position du bras en continu. La routine se termine lorsque la position est atteinte.

À ce moment, une consigne de vitesse ZÉRO est inscrite dans le variateur de

vitesse ce qui arrête le bras à la position désirée. La séquence de cette routine est

illustrée à la figure 25.

Page 42: Rapport final - uqac.ca

42

Figure 25: Séquence de positionnement du bras à l’angle initial

La deuxième étape est l’envoi de la consigne de charge. Cette valeur doit être

inscrite dans la console d’opération et envoyée en appuyant sur le bouton « ok ».

Cette valeur sera utilisée comme consigne de charge initiale et traitée de la même

manière que la consigne d’angle initial décrit précédemment.

La dernière étape consiste à déterminer le seuil maximal musculaire du client. Le

servomoteur ayant une consigne de vitesse de 0 RPM ne permet donc aucun

mouvement de rotation du bras mécanique. Le client doit ensuite forcer au

maximum de ses capacités contre le bras mécanique et relâcher. Cette étape doit

être faite sous la supervision d’un spécialiste afin d’éviter tout risque de blessures.

Pendant ce temps le microcontrôleur enregistre la valeur maximale lue par

l’EMG. En appuyant par la suite sur le bouton « Max. EMG» le programme

enregistre cette valeur et détermine le seuil de 30% que l’utilisateur ne devra pas

dépasser lors de l’exercice.

Page 43: Rapport final - uqac.ca

43

� Routine d’asservissement en fonctionnement normal

Figure 26: Séquence d’asservissement de la vitesse du moteur.

L’asservissement de la vitesse (figure 26) permet de varier la force que le client

applique sur la cellule de charge. En accélérant dans le même sens que

l’utilisateur la charge simulée sera diminuée tandis qu’une décélération la fera

augmenter. Toutefois, le seuil de 30% de l’EMG reste prioritaire sur la consigne

de charge. En effet, une fois la lecture de la cellule de charge effectuée, une

lecture de l’EMG permet de vérifier que le seuil de 30% n’a pas été dépassé.

Advenant le cas, le système diminuera la consigne de la charge afin de rétablir

une valeur d’EMG inférieure ou égale à 30%. La diminution de la consigne sera

proportionnelle au dépassement du seuil de 30 % :

[ ]%

_ 30%100%

_ 30%

D Dépassement

EMG SeuilD

Seuil

∆ =

−• = ∆

Page 44: Rapport final - uqac.ca

44

Avec le pourcentage de dépassement, il est possible ensuite de calculer la

nouvelle consigne de charge de l’appareil.

[ ]

( )nouvelle actuelle actuelle

SpF Consigneforce N

SpF SpF SpF D

=

= − • ∆

Ensuite, la mesure de la force appliquée permet de calculer la différence avec la

consigne de charge.

[ ]Différence de force

Consigne actuel

F N

F F F

∆ =

∆ = −

Les nouvelles consignes de vitesse et d’accélération sont ensuite déterminées en

fonction de F∆ .

[ ]

( )

2

2min

min min

Consigne de vitesse Compte/seconde

Consigne d'accélération Compte/seconde

Accélération minimum Compte/seconde

correction

actuelle correction

SpV

SpA

A

SpA A A F Gain

SpV V F Gain Facteur

=

=

=

= + • ∆ •

= ± ∆ • •( )correction

La valeur de la consigne d’accélération (SpA) varie donc entre une valeur

d’accélération minimale jusqu'à une valeur proportionnelle à l’erreur entre la

consigne et la force appliquée.

La valeur de la consigne de vitesse (SpV) dépend du type d’erreur sur la consigne

de charge. Si la valeur actuelle est inférieure à la consigne, il y aura une correction

négative sur la vitesse et inversement dans le cas d’une valeur actuelle supérieure

à la consigne.

Page 45: Rapport final - uqac.ca

45

Lorsque les nouvelles valeurs ont été déterminées, elles sont envoyées au

variateur de vitesse pour appliquer la correction. Une fois les nouvelles consignes

envoyées au variateur de vitesse, le programme envoie la valeur de position

angulaire, d’EMG et de cellule de charge vers l’interface.

Afin d’accélérer au maximum la vitesse de la boucle d’asservissement, la gestion

des positions de fin de course est gérée par le variateur de vitesse. De cette

manière, le programme dans le microcontrôleur n’aura plus besoin de recevoir les

données de position pour détecter les limites de position.

Lors du positionnement initial du bras, la première position est enregistrée comme

valeur minimale. Ensuite, la valeur maximale est calculée soit 90 degrés de plus

que la valeur minimale. Ces deux valeurs sont envoyées au variateur de vitesse

pour la détection de la fin de course.

Finalement, une comparaison à l’intérieur du variateur de vitesse permet d’activer

deux sorties sur le variateur de vitesse. L’activation des sorties permet d’alimenter

deux entrées du microcontrôleur informant que la fin de course est atteinte. Les

deux entrées permettent de signaler la fin de la course du bras, de commander

l’arrêt du moteur et de changer le sens du mouvement.

Page 46: Rapport final - uqac.ca

46

III.2.g. Interface d’opération

Figure 27: Interface d’opération.

Dans le cadre du projet, l’interface d’opération permettra d’opérer la machine

seulement en flexion du bras gauche.

Le fonctionnement de l’interface se divise en deux parties. La première est une

boucle séquentielle qui permet de rafraîchir les valeurs de l’interface à chaque

milliseconde (Figure 28). La deuxième est une fonction de réception qui s’active

en présence d’un événement permettant de recevoir les données envoyées par le

microcontrôleur.

Page 47: Rapport final - uqac.ca

47

Les données acquises de l’EMG, de la cellule de charge et de la position angulaire

sont affichées sur les trois graphiques de l’interface (figure 27). Les valeurs des

données sont rafraîchies lorsque la consigne du temporisateur de l’interface atteint

le temps désiré, soit 1mS.

Figure 28: Boucle de l’interface d’opération.

L’étape 0 consiste à envoyer la valeur de la position initiale en degré vers le

microcontrôleur. Le bouton « Dem » de l’interface permet d’aller à l’étape 0. Le

bouton « Ok » apparaît à droite de la boîte où peut être entrée la valeur de l’angle

initial (figure 29).

Page 48: Rapport final - uqac.ca

48

Le bouton « ARR » permet d’arrêter l’interface en fermant le port RS-232 et la

feuille Excel en cours. Un témoin (1/0) à droite du bouton « ARR » permet de

vérifier l’état de l’interface.

Figure 29: Consigne d’angle initial de l’interface.

Après avoir entré la consigne initiale de position angulaire, le bouton « Ok »

permet d’ouvrir le port de communication RS-232 et d’envoyer une chaîne de

caractères ASCII représentant la consigne angulaire. Par exemple, si la consigne

est 10 degrés, les caractères envoyés seront « :G10Z ». Les deux points permettent

de marquer le début de la chaîne, le «G» permet de spécifier l’angle initial, la

valeur « 10 » est la consigne et le « Z » représente la fin de la chaîne. Une fois

l’envoi des caractères terminé le port de communication est refermé, le

programme passe à l’étape 1 et le bouton « Ok » est masqué.

Figure 30: Consigne de charge.

L’étape 1 consiste à envoyer la consigne de la charge. Le bouton « Ok » est

affiché à droite de la consigne de charge. Un message clignotant est aussi affiché,

pour signaler qu’il ne faut pas toucher la poignée à cette étape. Ceci est dû à la

remise à zéro de la valeur lue à la cellule de charge. En appuyant sur le bouton

« Ok » le bouton est masqué et la valeur de la consigne est envoyée par RS-232.

Par exemple, pour une consigne de 10Kg, le message sera «:L10Z».

Page 49: Rapport final - uqac.ca

49

L’architecture est la même que pour la consigne angulaire sauf pour le « L» qui

spécifie la consigne de charge.

Figure 31: Consigne de l’EMG et valeur isométrique.

L’étape trois consiste tout d’abord à faire un test isométrique permettant d’obtenir

le seuil maximum lu par l’électromyogramme. À cette étape, la valeur de

l’électromyogramme est affichée en temps réel dans la case «ACT» pour valeur

actuelle. L’utilisateur peut donc forcer à quelque reprise contre le bras de

l’appareil de l’opérateur peut ensuite écrire la valeur maximale lue dans la case

«SP» afin de spécifier le maximum obtenu. Le bouton « Max EMG » est affiché

lorsque la séquence est à l’étape 3. En appuyant sur le bouton, celui-ci devient

masqué et permet d’envoyer la chaîne de caractère de la consigne de l’EMG. Par

exemple si la consigne est de 1000µV, le message envoyé sera «:S1000Z». Le

«S» permettra de spécifier la consigne de l’EMG au microcontrôleur.

Figure 32: Control de l’entraînement.

L’étape 4 peut débuter lorsque le bouton «DEM» est enfoncé. En appuyant sur le

bouton «ARR», l’entraînement est arrêté et l’interface attend le démarrage pour

continuer. Afin de transmettre la consigne d’arrêt ou de démarrage de

l’entraînement, les consignes «:ONNZ» (démarrage) et «:OFFZ» (arrêt) sont

envoyées au microcontrôleur. Pendant l’entraînement, l’interface permet de

visualiser les valeurs de la cellule de charge, de l’EMG et de la position angulaire.

Page 50: Rapport final - uqac.ca

50

Les valeurs affichées sont les valeurs qui sont contenues dans la mémoire tampon

de la réception RS-232, donc les dernières valeurs reçues en provenance du

microcontrôleur. La mémoire tampon contient 30 caractères ASCII et la chaîne de

caractères à recevoir est de 14 caractères. La chaîne de caractères est constituée

des valeurs hexadécimales de la position angulaire, de l’EMG et de la cellule de

charge de la façon suivante «:AAAAEEEELLLLZ». Le «:» définit le début de la

chaîne et le «Z» la fin. Les valeurs AAAA, EEEE ou LLLL sont les valeurs

hexadécimales de 0 à FFFF. Une détection du «:» et un compteur permettent de

localiser la chaîne de caractères de la mémoire tampon. Il faut par la suite

convertir les caractères ASCII en un nombre décimal. Chaque caractère ASCII

est converti en sa valeur décimale, soit 48 pour un «0» ASCII à 70 pour un «F». Il

suffit ensuite de ramener la valeur en hexadécimal et de faire la somme de chaque

caractère.

Par exemple : «1», «A», «2», «F» en décimal

( )

( )

( )

( )

( ) ( ) ( )

1 49 49 48 1

A 65 65 65 10 10

2 50 50 48 2

F 70 70 65 10 15

1 4096 10 256 2 16 15 6703

1A2F 6703

Val

→ → − =

→ → − + =

→ → − =

→ → − + =

= • + • + • + =

=

Une fois la valeur convertie, il suffit de l’afficher dans l’interface et d’enregistrer

les valeurs dans Excel. Afin d’avoir un graphique ayant un affichage précis,

l’image de fond a été dessinée avec une précision de un pixel. Le format de

l’image est de 1200X800 pixels et les divisions verticales sont à tous les 100

pixels. Chaque rafraîchissement avance le pointeur dans l’image de un pixel.

Selon le temps de rafraîchissement, il est possible de ramener les échantillons

dans le temps. De la même façon, les valeurs affichées dans les graphiques seront

donc des %, kg ou degré ramenées sur 267 pixels. Lorsque la valeur du pointeur

en X atteint 1200 pixels, l’image est réinitialisée pour effacer les graphiques.

Page 51: Rapport final - uqac.ca

51

Pour faciliter la comparaison des données avec celles recueillies avec le prototype,

un enregistrement Excel permet de sauvegarder toutes les données affichées

durant toute la durée de l’exercice.

L’enregistrement dans un fichier nommé «Entraînement.xls» débute automatique

lorsque l’entraînement démarre. Ce fichier est sauvegardé lors de l’arrêt de

l’exercice. À chaque fois que le pointeur du graphique atteint 1200 pixels,

l’enregistrement Excel change de colonne. Ceci permet donc d’afficher facilement

un graphique de 1200 échantillons de l’EMG de la cellule de charge et de la

position angulaire

Figure 33: Affichage du graphique de l’EMG.

Figure 34: Affichage du graphique de l’EMG à partir du fichier Entraînement.xls

Comme le démontrent les figures 33 et 34, il est possible de vérifier la

concordance des valeurs enregistrées dans le tableau Excel.

-10

0

10

20

30

40

50

0 50 100 150 200 250 300 350 400

Page 52: Rapport final - uqac.ca

52

Afin de vérifier l’interface, des valeurs aléatoires ont été envoyées par RS-232. La

seconde partie du programme est une fonction qui se déclenche lorsque le port

RS-232 reçoit 24 caractères. À ce moment une copie de la mémoire tampon est

transférée dans un registre afin d’être traitée dans la routine principale. La

fonction de réception est active seulement à l’étape 2 pour obtenir la valeur en

isométrie et à l’étape 3 pour le rafraîchissement de l’affichage.

Figure 35: Paramètre du port RS-232 et remise à zéro

Plusieurs fonctions ont été programmées afin de faciliter les essais. Pour

configurer le nom du port RS-232, une case permet de la spécifier pour le bon

fonctionnement de l’interface. Ensuite, un bouton remis à zéro permet de

réinitialiser l’interface à l’étape initiale en tout temps (Figure 35). Des affichages

permettant de visualiser la valeur actuelle des graphiques en temps réel ont été

ajoutés afin d’obtenir rapidement la valeur affichée (Figure 36_1). Ensuite pour

diagnostiquer la communication les valeurs du tampon de réception sont affichées

en temps réel (figure 36_3) ainsi que les caractères ASCII détectés dans la chaîne

de caractères (Figure 36_4).

Finalement, l’affichage du temps de

rafraîchissement (figure 36_2) représente le temps

nécessité par le programme du microcontrôleur pour

effectuer un cycle complet de l’asservissement.

Cette valeur est affichée en milliseconde et permet

de mesurer la performance de la boucle.

Figure 36: Affichage des valeurs reçues et converties en temps réel.

Page 53: Rapport final - uqac.ca

53

IV. Bilan des activités

IV.1 Arrimage formation pratique/universitaire

Lors de la réalisation du projet, de nombreuses notions techniques et

mathématiques ont été nécessaires pour le bon déroulement de celui-ci. En effet,

des cours tels que Système à Microprocesseur, Systèmes digitaux, Introduction

aux Ordinateurs, Dynamique des Systèmes II, Électronique I et Électronique II

ont permis d’acquérir les connaissances de base nécessaire au bon déroulement du

projet.

Les cours tels que système à Microprocesseur, Systèmes digitaux et Introduction

aux Ordinateurs ont été très utiles pour développer le programme de contrôle du

système fonctionnant sur microcontrôleur. Par la suite, les notions acquises dans

les cours de Dynamique des Systèmes II, Électronique I et Électronique II ont

permis de comprendre de nombreuse notion sur la stabilité des systèmes et le

traitement des signaux.

Le projet a quant à lui permis d’approfondir de nombreuses notions qui ont été

apprises plus tard au cours de la formation. Effectivement, une étude approfondie

des systèmes de conversions analogiques à numériques a été nécessaire et très

utile. Subséquemment, le développement d’une interface de contrôle a nécessité

l’apprentissage du programme Visual Studio et du langage de programmation

Visual Basic. Finalement, le projet en général permet d’appliquer de nombreuses

notions apprises au long de la formation et de comprendre l’utilité de celles-ci.

Il est à noter que la matière des cours tels que Signaux et Système, Traitement

numérique des Signaux et Système asservi aurait pu être très utile pour le

développement de l’appareil. Cependant, il était difficile de faire le lien entre les

notions théoriques de ces cours et leurs applications dans ce projet.

Page 54: Rapport final - uqac.ca

54

Finalement, les cours optionnels comme Interface et Instrumentation ainsi que

Conception de Systèmes digitaux sont des cours très appliqués qui auraient pu

apporter des techniques de conception utiles au développement du système.

Cependant, le projet était déjà très avancé lorsque nous avons assisté à ces cours,

il a donc été impossible de bénéficier de ces connaissances durant le projet.

Page 55: Rapport final - uqac.ca

55

IV.2 Travail d’équipe

Dans la première moitié du projet, l’appareil A.M.E résidait dans les locaux de

l’entreprise et était utilisé pour la réadaptation physique. Ensuite, dans la

deuxième partie du projet, la machine a été transférée dans l’aile des humanités de

l’UQAC pour une étude sur plusieurs personnes afin de valider les performances

de l’appareil au niveau physiologique.

Afin de ne pas interférer avec l’utilisation de la machine, il fallait bien planifier

les moments où allaient être effectuées les interventions sur l’équipement. De

plus, comme l’équipement était utilisé fréquemment, il fallait s’assurer de

remettre A.M.E. dans sa condition initiale après chaque intervention.

Le projet a donc permis de mieux coordonner les interventions de façon à ne pas

compromettre l’utilisation normale de l’appareil avec l’utilisation de l’agenda en

ligne de Google.

Puisque la première version de l’équipement a été conçue par le CPA, il fallait

fréquemment entrer en contact avec eux afin d’obtenir de l’information technique

sur certains composants. De plus, certains des équipements étaient accessibles via

le laboratoire du Cégep de Jonquière et ont pu nous permettre de faire plusieurs

essais avec le variateur de vitesse. De cette, façon il était possible d’effectuer des

essais sécuritaires et sans utiliser du temps d’opération de A.M.E.

Cette particularité du projet a permis d’apprendre à utiliser les ressources

disponibles afin de faciliter le développement de l’équipement.

Finalement, l’interaction avec l’ensemble des participants, soient le CEME, le

CPA , les techniciens et notre conseiller, a permis tout au long du projet de

vérifier et corriger les hypothèses qui ont été avancées.

Page 56: Rapport final - uqac.ca

56

IV.3 Respect de l’échéancier

Figure 37 : Diagramme de Gantt de la planification du projet

Page 57: Rapport final - uqac.ca

57

L’échéancier a été respecté pour la majorité des tâches à effectuer. Toutefois,

certains points ont été plus longs que prévu.

La calibration et l’essai de la cellule de charge ont duré une semaine de plus que

le délai prévu dû à des problèmes de configuration du circuit intégré. Ensuite, dû à

une particularité du convertisseur de la cellule de charge, un port de

communication SPI virtuel a dû être programmé. Cette étape supplémentaire a

ajouté un délai au niveau du développement de l’acquisition de la cellule de

charge.

La conception de l’interface d’essai a aussi été un peu plus longue que prévu. En

effet, la programmation avec Visual Studio 2008 a nécessité un temps

d’adaptation afin de maîtriser les fonctions et l’environnement du programme. De

plus, pour faciliter le diagnostic du programme durant le projet, l’interface a été

modifiée et adaptée tout au long du projet. Finalement, pour permettre l’affichage

des valeurs en temps réel, il a fallu optimiser la communication RS-232 afin de

maximiser le rafraîchissement des valeurs affichées.

La fin du projet était prévue pour le début du mois de mars 2010. Afin d’obtenir

les résultats voulus, il a été possible de prolonger la période d’évaluation des

performances du processeur versus celles de l’automate d’un mois c'est-à-dire

jusqu’au début avril 2010. Les résultats qui auraient été obtenus à la fin du mois

de mars auraient été satisfaisants, toutefois l’étude a été prolongée afin d’obtenir

le meilleur fonctionnement possible. Cette période a permis de faire quelques

correctifs au niveau du contrôle de l’appareil et d’optimiser l’asservissement du

système.

Page 58: Rapport final - uqac.ca

58

IV.4 Analyse et discussion

Après analyse du projet de façon générale, il est possible d’affirmer que celui-ci

s’est bien déroulé. Cependant, dû à une limitation causée par la vitesse de

communication entre le variateur de vitesse et l’unité centrale, il n’a pas été

possible d’utiliser les pleines performances de l’unité de calcul. Il sera donc

primordial dans la continuité du développement de l’appareil d’utiliser un

protocole de communication beaucoup plus rapide capable d’exploiter les

performances du système de contrôle à son maximum.

Un élément qui risque de devenir une faiblesse après l’amélioration de la vitesse

de communication énumérée précédemment est le convertisseur

analogique/numérique servant à faire la conversion des signaux provenant de la

cellule de charge. En effet, lors des essais effectués sur le système, il a été

possible de constater que la vitesse de conversion théorique de cet élément semble

difficile à atteindre si l’on désire une grande précision.

Un élément très important du projet est le remplacement du Myotrac par un

amplificateur EMG situé directement sur la triode. Ceci permet d’effectuer le

traitement des signaux musculaires directement à la source. En effet, cet

équipement permet de réduire les coûts de production de l’équipement en plus de

permettre au microcontrôleur d’effectuer le traitement des données. Cela a eu

pour effet d’éliminer la boucle de traitement qui était longue et qui pouvait ainsi

amener des délais de traitement et des réponses lentes du système.

Finalement, la vitesse de traitement du microcontrôleur est très élevée et permet

d’effectuer tous les calculs nécessaires au bon fonctionnement de l’appareil.

L’optimisation de la communication au niveau du variateur de vitesse permettra

d’utiliser le microcontrôleur à son plein potentiel et ceci amènera par le fait même

une meilleure réaction du système. De plus, le coût de cette composante est

minime si on la compare au système de contrôle existant.

Page 59: Rapport final - uqac.ca

59

Effectivement, il est possible de réduire le coût de l’unité de calcul par un facteur

de 20 pour une vitesse de traitement supérieure, tel qu’illustré dans le tableau 3.

Tableau 3 : Comparaison du prix des équipements

Prototype actuel Nouvelle Approche Processeur CompactLogix L43

3 656,18 $ Carte de développement dsPic (Microchip)

150 $

Carte de conversion pour cellule de charge

1 782,50 $ Convertisseur de la cellule de charge (A/D)

70 $

MyTrac 1 700 $ Convertisseur de l’EMG (A/D)

70 $

MyoScanPro 400 $

Total 7138,68$ Total 690$

Page 60: Rapport final - uqac.ca

60

V. Conclusion et recommandations

L’objectif du projet était de réévaluer les choix qui ont été faits dans le premier

prototype et de modifier le système pour améliorer les performances et réduire les

coûts. Les objectifs du projet ont pratiquement tous été atteints puisque le système

a présentement un fonctionnement comparable au prototype existant. De plus, les

coûts reliés au système de contrôle et à l’acquisition des signaux musculaires sont

grandement réduits.

La raison pour laquelle il n’a pas été possible d’obtenir un système possédant une

réponse plus rapide que le système existant est le protocole de communication

utilisé entre le variateur de vitesse et le microcontrôleur. Effectivement, ce

protocole a été choisi pour sa compatibilité avec le variateur de vitesse et le temps

limité pour la réalisation du projet. Il aurait été possible d’utiliser la

communication SERCOS, qui est un protocole sur fibre optique et qui est

présentement utilisée sur le prototype, mais il aurait été impossible de respecter le

temps alloué au projet si le support de la communication SERCOS avait été

ajouté. Il serait donc important d’étudier ce point pour le développement futur et

aussi, de faire une étude complète de la réaction du système bras/moteur pour

déterminer son temps de réaction et sa capacité à réagir à des mouvements

brusques.

Pour ce qui est du traitement des signaux de la cellule de charge, il serait peut-être

avantageux d’effectuer une amplification du signal directement à la sortie de la

cellule de charge. Effectivement, cela aurait pour effet de diminuer l’influence des

équipements environnants sur les signaux de la cellule. De plus, une fois amplifié,

il serait possible de faire la conversion analogique/numérique des signaux avec le

convertisseur intégré au microcontrôleur qui est plus rapide que le convertisseur

présentement utilisé.

Page 61: Rapport final - uqac.ca

61

Ensuite, le système actuel utilise un asservissement de vitesse pour simuler la

charge ressentie. En considérant une approche plus près de la physique réelle,

l’utilisation de consignes d’accélération pourrait probablement augmenter la

précision de l’asservissement et ainsi, diminuer le temps de réaction de

l’équipement.

Finalement, après une étude du travail accompli, il est possible de conclure que

les objectifs initiaux du projet ont été respectés et que le projet est maintenant

terminé.

Page 62: Rapport final - uqac.ca

62

VI. Bibliographie

CEME, Qu’est que c’est, 1 page , 2002, Consultants en ergonomie et en mieux-être

http://www.ceme.qc.ca/Questceque.htm

Consulté le 14 avril 2010.

AB, Ultra3000 Digital servo drive, 180 pages, 2004, Rockwell Automation

http://literature.rockwellautomation.com/idc/groups/literature/documents/in/2098-

in003_-en-p.pdf

Consulté le 10 octobre 2009.

AB, Ultra 3000 Digital servo drive, 180 pages, 2004, Rockwell Automation

http://literature.rockwellautomation.com/idc/groups/literature/documents/in/2098-

in005_-en-p.pdf

Consulté le 13 octobre 2009.

LINAK, Actuateur linéaire, 1 page, 2010, Linear actuator technologie

http://www.linak.com/Products/?id2=2

Consulté le 12 octobre 2009.

AB, Tl serie servo motor, 24 pages, 2005, Allen Bradley

http://literature.rockwellautomation.com/idc/groups/literature/documents/in/tl-

in001_-en-p.pdf

Consulté le 13 octobre 2009.

AB, Compact Logix Controller, 36 pages, 2008, Allen Bradley

http://literature.rockwellautomation.com/idc/groups/literature/documents/in/1768-

in004_-en-p.pdf

Consulté le 13 octobre 2009.

Page 63: Rapport final - uqac.ca

63

AB, 1768 Compact Logix Controller, 132 pages, 2008, Allen Bradley

http://literature.rockwellautomation.com/idc/groups/literature/documents/um/1768-

um001_-en-p.pdf

Consulté le 13 octobre 2009.

Oméga, Cellule de charge, 1 page, 2002, Oméga.ca

http://www.omega.ca/manuals/default_FRRR.asp?s=j

Consulté le 19 octobre 2009.

Vishay, Cellule de charge, 6 pages, 2002, Vishay Intertechnology

http://www.vishay.com/docs/49408/tedea-h.pdf

Consulté le 20 octobre 2009.

Thought technology, Cellule de charge, 23 pages, 2003, Thought technology

http://www.thoughttechnology.com/pdf/manuals/MAR900-

01%20SEMG%20applied%20to%20psychophysiology.pdf

Consulté le 15 octobre 2009.

Thought technology, Myotrac Infiniti, 56 pages, 2006, Thought technology

http://bio-medical.com/support/pdf/CONTISUITE.pdf

Consulté le 23 octobre 2009.

Thought technology, Myotrac Infiniti (user guide), 57 pages, 2005, Thought technology

http://www.thoughttechnology.com/pdf/manuals/SA9810%20Rev%204%20.pdf

Consulté le 25 octobre 2009.

Thought technology, MyoScan, 1 pages, 2010, Thought technology

http://www.thoughttechnology.com/gbfsensors.htm

Consulté le 25 octobre 2009.

Page 64: Rapport final - uqac.ca

64

AB, PLCenter_Surplus, 1 page, 2010, Allen Bradley

http://www.plccenter.com/buy/ALLEN+BRADLEY/2098DSD020X

Consulté le 15 octobre 2009.

MC, Compiler C30, 1 page, 2009, Microchip

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=14

06&dDocName=en535363

Consulté le 29 octobre 2009.

MC, Carte de développement, 1 page, 2009, Microchip

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=14

06&dDocName=en023561

Consulté le 29 octobre 2009.

EFPGA, EZ1CUSB - Altera Cyclone FPGA, 1 page, 2009, Easy_FPGA

http://www.easyfpga.com/

Consulté le 17 octobre 2009.

OTTech, FPGA USB Boards- ZestSC2, 1 page, 2009, Orange tree technologie

http://www.easyfpga.com/

Consulté le 11 octobre 2009.

SemiFluid, PIC18F2550 USB HID Oscilloscope, 1 page, 2009, SemiFluid

http://www.semifluid.com/?p=24#more-24

Consulté le 13 octobre 2009.

MC, dsPic30f4011, 1 page, 2009, Microchip

http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010337

Consulté le 13 octobre 2009.

Page 65: Rapport final - uqac.ca

65

TI, TLC2270 amplifier, 1 page, 2009, Texas Instrument

http://focus.ti.com/lit/ds/symlink/tlc2274.pdf

Consulté le 13 octobre 2009.

ONSEMI, Diodes MRA4003T3, 4 pages, 2004, ON semiconductor

http://www.onsemi.com/pub_link/Collateral/MRA4003T3-D.PDF

Consulté le 13 octobre 2009.

BFMC, CTT IKARUS, 1 page, 2009, BioFeedbackMotorControl

http://www.bfmc.de/produkte_direkt_eng.html

Consulté le 13 octobre 2009.

Page 66: Rapport final - uqac.ca

66

Annexe A : Nouvelle approche

Afin d’obtenir un contrôle qui s’approche au maximum des équations de la

physique, il serait possible de faire l’asservissement de la charge simulée en

faisant des corrections d’accélération durant le mouvement.

[ ]

[ ]

[ ]

2

2

Force appliquée

Masse

ccélération m/s

_ ang = Accélération angulaire cnt/s

F N

m Kg

A A

A

F mA N

=

=

=

=

Figure 38 : Schéma du bras de A.M.E. avec la force appliquée

Afin d’obtenir la valeur de la masse simulée (m), la force (F) appliquée doit être

mesurée ainsi que la hauteur (H) ou la poignée est positionnée. De plus,

l’accélération (A) angulaire du moteur devra être mesurée par le variateur de

vitesse.

Avec ces valeurs, il sera possible de déterminer la masse simulée par le système.

L’accélération (A) qui est mesurée par le variateur de vitesse est une accélération

angulaire, il faut donc la convertir pour avoir l’accélération à la hauteur de la

poignée.

( )

[ ]

2

2

22

Accélération angulaire /

1 tour du moteur = 8000 cnt

1 1 /8000 360 0.045

Accélération au niveau de la poignée m/s

2m/s 0.045

360

poignée

poignée

A cnt s

Cnt cnt cnt

A

cntA A H m

s cnt

π

=

= ° = °

=

° = °

i

i i i

H

F

A_ang

Page 67: Rapport final - uqac.ca

67

Lorsque l’accélération de la poignée est connue, il suffit d’utiliser la formule

suivante pour déterminer la masse simulée.

[ ]Kgpoignée

Fm

A=

Lorsque la masse simulée a été obtenue, il est possible de la comparer avec la

consigne et de calculer la correction à effectuer.

[ ]

[ ]

[ ][ ]

[ ]

% = Correction [%]

_ = Consigne de charge kg

Charge mesurée N

_

9.81

% 100% _

C

Sp load

load

load NSp load kg

N

kgC

Sp load kg

=

= •

Avec le pourcentage de correction, il sera ensuite possible de calculer la nouvelle

consigne d’accélération permettant d’obtenir la charge simulée voulue.

[ ]

( )( )

2

2

_ = Consigne d'accélération [ / ]

_ = Accélération réelle /

% Correction %

_ _ _ %

Sp A m s

A reel m s

C

Sp A A reel A reel C

=

= + •

Page 68: Rapport final - uqac.ca

68

La nouvelle consigne d’accélération aura donc une variation proportionnelle à

l’écart entre la charge et la consigne de charge. Afin de conserver l’appareil

sécuritaire, il sera important de spécifier une valeur maximum pour l’accélération

et la vitesse.

Finalement, pour permettre un contrôle en accélération avec le variateur de

vitesse existant, il faudra que le système n’atteigne jamais sa consigne de vitesse

pour conserver une variation de l’accélération. Donc ceci implique qu’à chaque

cycle de l’asservissement, il faudra ajuster la vitesse (positive ou négative) afin

d’accélérer ou de décélérer en plus d’envoyer la grandeur de l’accélération

voulue.

Il est à noter que la nouvelle consigne d’accélération (Sp_ A) devra être convertie

en accélération angulaire pour être envoyée au variateur de vitesse.

Page 69: Rapport final - uqac.ca

69

Annexe B : Plans électriques

Page 70: Rapport final - uqac.ca
Page 71: Rapport final - uqac.ca

Annexe C : Programme du microcontrôleur et de l’interface

Page 72: Rapport final - uqac.ca

1C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

'***********************************************************************************************************

'Declaration des variables'********************************************************************************************

***************Public Class Form1 Dim Temp As String = 0 Dim ExcelACT As Boolean = 0 Dim A As Char = "A" Dim CAR As Char = "Z" Dim ZERO As Char = "0" Dim X1 As Integer = 5 Dim Y1 As Integer = 264 Dim X2 As Integer = 5 Dim Y2 As Integer = 264 Dim Y3 As Integer = 530 Dim Y4 As Integer = 530 Dim Y5 As Integer = 796 Dim Y6 As Integer = 796 Dim Y7 As Integer = 264 Dim Y8 As Integer = 530 Dim Y9 As Integer = 796 Dim Y10 As Integer = 264 Dim Y11 As Integer = 530 Dim Y12 As Integer = 796

Dim fin As String = Chr(13) '<CR> Dim ONN As String = "ONN" Dim OFF As String = "OFF" Dim str As String = Chr(58) ': Dim FF As String = Chr(12) 'NP Dim RX_T_1 As Integer = 0 Dim temp1 As Integer = 0 Dim count As Long = 1 Dim MyXL As Object Dim XL_File As String Dim NomP As String Dim RX() As Integer = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} Dim PTR As Integer = 0 Dim RXVAL As String = 0 Dim RX_temp As Integer = 0 Dim RX_temp1 As Integer = 0 Dim PRX As Integer = 0 Dim POT() As Integer = {0, 0, 0, 0} Dim EMG() As Integer = {0, 0, 0, 0} Dim LOADC() As Integer = {0, 0, 0, 0} Dim ANG() As Integer = {0, 0, 0, 0} Dim TMRFRESH() As Integer = {0, 0, 0, 0} Dim TMRFRESH_val As Double = 0.0 Dim SPCHARGE() As Integer = {0, 0, 0, 0} Dim SPCHARGE_val As Integer = 0 Dim RXtemp() As Char = {A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,

A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A} Dim RXstat As Integer = 0 Dim EN_DIS As Boolean = False Dim Etape As Integer = 0 Dim ANG_STAT_OK As Boolean = False Dim EMG_STAT_OK As Boolean = False Dim CHRG_STAT_OK As Boolean = False Dim TR_STATUS As Boolean = False Dim R1 As Integer = 1 Dim R2 As Integer = 2 Dim R3 As Integer = 3 Dim CNT As Integer = 0 Dim flash As Integer = 0 Dim Maximum_emg() As Char = {ZERO, ZERO, ZERO, ZERO}

Page 73: Rapport final - uqac.ca

2C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

Dim Maximum_emgint() As Integer = {0, 0, 0, 0} Dim Maximum_emgVAL As Integer = 0 Dim CntEmgREF = 0 Dim emgTemp = 0 '****************************************************************************************

********************** 'Bouton DEM de l'interface (ouvre le port de communication et demarre l'interface) '****************************************************************************************

********************** Private Sub ComActive_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles ComActive.Click EN_DIS = True SerialPort1.PortName = COMNAME.Text 'Ouvre le port du nom

entree dans la case COMNAME SerialPort1.Open() INTERF_STAT.BackColor = Color.Lime 'Change la couleur du

status en vert (Active) INTERF_STAT.Text = 1 INTERF_STAT.Refresh() End Sub

'**************************************************************************************************************

'Bouton ARR de l'interface (Ferme le port de communication, la feuille excel et l'interface)

'**************************************************************************************************************

Private Sub COMDESACTIVE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles COMDESACTIVE.Click

EN_DIS = False INTERF_STAT.BackColor = Color.Red 'Change la couleur du

status en rouge (Desactive) INTERF_STAT.Text = 0 INTERF_STAT.Refresh() SerialPort1.Close() 'Ferme le port rs232 If ExcelACT = True Then MyXL.Quit() 'Ferme la feuille Excel End If Close() 'Ferme l'interface End Sub

'**************************************************************************************************************

'Boucle principale, s'active sur l'evenement du temporisateur Timer1 (1mS) '****************************************************************************************

********************** Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles Timer1.Tick

'*******Declaration des variables:************** Dim Graph As Graphics = PictureBox1.CreateGraphics Dim temp As Integer = 0 Dim temp1 As Integer = 0 Dim Val1 As Integer = 0 Dim Val2 As Integer = 0 Dim A As Integer = 0 Dim B As Integer = 0 Dim C As Integer = 0 Dim D As Integer = 0 Dim M As Integer = 0 Dim F As Integer = 0 Dim G As Integer = 0 Dim H As Integer = 0 Dim I As Integer = 0 Dim J As Integer = 0 Dim K As Integer = 0

Page 74: Rapport final - uqac.ca

3C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

Dim L As Integer = 0 Dim Q As Integer = 0 Dim N As Integer = 0 Dim O As Integer = 0 Dim P As Integer = 0 Dim U As Integer = 0 Dim R As Integer = 0 Dim S As Integer = 0 Dim T As Integer = 0 Dim CNT As Integer = 0 Dim rece As Integer = 0

If EN_DIS = True Then 'Activation de l'interface

'------------------------------------------------------------------------------------------------------------------------

'------------------------------------------------------------------------------------------------------------------------

If Etape = 0 Then 'Configuration de l'angle de depart

ANG_OK.Visible = True 'Affichage du bouton ok (pour envoyer lorsque pret)

ANG_OK.Refresh() If ANG_STAT_OK Then 'Bouton ok appuye ANG_OK.Visible = False 'Masquer le bouton ok ANG_OK.Refresh() SerialPort1.Write(str) 'Envoyer la valeur de la

angulaire de depart SerialPort1.Write("G") SerialPort1.WriteLine(ANG_SP.Value.ToString) SerialPort1.Write(fin) Etape = Etape + 1 'Etape suivante ANG_STAT_OK = 0 End If End If '--------------------------------------------------------------------------------

----------------------------------------- '--------------------------------------------------------------------------------

----------------------------------------- If Etape = 1 Then 'Configuration de la

consigne de charge CRG_OK.Visible = True CRG_OK.Refresh()

warn1.Visible = True 'Affichage clignotant (Ne pas toucher la poignee)

If flash < 20 Then warn1.BackColor = Color.Yellow warn1.Refresh() flash = flash + 1 Else warn1.BackColor = Color.Gainsboro warn1.Refresh() flash = flash + 1 End If

If flash > 40 Then flash = 0 End If

If CHRG_STAT_OK = True Then 'Affichage du bouton ok (pour envoyer lorsque pret)

CRG_OK.Visible = False 'Masquer le bouton ok CRG_OK.Refresh() warn1.Visible = False 'Masquer l'avertissement warn1.Refresh() SerialPort1.Write(str) 'Envoyer la valeur de la

Page 75: Rapport final - uqac.ca

4C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

consigne de charge SerialPort1.Write("L") SerialPort1.WriteLine(CHRG_SP.Value.ToString) SerialPort1.Write(fin) Etape = Etape + 1 'Etape suivante CHRG_STAT_OK = False End If End If '--------------------------------------------------------------------------------

----------------------------------------- '--------------------------------------------------------------------------------

----------------------------------------- If Etape = 2 Then 'Configuration du seuil

EMG MAX_EMG.Visible = True 'Affichage du MAX EMG

(pour envoyer lorsque pret) MAX_EMG.Refresh() act.Visible = True 'Affichage en temps reel

de l'EMG act.Refresh() SP_emg_TAG.Visible = True SP_emg_TAG.Refresh() ACT_EMG.Visible = True ACT_EMG.Refresh() EMG_SP.Visible = True EMG_SP.Refresh()

'-------------------------------------Détection de la chaine de caractère reçu (EMG)------------------------------------

PTR = 0 While PTR < 22 RX_temp = Convert.ToInt16(RXtemp(PTR)) TextBox1.Text = RXtemp If RX_temp = 90 Then '(CR)=13 z=90 Fin de la

transmission If CNT = 20 Then 'Vérification de la

longueur de la chaine recu

EMG(0) = RX(4) 'Mise à jour de la valeur du EMG

EMG(1) = RX(5) EMG(2) = RX(6) EMG(3) = RX(7)

PTR = 22 'EXIT WHILE End If End If

If rece = 1 Then RX(CNT) = RX_temp CNT = CNT + 1 End If

If CNT = 21 Then PTR = 22 End If

PTR = PTR + 1

If RX_temp = 58 Then '(:) Debut de la transmission

CNT = 0 rece = 1 End If

End While

'-----------------------------------------Conversion Ascii vers Hexa EMG-------------------------------------------

Page 76: Rapport final - uqac.ca

5C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

If EMG(0) < 58 Then A = EMG(0) - 48 Else A = (EMG(0) - 65) + 10 End If If EMG(1) < 58 Then B = EMG(1) - 48 Else B = (EMG(1) - 65) + 10 End If If EMG(2) < 58 Then C = EMG(2) - 48 Else C = (EMG(2) - 65) + 10 End If If EMG(3) < 58 Then D = EMG(3) - 48 Else D = (EMG(3) - 65) + 10 End If

'----------------------------------------------------Diagnose RX EMG------------------------------

TextBox2.Text = A 'Affichage des valeurs recu pour diagnostique

TextBox3.Text = B TextBox4.Text = C TextBox5.Text = D

'----------------------------------------------------------------------------------------------------------

temp = ((A * 4096) + (B * 256) + (C * 16) + D) 'Calcul EMG temp1 = (temp / 65536) * 5000 'Conversion pour table

excel 0 à 5000 uV EMG

CntEmgREF = CntEmgREF + 1 'Affichage de la valeur la plus grande

If temp1 > emgTemp Then emgTemp = temp1 End If

If CntEmgREF = 10 Then 'Rafraichissment de la valeur 1/10 pour la voir passer

ACT_EMG.Text = (emgTemp).ToString CntEmgREF = 0 emgTemp = 0 End If

If EMG_STAT_OK = True Then 'Bouton MAX_EMG détecté MAX_EMG.Visible = False 'Masquer bouton MAX_EMG MAX_EMG.Refresh() SerialPort1.Write(str) 'Envoiyer la valeur

MAX_EMG par RS232 SerialPort1.Write("S") SerialPort1.WriteLine(EMG_SP.Text) SerialPort1.Write(fin) Etape = Etape + 1 'Étape suivante act.Visible = False act.Refresh() ACT_EMG.Visible = False ACT_EMG.Refresh() EMG_STAT_OK = False

PTR = 0 XL_File = "C:\Entrainement.xls" 'Création de la feuille

Excel

Page 77: Rapport final - uqac.ca

6C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

NomP = "Entrainement" MyXL = CreateObject("Excel.Application") MyXL.Workbooks.Add() MyXL.Worksheets(1).Name = NomP ExcelACT = True DEM_TR.Visible = True DEM_TR.Refresh() ARR_TR.Visible = True ARR_TR.Refresh() TR_TAG.Visible = True TR_TAG.Refresh() TR_STAT.Visible = True TR_STAT.Refresh() End If End If '--------------------------------------------------------------------------------

----------------------------------------- '--------------------------------------------------------------------------------

----------------------------------------- If Etape = 3 Then 'Demarrage de l'entrainement If TR_STATUS = True Then

'-------------------------------------Détection de la chaine de caractère reçu------------------------------------

PTR = 0 While PTR < 22 RX_temp = Convert.ToInt16(RXtemp(PTR))

If RX_temp = 90 Then 'z=90 Fin de la transmission

If CNT = 20 Then 'Vérification de la longueur de la chaine recu

EMG(0) = RX(4) 'Mise à jour de la valeur du EMG

EMG(1) = RX(5) EMG(2) = RX(6) EMG(3) = RX(7)

LOADC(0) = RX(0) 'Mise à jour de la valeur du LOAD

LOADC(1) = RX(1) LOADC(2) = RX(2) LOADC(3) = RX(3)

ANG(0) = RX(8) 'Mise à jour de la valeur du ANG

ANG(1) = RX(9) ANG(2) = RX(10) ANG(3) = RX(11)

TMRFRESH(0) = RX(12) 'Mise à jour du temp de rafraichissement

TMRFRESH(1) = RX(13) TMRFRESH(2) = RX(14) TMRFRESH(3) = RX(15)

SPCHARGE(0) = RX(16) 'Mise à jour du temp de Consigne Load

SPCHARGE(1) = RX(17) SPCHARGE(2) = RX(18) SPCHARGE(3) = RX(19)

PTR = 22 'EXIT WHILE End If End If

If rece = 1 Then 'Compte du nombre de caractère reçu

Page 78: Rapport final - uqac.ca

7C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

RX(CNT) = RX_temp CNT = CNT + 1 End If

If CNT = 21 Then 'Force la fin de chaine reçu

PTR = 22 End If

PTR = PTR + 1

If RX_temp = 58 Then '(:) Debut de la transmission

CNT = 0 rece = 1 End If

End While

TextBox1.Text = RXtemp 'Affichage de la valeur reçu (diagnostic)

'-----------------------------------------Conversion Ascii vers Hexa EMG-------------------------------------------

If EMG(0) < 58 Then A = EMG(0) - 48 Else A = (EMG(0) - 65) + 10 End If If EMG(1) < 58 Then B = EMG(1) - 48 Else B = (EMG(1) - 65) + 10 End If If EMG(2) < 58 Then C = EMG(2) - 48 Else C = (EMG(2) - 65) + 10 End If If EMG(3) < 58 Then D = EMG(3) - 48 Else D = (EMG(3) - 65) + 10 End If '----------------------------------------Conversion Ascii vers Hexa load

cell--------------------------------------- If LOADC(0) < 58 Then M = LOADC(0) - 48 Else M = (LOADC(0) - 65) + 10 End If If LOADC(1) < 58 Then F = LOADC(1) - 48 Else F = (LOADC(1) - 65) + 10 End If If LOADC(2) < 58 Then G = LOADC(2) - 48 Else G = (LOADC(2) - 65) + 10 End If If LOADC(3) < 58 Then H = LOADC(3) - 48 Else H = (LOADC(3) - 65) + 10 End If

'----------------------------------------Conversion Ascii vers Hexa ANG ---------------------------------------

Page 79: Rapport final - uqac.ca

8C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

If ANG(0) < 58 Then I = ANG(0) - 48 Else I = (ANG(0) - 65) + 10 End If If ANG(1) < 58 Then J = ANG(1) - 48 Else J = (ANG(1) - 65) + 10 End If If ANG(2) < 58 Then K = ANG(2) - 48 Else K = (ANG(2) - 65) + 10 End If If ANG(3) < 58 Then L = ANG(3) - 48 Else L = (ANG(3) - 65) + 10 End If

'----------------------------------------Conversion Ascii vers Hexa Refresh ---------------------------------------

If TMRFRESH(0) < 58 Then Q = TMRFRESH(0) - 48 Else Q = (TMRFRESH(0) - 65) + 10 End If If TMRFRESH(1) < 58 Then N = TMRFRESH(1) - 48 Else N = (TMRFRESH(1) - 65) + 10 End If If TMRFRESH(2) < 58 Then O = TMRFRESH(2) - 48 Else O = (TMRFRESH(2) - 65) + 10 End If If TMRFRESH(3) < 58 Then P = TMRFRESH(3) - 48 Else P = (TMRFRESH(3) - 65) + 10 End If

TMRFRESH_val = ((((Q * 4096) + (N * 256) + (O * 16) + P)) / 100) 'Calcul TMRFRESH

RefreshLBL.Text = TMRFRESH_val.ToString 'Affichage du temps de rafraichissement

'----------------------------------------Conversion Ascii vers Consigne Load ---------------------------------------

If SPCHARGE(0) < 58 Then U = SPCHARGE(0) - 48 Else U = (SPCHARGE(0) - 65) + 10 End If If SPCHARGE(1) < 58 Then R = SPCHARGE(1) - 48 Else R = (SPCHARGE(1) - 65) + 10 End If If SPCHARGE(2) < 58 Then S = SPCHARGE(2) - 48 Else S = (SPCHARGE(2) - 65) + 10 End If If SPCHARGE(3) < 58 Then T = SPCHARGE(3) - 48 Else

Page 80: Rapport final - uqac.ca

9C:\Users\Ben\Desktop\Ecole_2\Projet de ... de progrès\Jacques Paradis\Code_Interface.vb

T = (SPCHARGE(3) - 65) + 10 End If

SPCHARGE_val = ((U * 4096) + (R * 256) + (S * 16) + T) 'Calcul Consigne charge g

'----------------------------------------------------Diagnose RX EMG TextBox2.Text = A TextBox3.Text = B TextBox4.Text = C TextBox5.Text = D '----------------------------------------------------Diagnose RX LOADC TextBox9.Text = M TextBox8.Text = F TextBox7.Text = G TextBox6.Text = H '----------------------------------------------------Diagnose RX Ang TextBox13.Text = I TextBox12.Text = J TextBox11.Text = K TextBox10.Text = L '------------------------------------------------------------------------

---------------------------------- temp = ((A * 4096) + (B * 256) + (C * 16) + D) 'Calcul EMG temp1 = (temp / 65536) * 5000 'Conversion pour

table excel 0 à 5000uV EMG emgstatval.Text = ((temp1 / Maximum_emgVAL) * 100) temp = ((temp1 / Maximum_emgVAL) * 264) 'Calcul de la

position Y en pixel MyXL.Worksheets(NomP).Cells(count, R1) = temp1 Y2 = (264 - temp) Y7 = (264 - (((Maximum_emgVAL * 0.3) / Maximum_emgVAL) * 264)) 'Calcul de

la consigne EMG 30%

temp = ((M * 4096) + (F * 256) + (G * 16) + H) 'Calcul Load temp1 = (temp) 'Calcul Load pour

table excel 0 à 30000 g crgstatval.Text = temp1 temp = (temp1 / 30000) * 264 'Calcul de la

position Y en pixel MyXL.Worksheets(NomP).Cells(count, R2) = temp1 Y4 = (530 - temp) Y8 = (530 - ((SPCHARGE_val / 30000) * 264)) 'Calcul de la

consigne de Charge

temp = ((I * 4096) + (J * 256) + (K * 16) + L) 'Calcul Ang angstatval.Text = temp temp1 = (temp / 90) * 264 'Calcul de la

position Y en pixel MyXL.Worksheets(NomP).Cells(count, R3) = temp 'Calcul angulaire

table excel 0 à 100 deg Y6 = (796 - temp1) X2 = X1 + 1 'Incrémentation de la

position en X en pixel

Graph.DrawLine(Pens.Red, X1, Y1, X2, Y2) 'Dessiner les trois courbes à l'écran point (x1,y1) vers (x2,y2)

Graph.DrawLine(Pens.Red, X1, Y7, X2, Y10) 'Dessiner les SP Graph.DrawLine(Pens.Red, X1, Y7 + 1, X2, Y10 + 1) 'Dessiner les

SP Graph.DrawLine(Pens.Red, X1, Y7 + 2, X2, Y10 + 2) 'Dessiner les

SP

Graph.DrawLine(Pens.Green, X1, Y3, X2, Y4) Graph.DrawLine(Pens.Red, X1, Y8, X2, Y11) 'Dessiner les SP Graph.DrawLine(Pens.Red, X1, Y8 + 1, X2, Y11 + 1) 'Dessiner les

SP

Page 81: Rapport final - uqac.ca

10C:\Users\Ben\Desktop\Ecole_2\Projet de ...de progrès\Jacques Paradis\Code_Interface.vb

Graph.DrawLine(Pens.Red, X1, Y8 + 2, X2, Y11 + 2) 'Dessiner les SP

Graph.DrawLine(Pens.Blue, X1, Y5, X2, Y6)

Y5 = Y6 'Enregistrement de la valeur actuelle

Y3 = Y4 Y1 = Y2 X1 = X2

Y10 = Y7 'Enregistrement de la valeur actuelle

Y11 = Y8

If X1 > 1200 Then 'Rafraichissement de l'écran en fin d'image X=1200

X1 = 5 PictureBox1.Refresh() End If count = count + 1 'Compteur du nombre

de pixel parcouru en X If count > 1200 Then 'Changement de

colonne de la table excel pour chaque fin de page. count = 1 R1 = R1 + 4 R2 = R2 + 4 R3 = R3 + 4 End If End If End If End If End Sub

'***********************************************************************************************************

'Boucle de récéption de données du port RS232 '****************************************************************************************

******************* Private Sub dataRX(ByVal sender As System.Object, ByVal e As System.IO.Ports.

SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived If EN_DIS = True Then RXtemp = SerialPort1.ReadExisting.ToCharArray SerialPort1.DiscardInBuffer() End If End Sub

'***********************************************************************************************************

'Détection du bouton ANG_OK (Angle initial) '****************************************************************************************

******************* Private Sub ANG_OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles ANG_OK.Click ANG_STAT_OK = True End Sub

'***********************************************************************************************************

'Détection du bouton CRC_OK (Consigne de charge) '****************************************************************************************

******************* Private Sub CRG_OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles CRG_OK.Click CHRG_STAT_OK = True End Sub

Page 82: Rapport final - uqac.ca

11C:\Users\Ben\Desktop\Ecole_2\Projet de ...de progrès\Jacques Paradis\Code_Interface.vb

'***********************************************************************************************************

'Détection du bouton MAX_EMG (Maximum du seuil EMG) '****************************************************************************************

******************* Private Sub MAX_EMG_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

Handles MAX_EMG.Click Dim cnt As Integer = 0 Dim EMG_LENGTH As Integer = EMG_SP.TextLength EMG_STAT_OK = True Maximum_emg = EMG_SP.Text.ToCharArray

For cnt = 1 To EMG_LENGTH Maximum_emgint(EMG_LENGTH - (cnt)) = Convert.ToInt16(Maximum_emg(cnt - 1)) Next

For cnt = (EMG_LENGTH + 1) To 4 Maximum_emgint(cnt - 1) = 48 Next

'Permet d'afficher la consigne de l'emg 30% de MAX EMG '----------------------------------------Conversion Ascii vers Decimal --------------

--------------------- Maximum_emgVAL = (((Maximum_emgint(3) - 48) * 1000) + ((Maximum_emgint(2) - 48) *

100) + ((Maximum_emgint(1) - 48) * 10) + (Maximum_emgint(0) - 48)) 'Calcul EMG

End Sub

'***********************************************************************************************************

'Détection du bouton DEM_ENT (Démarrer entrainement) '****************************************************************************************

*******************

Private Sub DEM_TR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DEM_TR.Click

TR_STAT.BackColor = Color.Lime 'Change la couleur du status de l'entrainement (vert)

TR_STAT.Text = 1 TR_STAT.Refresh() SerialPort1.Write(str) 'Envoie la valeur ONN

(Démarrage de l'entrainement) SerialPort1.Write(ONN) SerialPort1.WriteLine(fin) TR_STATUS = 1 End Sub

'***********************************************************************************************************

'Détection du bouton ARR_ENT (Arrêt de l'entrainement) '****************************************************************************************

*******************

Private Sub ARR_TR_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ARR_TR.Click

TR_STATUS = 0 TR_STAT.BackColor = Color.Red 'Change la couleur du

status de l'entrainement (rouge) TR_STAT.Text = 0 TR_STAT.Refresh() SerialPort1.Write(str) 'Envoie la valeur OFF

(Arrêt de l'entrainement) SerialPort1.Write(OFF) SerialPort1.WriteLine(fin) End Sub

'***********************************************************************************************************

'Détection du bouton Remise à zéro (Redémarrage de l'entraînement)

Page 83: Rapport final - uqac.ca

12C:\Users\Ben\Desktop\Ecole_2\Projet de ...de progrès\Jacques Paradis\Code_Interface.vb

'***********************************************************************************************************

Private Sub Reset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Reset.Click

If EN_DIS = 1 Then 'Arrêt de l'interface SerialPort1.Write(str) SerialPort1.Write(OFF) 'Envoie la valeur OFF

(Arrêt de l'entrainement) SerialPort1.WriteLine(fin) SerialPort1.Close() End If

Etape = 0 'Retour à l'étape 0 et réinitialisation des affichages

DEM_TR.Visible = False DEM_TR.Refresh() ARR_TR.Visible = False ARR_TR.Refresh() TR_TAG.Visible = False TR_TAG.Refresh() TR_STAT.Visible = False TR_STAT.Refresh() act.Visible = False act.Refresh() ACT_EMG.Visible = False ACT_EMG.Refresh() ANG_OK.Visible = False ANG_OK.Refresh() CRG_OK.Visible = False CRG_OK.Refresh() MAX_EMG.Visible = False MAX_EMG.Refresh() act.Visible = False act.Refresh() SP_emg_TAG.Visible = False SP_emg_TAG.Refresh() warn1.Visible = False warn1.Refresh()

Dim X1 As Integer = 5 'Réinitialisation des variables

Dim Y1 As Integer = 264 Dim X2 As Integer = 5 Dim Y2 As Integer = 264 Dim Y3 As Integer = 530 Dim Y4 As Integer = 530 Dim Y5 As Integer = 796 Dim Y6 As Integer = 796 Dim Y7 As Integer = 264 Dim Y8 As Integer = 530 Dim Y9 As Integer = 796 Dim Y10 As Integer = 264 Dim Y11 As Integer = 530 Dim Y12 As Integer = 796 PictureBox1.Refresh() End Sub

End Class

Page 84: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Asservissement(1).c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À REÇU******************************************************************************************************/

extern Envoi_Vitess_drive(signed long ADRES);extern Envoi_Accel_drive(signed long ADRES2);extern Convert_to_hex_Drive(unsigned char caractere2[]);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS ACCESSIBLE DANS TOUT LE PROGRAMME*****************************************************************************************************/extern WriteUART_to_RS232(void);extern RXLoadC(void); //Get Loadc Valueextern INIT_ADs_SPI(void); //Get EMG Valueextern AffCONSIGNE(void);extern ZERO_VITESSE (void);

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/

extern unsigned int LCSPIRX; //Valeur recu Load Cellextern unsigned int EMG; //Valeur recu EMGextern unsigned int Consigne_load_Hexa; //Valeur de la consigne de chargeextern unsigned int Consigne_seuil_Hexa; //Valeur de la consigne du seuilextern unsigned int start_load; //Application de la force initialextern unsigned int up_down; //Sens de l'exerciceextern unsigned int RS;extern unsigned int ZERO_LOAD;extern unsigned int STAT_RECEI;extern unsigned int Reel_pos_Read; extern unsigned int POSI;extern unsigned int SP_load;extern unsigned int RXsel;extern unsigned int x;

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME ET UTILISÉ DANS CELUI-CI*****************************************************************************************************/extern unsigned char ReceivedData[];extern unsigned char PositionData[];extern unsigned char Read_speed_ASCII[];

/**************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 4 294 967 295)**************************************************************************************************************/extern unsigned long Seuil_Trente_Hexa; //Valeur de 30% du seuil

/*************************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (-2 147 483 648 À 2 147 483 647)*************************************************************************************************************************/extern signed long Read_speed_Calc;extern signed long Coco;extern signed long Diff_Hexa_Calc;extern signed long Zero_Speed;extern signed long SP_vit;extern signed long Accel_Val_MIN; extern signed long Acceleration; extern signed long Vit_act;

1

Page 85: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Asservissement(1).c

/*************************************************************************************************************************DÉCLARATION DES VARIABLES EN POINT FLOTTANT (1.17549*10e-38 À 8.5*10e37)*************************************************************************************************************************/extern float depass; //Depassement de la valeur seuil de l'emg en %extern float SP_EMG;extern float Delta_force;extern float facteur; //cnt/sec; //Facteur de correction du systeme (0.007136 tr/N*s * 2000)extern float EMG_CORR_GAIN;extern float LOAD_CORR_GAIN;extern float ACCEL_GAIN;extern float LOAD;extern float tempload = 0;

/*****************************************************************************************************DÉCLARATION DES FONCTIONS DE DÉLAI*****************************************************************************************************/

extern Delay5ms (int);extern Delay5us (int);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS RELIÉES SEULEMENT SUR CETTE FEUILLE*****************************************************************************************************/

void convert_load(void);void Asservi(void);

/******************************ENTRÉE DANS LA ROUTINE DE CONVERSION DE LA VALEUR DE LA CHARGE***************************************

CETTE ROUTINE PERMET DE CONVERTR LES DONNÉE PROVENANT DE LA CELLULE DE CHARGE. LES DONNÉES ARRIVE EN BINAIRE VIA LE POR SPI ET DOIVENT ÊTRE TRAITÉES POUR REPRÉSENTER UNE VRAI VALEUR DE CHARGE.

***********************************************************************************************************************************/

void convert_load(void){

if(up_down==1) //30Kg = 10mV = 0.33333333mV / Kg{

if (LCSPIRX>=ZERO_LOAD) //Si valeur lu est plus grande ou égale à 0x8000

{LOAD=(LCSPIRX-ZERO_LOAD)*3.5763; //0.004768mV/Div (pour 10mV la

plage est de 2097 division) POUR GAIN DE 16

if (LOAD > 10000){

LOAD =10000;} //0.0023842mV/Div (pour 10mV la

plage est de 4194 division) POUR GAIN DE 32}

//(0.004768(mV/div)/.333333(mV/Kg))*1000(g/Kg) =14.304(g/Div) POUR GAIN DE 16

//0.0023842mV/Div/.333333(mV/Kg))*1000(g/Kg) =7.152629(g/Div) POUR GAIN DE 32else //Si valeur lu est plus grande

que 0x8000{LOAD = 0x0000;}

}

else

{if (LCSPIRX<ZERO_LOAD) //Si valeur lu est plus PETITE ou

égale à 0x8000

2

Page 86: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Asservissement(1).c

{LOAD=(ZERO_LOAD-LCSPIRX)*3.5763; //0.004768mV/Div (pour 10mV la

plage est de 2097 division) POUR GAIN DE 16//0.0023842mV/Div (pour 10mV la

plage est de 4194 division) POUR GAIN DE 32if (LOAD > 10000){

LOAD =10000;}

//(0.002384(mV/div)/.333333(mV/Kg))*1000(g/Kg) =14.304(g/Div) POUR GAIN DE 1

}

else //Si valeur lu est plus petite que 0x8000

{LOAD = 0x0000;}

}

}/*************************************ENTRÉE DANS LA ROUTINE D'ASSERVISSEMENT******************************************************

CETTE ROUTINE PERMET LE CONTRÔLE DU SYSTÈME, C'EST À DIRE QU'ELLE EFFECTUE LES CALCULS NÉCESSAIRES POUR DÉTERMINER LES VITESSES ET ACCELLÉRATION À ENVOYER AU VARIATEUR DE VITESSSE POUR LE MAINTIENT DE LA CHARGE RÉEL LE PLUS PRÈS POSSIBLE DE LA CONSIGNE.

***********************************************************************************************************************************/void Asservi(void){

float EMG_CALC = 0;

if(!PORTBbits.RB5) //Lecture de la cellule de charge LORSQUE LE A/D EST PRÈS

{RXLoadC(); //APPEL DE LA

FONCTION DE LECURE DU A/Dconvert_load(); //APPEL À LA FONCTION

DE CONVERSION DES DONNÉES RECU PAR LA CELLULE EN VALEUR DE CHARGE RÉEL }

if(!PORTBbits.RB5) //Lecture de la cellule de charge LORSQUE LE A/D EST PRÈS

{RXLoadC(); //APPEL DE LA

FONCTION DE LECURE DU A/Dconvert_load(); //APPEL À LA FONCTION

DE CONVERSION DES DONNÉES RECU PAR LA CELLULE EN VALEUR DE CHARGE RÉEL }INIT_ADs_SPI(); //APPEL DE LA

FONCTION DE Lecture de l'EMG

EMG_CALC = EMG; //TRANSFERT DE LA DONNÉE ENTIÈRE EN DONNÉE POINT FLOTTANT POUR TRAITEMENT

if(EMG_CALC>SP_EMG) //Ajustement de la charge en fonction DU SEUIL EMG (30% DU MAX)

{depass=(((EMG_CALC-SP_EMG)/SP_EMG) * EMG_CORR_GAIN);SP_load=(SP_load-(depass*SP_load));

}else

{SP_load=SP_load; //SI PAS DE

DÉPASSEMENT, LA CONSIGNE DE CHARGE NE CHANGE PAS}

RXsel=0; //REMISE DES POINTEUR

3

Page 87: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Asservissement(1).c

À ZÉRO AVANT DE CONTINUER LE PROGRAMMEReel_pos_Read=0;RS =0;

Read_speed(); //APPEL DE LA ROUTINE QUI EFFECTUE LA LECTURE DE LA VITESSE ACTUELLE DU MOTEUR DANS LE VARIATEUR DE VITESSE

while(!RS); //ATTENTE QUE LA VITESSE SOIT ENTRÉE

for(x=0;x<8;x++){Read_speed_ASCII[x]=ReceivedData[x+6]; //Transfert de la

vitesse ASCII en ASCII 8 caractère pour convertion}

Convert_to_hex_Drive(Read_speed_ASCII); //Convertion de la vitesse ASCII en vitesse Hexadecimale

Vit_act = Read_speed_Calc; //TRANSFERT DE VARIABLE SERVANT SEULEMENT POUR LE TRAITEMENT

if(up_down==1) //SI LE SYSTÈME EST EN MONTER, FAIRE UN COMPLÉMENT À DEUX SUR LA VITESSE AVANT DE LA TRAITER

{Vit_act=(0xFFFFFFFF-(Vit_act-1)); //Complement a 2}

if(LOAD<SP_load) //Ajustement de la vitesse du moteur en fonction de la consigne de la charge, SI LA VALEUR ACTUELLE EST SOUS LA CONSIGNE

{Delta_force=(SP_load-LOAD);SP_vit=(Vit_act-(Delta_force*facteur*LOAD_CORR_GAIN));

if(SP_vit<=0) //SI LA CONSIGNE DE VITESSE EST EN DESSOUS DE ZÉRO, LA METTRE À ZÉRO POUR ÉVITER LES OSCILLATIONS

{ZERO_VITESSE(); //APPEL DE LA

FONCTION QUI ENVOI UNE CONSIGNE DE VITESSE ZÉRO AU VARIATEUR DE VITESSE}else

{Envoi_Vitess_drive(SP_vit); //Envoi de la

nouvelle consigne de vitesseWriteUART_to_RS232();Delay5us(1200);

}}

else //Ajustement de la vitesse du moteur en fonction de la consigne de la charge, SI LA VALEUR ACTUELLE EST AU DESSUS DE LA CONSIGNE

{Delta_force=(LOAD-SP_load);SP_vit=(Vit_act+(Delta_force*facteur*LOAD_CORR_GAIN));

if(SP_vit>=0x00061A80) //Detection de vitesse ZERO

{Envoi_Vitess_drive(0x00061A80); //SI LA CONSIGNE DE

VITESSE EST EN DESSUS DE CE SEUIL, LA METTRE À CE SEUIL LA CONSIGNE DE VITESSE}else

{Envoi_Vitess_drive(SP_vit); //Envoi de la

nouvelle consigne de vitesseWriteUART_to_RS232();Delay5us(1200);

}}

Acceleration = (Accel_Val_MIN+(Delta_force*facteur*ACCEL_GAIN)); //TRAITEMENT

4

Page 88: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Asservissement(1).c

DE LA CONSIGNE D'ACCÉLÉRATIONEnvoi_Accel_drive(Acceleration); //ENVOI DE LA NOUVELLE VALEUR

D'ACCÉLÉRATIONWriteUART_to_RS232();Delay5us(1500);

AffCell(); //ROUTINE DE TRANSFERT DES

DONNÉES DE LA CELLULE DANS VARIABLE DE TANSFERT ASCIIAffEMG(); //ROUTINE DE TRANSFERT DES

DONNÉES DE L'EMG DANS VARIABLE DE TANSFERT ASCIIAffPOSI(); //ROUTINE DE TRANSFERT DES

DONNÉES DE LA POSITION DANS VARIABLE DE TANSFERT ASCIIAffCONSIGNE(); //ROUTINE DE TRANSFERT DES

DONNÉES DE LA CONSIGNE DE CHARGE DANS VARIABLE DE TANSFERT ASCIIWriteUART2_to_RS232();

}

5

Page 89: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Communication_SPI.c

/*; © 2005 Microchip Technology Inc.;; Microchip Technology Inc. (“Microchip”) licenses this software to you; solely for use with Microchip dsPIC® digital signal controller; products. The software is owned by Microchip and is protected under; applicable copyright laws. All rights reserved.;; SOFTWARE IS PROVIDED “AS IS.” MICROCHIP EXPRESSLY DISCLAIMS ANY; WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A; PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP; BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL; DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF; PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS; BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),; ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.;;;FILE DESCRIPTION:; This file provides low-leve SPI drivers to interface to the 30F2011; that controls the text-based 4-bit parallel LCD on the dsPICDEM2; development board.;;REVISION HISTORY:; $Log: SPI_for_LCD.c,v $; Revision 1.1.1.1 2005/06/06 09:16:45 VasukiH; First release of software;;*/

//Pre-Processor Directives:#include <p30fxxxx.h>#include "system.h"#include "spi.h"

/*****************************************************************************************************DÉCLARATION DES FONCTIONS DE DÉLAI*****************************************************************************************************/

extern Delay5ms (int);extern Delay5us (int);

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME ET UTILISÉ SUR CETTE FEUILLE*****************************************************************************************************/extern unsigned char Status[];extern unsigned char aff[];

/*****************************************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME ET UTILISÉS SUR CETTE FEUILLE (0 À 65535)*****************************************************************************************************************************/extern unsigned int EMG;extern unsigned int EMG1;extern unsigned int EMG2;extern unsigned int EMG3;extern unsigned int TAMPON;

/*****************************************************************************************************DÉCLARATION ROUTINE UTILISÉES DANS CETTE FEUILLE*****************************************************************************************************/void READ_SPI1BUF(void);void INIT_ADs_SPI(void);void SPI_Init(void);

/*****************************************************************************************************DÉCLARATION ROUTINE UTILISÉES QUI RECOIVENT ET RENVOIT DES VARIABLES DANS CETTE FEUILLE

1

Page 90: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Communication_SPI.c

*****************************************************************************************************/unsigned int LSBYTE(unsigned int);unsigned int CSBYTE(unsigned int);unsigned int MSBYTE(unsigned int);

/*-----------------------------------------------------------------------------------------------------------------INITIALISER La Com SPI-------------------------------------------------------------------------------------------------------------------*/void SPI_Init(void){ SPI1STAT = 0x0000; SPI1CON = 0x0021; //Set the SPI1 module to 8-bit Master mode IFS0bits.SPI1IF = 0; //Clear the SPI1 Interrupt Flag IEC0bits.SPI1IE = 0; //SPI1 ISR processing is not enabled. //SPI1 will be used in polling-mode SPI1STATbits.SPIEN = 1; //Turn on the SPI1 module}/*-----------------------------------------------------------------------------------------------------------------EFFECTUER LACOMMUNICATION AVEC LE ADs EMG-------------------------------------------------------------------------------------------------------------------*/void INIT_ADs_SPI(void){

unsigned int msbytev;unsigned int csbytev;unsigned int lsbytev;

LATBbits.LATB4 = 0; //SORTIE PERMETTANT DE SÉLECTIONNER LE CONVERTISSEUR DE L'EMG (EN FONCTION)

TAMPON = SPI1BUF; //VARIABLE PERMETTANT DE VIDER LE "BUFFER" SPI

msbytev = MSBYTE(0x0000); //DÉMARRER LA COMMUNICATION SPI POUR RECEVOIR LE MOST SIGNIFIANT BYTE

csbytev = CSBYTE(0x0000); //DÉMARRER LA COMMUNICATION SPI POUR RECEVOIR LE CENTER BYTE

lsbytev = LSBYTE(0x0000); //DÉMARRER LA COMMUNICATION SPI POUR RECEVOIR LE LESS SIGNIFIANT BYTE

Delay5us (1);LATBbits.LATB4 = 1; //SORTIE PERMETTANT DE SÉLECTIONNER LE CONVERTISSEUR DE L'EMG

(HORS FONCTION)

/*****************************************************Traitement des données EMG pour les mettre sur 16 bits*****************************************************/ msbytev = msbytev << 12;msbytev = msbytev & 0xF000;

csbytev = csbytev << 4;csbytev = csbytev & 0x0FF0;

lsbytev = lsbytev >> 4;lsbytev = lsbytev & 0x000F;

EMG = lsbytev + csbytev + msbytev;

}/*-----------------------------------------------------------------------------------------------------------------LECTURE DU MSBYTE-------------------------------------------------------------------------------------------------------------------*/unsigned int MSBYTE(unsigned int TEMP1){

2

Page 91: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Communication_SPI.c

SPI1BUF = TEMP1;while (!SPI1STATbits.SPIRBF);return SPI1BUF;

}/*-----------------------------------------------------------------------------------------------------------------LECTURE DU CSBYTE-------------------------------------------------------------------------------------------------------------------*/unsigned int CSBYTE(unsigned int TEMP3){

SPI1BUF = TEMP3;while (!SPI1STATbits.SPIRBF);return SPI1BUF;

}/*-----------------------------------------------------------------------------------------------------------------LECTURE DU LSBYTE-------------------------------------------------------------------------------------------------------------------*/unsigned int LSBYTE(unsigned int TEMP2){

SPI1BUF = TEMP2;while (!SPI1STATbits.SPIRBF);return SPI1BUF;

}

3

Page 92: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

//Pre-Processor Directives:#include <p30f4011.h>#include "system.h"

/*****************************************************************************************************DÉCLARATION DES FONCTIONS ACCESSIBLE DANS TOUT LE PROGRAMME*****************************************************************************************************/extern WriteUART1(unsigned int data);extern WriteUART_to_RS232(void);

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/extern unsigned int cons_ang_stat;extern unsigned int cons_load_stat;extern unsigned int cons_seuil_stat;extern unsigned int First_pos_Read;extern unsigned int Long;extern unsigned int STAT_RECEI;extern unsigned int Posi_init;extern unsigned int Consigne_seuil_Hexa;extern unsigned int Consigne_load_Hexa;extern unsigned int Reel_pos_Read; extern unsigned int RS;extern unsigned int up_down;extern unsigned int j; extern unsigned int l; extern unsigned int TimeScan;extern unsigned int SP_load;

/*************************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (-32768 À 32767)**************************************************************************************************************/extern signed int Potentiometer;extern signed int EMG;extern signed int EMG1;extern signed int EMG2;extern signed int EMG3;extern signed int LCSPIRX;extern signed int POSI;

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME ET UTILISÉ DANS CETTE FEUILLE*****************************************************************************************************/extern unsigned char Status[];extern unsigned char DisplayData[];extern unsigned char Donnee_DEC[];extern unsigned char Donnee_HEX[];extern unsigned char REFRESHVAL[];extern unsigned char consigne_posi[];extern unsigned char consigne_load[];extern unsigned char consigne_seuil[];extern unsigned char REELPosition[];extern unsigned char Read_speed_ASCII[];

/**************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 4 294 967 295)**************************************************************************************************************/extern unsigned long Consigne_ang_Hexa;extern unsigned long Zero_Speed;extern unsigned long Consigne_Pulse;

/*************************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (-2 147 483 648 À 2 147 483 647)

1

Page 93: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

*************************************************************************************************************************/extern signed long Donnee_Hexa_Calc;extern signed long Zero_Hexa_Calc;extern signed long Reel_Hexa_Calc;extern signed long Diff_Hexa_Calc;extern signed long Read_speed_Calc;extern signed long TEMP_DEEEEEE;

/*************************************************************************************************************************DÉCLARATION DES VARIABLES EN POINT FLOTTANT (1.17549*10e-38 À 8.5*10e37)*************************************************************************************************************************/extern float LOAD;

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À REÇU******************************************************************************************************/

void Convert_to_hex(unsigned char caractere[]);void Convert_to_hex_Drive(unsigned char caractere2[]);void Consigne_Char(unsigned char caractere1[]);void Reel_Pulse_Posi(unsigned char caractere3[]);void Convert_Angle_Pulse(unsigned long ANGLE);void Envoi_Vitess_drive(signed long ADRES);void Envoi_Accel_drive(signed long ADRES2);void soft_overtravel_positif (signed long ADRES3);void soft_overtravel_negatif (signed long ADRES4);void soft_overtravel_pos_limit (signed long ADRES5);void soft_overtravel_neg_limit (signed long ADRES6);void MINIMUM_POSI(signed long ADRES7);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS UTILISÉS SUR CETTE FEUILLE *****************************************************************************************************/void AffCell(void);void AffEMG(void);void AffPOSI(void);void AffREFRESH(void);void AffCONSIGNE(void);void Checksum(void);void Checksum_LONG(void);

//**************************************************************************************************************************//Envoi de la charge réel à l'interface//**************************************************************************************************************************void AffCell(void){ //unsigned int val = LCSPIRX;

unsigned int val = LOAD;unsigned int tmp = 0x0000;

tmp= val & 0x000F;

if (tmp<=9){ tmp+=0x30;}

else {

tmp+=0x37; }

REFRESHVAL[4]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

2

Page 94: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

if (tmp<=9) { tmp+=0x30;}

else { tmp+=0x37;}REFRESHVAL[3]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9){ tmp+=0x30;}

else {tmp+=0x37;

} REFRESHVAL[2] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{ tmp+=0x37;

} REFRESHVAL[1]=tmp;

REFRESHVAL[21]=0x5A;REFRESHVAL[22]=0x00;

}

//**************************************************************************************************************************//Envoi des données EMG à l'interface//**************************************************************************************************************************void AffEMG(void){ unsigned int val = EMG;

unsigned int tmp = 0x0000;

//Conv char0

tmp= val & 0x000F; if (tmp<=9)

{tmp+=0x30;}

else{

tmp+=0x37; }

REFRESHVAL[8]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) { tmp+=0x30;}

else

3

Page 95: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

{ tmp+=0x37;}REFRESHVAL[7]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) { tmp+=0x30;}

else{ tmp+=0x37;

} REFRESHVAL[6] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{ tmp+=0x37;}

REFRESHVAL[5]=tmp;

REFRESHVAL[21]=0x5A;REFRESHVAL[22]=0x00;

}

//**************************************************************************************************************************//Envoi de la position à l'interface//**************************************************************************************************************************void AffPOSI(void){ unsigned int val = POSI;

unsigned int tmp = 0x0000;

//Conv char0

tmp= val & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{

tmp+=0x37;}

REFRESHVAL[12]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9){ tmp+=0x30;}

else { tmp+=0x37;}REFRESHVAL[11]=tmp;

4

Page 96: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) { tmp+=0x30;}

else{ tmp+=0x37;

} REFRESHVAL[10] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{ tmp+=0x37;}

REFRESHVAL[9]=tmp;

REFRESHVAL[21]=0x5A;REFRESHVAL[22]=0x00;

}

//**************************************************************************************************************************//Envoi du time-scan à l'interface//**************************************************************************************************************************void AffREFRESH(void){ unsigned int val = TimeScan;

unsigned int tmp = 0x0000;

//Conv char0

tmp= val & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{

tmp+=0x37;}

REFRESHVAL[16]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9){ tmp+=0x30;}

else { tmp+=0x37;}REFRESHVAL[15]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) { tmp+=0x30;

5

Page 97: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

} else

{ tmp+=0x37;

} REFRESHVAL[14] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{ tmp+=0x37;}

REFRESHVAL[13]=tmp;

REFRESHVAL[21]=0x5A;REFRESHVAL[22]=0x00;

}

//**************************************************************************************************************************//Envoi de la consigne de charge à l'interface//**************************************************************************************************************************void AffCONSIGNE(void){ unsigned int val = SP_load;

unsigned int tmp = 0x0000;

//Conv char0

tmp= val & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{

tmp+=0x37;}

REFRESHVAL[20]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9){ tmp+=0x30;}

else { tmp+=0x37;}REFRESHVAL[19]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) { tmp+=0x30;}

else{ tmp+=0x37;

}

6

Page 98: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

REFRESHVAL[18] =tmp; //Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

{ tmp+=0x30;}

else{ tmp+=0x37;}

REFRESHVAL[17]=tmp;

REFRESHVAL[21]=0x5A;REFRESHVAL[22]=0x00;

}

//**************************************************************************************************************************//Envoi de la vitesse au variateur de vitesse//**************************************************************************************************************************void Envoi_Vitess_drive(signed long ADRES){

signed long val=0; signed long tmp;

val = ADRES;

//REV COMPLEMENT A 2 DE LA CONSIGNEif (up_down==1)

{val=(0xFFFFFFFF-val)+1;}

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x36; // Caractère ASCII "6" >>Adresse du régistre dans la driveDisplayData[5] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) tmp+=0x30;

7

Page 99: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

else tmp+=0x37;

DisplayData[12] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;

}

//**************************************************************************************************************************//Imposition de la position minimum d'arret//**************************************************************************************************************************

void MINIMUM_POSI(signed long ADRES7){

signed long val=0;signed long tmp;

8

Page 100: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

val = ADRES7;val = (0xFFFFFFFF-val)+1;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x31; // Caractère ASCII "1" >>Adresse du régistre dans la driveDisplayData[4] = 0x35; // Caractère ASCII "5" >>Adresse du régistre dans la driveDisplayData[5] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Position mINIMALEDisplayData[7] = 0x30; //0 DisplayData[8] = 0x31; //1

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[16]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[15]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[14] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[13]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[12]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

9

Page 101: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

DisplayData[11]=tmp;

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[9]=tmp;

Checksum_LONG();DisplayData[19]=0x0D;DisplayData[20]=0x00;

}

//**************************************************************************************************************************//ENVOIE DE LA RAMPE D'ACCÉLÉRATION//**************************************************************************************************************************void Envoi_Accel_drive(signed long ADRES2){

signed long val=0;signed long tmp;

val = ADRES2;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x36; // Caractère ASCII "6" >>Adresse du régistre dans la driveDisplayData[5] = 0x45; // Caractère ASCII "E" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

10

Page 102: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[12] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;//DisplayData[19]=0x00;

}

//**************************************************************************************************************************//Envoie des consignes des limites Soft travels POSITIVES//**************************************************************************************************************************void soft_overtravel_positif (signed long ADRES3){

11

Page 103: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

signed long val=0;signed long tmp;

val = ADRES3;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la driveDisplayData[5] = 0x38; // Caractère ASCII "8" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[12] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

12

Page 104: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;//DisplayData[19]=0x00;

}

//**************************************************************************************************************************//Envoie des consignes des limites Soft travels NEGATIVES//**************************************************************************************************************************void soft_overtravel_negatif (signed long ADRES4){

signed long val=0;signed long tmp;

val = ADRES4;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la driveDisplayData[5] = 0x39; // Caractère ASCII "9" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

13

Page 105: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[12] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;//DisplayData[19]=0x00;

}

//**************************************************************************************************************************//Envoie des consignes des distances limites Soft travels POSITIVES//**************************************************************************************************************************void soft_overtravel_pos_limit (signed long ADRES5){

signed long val=0;

14

Page 106: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

signed long tmp;

val = ADRES5;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la driveDisplayData[5] = 0x41; // Caractère ASCII "A" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[12] =tmp;

//Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

15

Page 107: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;//DisplayData[19]=0x00;

}

//**************************************************************************************************************************//Envoie des consignes des distances limites Soft travels NÉGATIVES//**************************************************************************************************************************void soft_overtravel_neg_limit (signed long ADRES6){

signed long val=0;signed long tmp;

val = ADRES6;

DisplayData[0] = 0x3A; // Caractère ASCII ":"DisplayData[1] = 0x30; // Caractère ASCII "0" >>Adresse de la driveDisplayData[2] = 0x30; // Caractère ASCII "0" >>Adresse de la drive

DisplayData[3] = 0x30; // Caractère ASCII "0" >>Adresse du régistre dans la driveDisplayData[4] = 0x44; // Caractère ASCII "D" >>Adresse du régistre dans la driveDisplayData[5] = 0x42; // Caractère ASCII "B" >>Adresse du régistre dans la drive

DisplayData[6] = 0x31; // Caractère ASCII "1" >>Fonction écrire dans le régistre sélectionné

//Conv char0 tmp= val & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[14]=tmp;

//Conv char1tmp= val>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[13]=tmp;

//Conv char2 tmp= val>>8 & 0x000F;

if (tmp<=9)

16

Page 108: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

tmp+=0x30; else

tmp+=0x37;

DisplayData[12] =tmp; //Conv char3

tmp= val>>12 & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[11]=tmp;

//Conv char4 tmp=val >>16 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[10]=tmp;

//Conv char5 tmp=val >>20 & 0x000F;

if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[9]=tmp;

//Conv char6 tmp=val >>24 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[8]=tmp;

//Conv char7 tmp=val >>28 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[7]=tmp;

Checksum();

DisplayData[17]=0x0D;DisplayData[18]=0x00;

}

//**************************************************************************************************************************//Conversion des caractères ASCII représentant des décimales en binaire //**************************************************************************************************************************void Convert_to_hex(unsigned char caractere[]){ unsigned long val=0;

unsigned int c,d,e=0;unsigned int

17

Page 109: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

tmp0=0x0000,tmp1=0x0000,tmp2=0x0000,tmp3=0x0000,tmp4=0x0000,tmp5=0x0000,tmp6=0x0000,tmp7=0x0000;unsigned int temp=0x0000;

for(c=0;c<4;c++){

Donnee_DEC[c] = caractere[c]-48;}

tmp0 = Donnee_DEC[3];

tmp1 = Donnee_DEC[2];

tmp2 = Donnee_DEC[1];

tmp3 = Donnee_DEC[0];

Donnee_Hexa_Calc = tmp0 + (tmp1*10) + (tmp2*100) + (tmp3*1000);

if(cons_ang_stat==1){

Consigne_ang_Hexa = Donnee_Hexa_Calc;}

if(cons_load_stat==1){

Consigne_load_Hexa = Donnee_Hexa_Calc;}

if(cons_seuil_stat==1){

Consigne_seuil_Hexa = Donnee_Hexa_Calc;Consigne_seuil_Hexa =(Consigne_seuil_Hexa*13.107); //65535/5000;

}

}

//***********************************************************************************************************//Routine de conversion de la position du variateur de vitesse et la Vitesse du variateur de vitesse//***********************************************************************************************************void Convert_to_hex_Drive(unsigned char caractere2[]){ signed long val=0;

signed int c,d,e=0;signed long

tmp0=0x00000000,tmp1=0x00000000,tmp2=0x00000000,tmp3=0x00000000,tmp4=0x00000000,tmp5=0x00000000,tmp6=0x00000000,tmp7=0x00000000;

signed long temp=0x00000000;

for(c=0;c<8;c++){

if (caractere2[c] > 0x40){

Donnee_HEX[c] = caractere2[c]-55;}else

{Donnee_HEX[c] = caractere2[c]-48;

}}

tmp0 = Donnee_HEX[7]; //tmp0 = (tmp0 && 0x0000000F);

tmp0 = (tmp0);

tmp1 = Donnee_HEX[6];//tmp1 = (tmp1 << 4) && 0x000000F0;

18

Page 110: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

tmp1 = (tmp1 << 4);

tmp2 = Donnee_HEX[5];//tmp2 = (tmp2 << 8) && 0x00000F00;tmp2 = (tmp2 << 8);

tmp3 = Donnee_HEX[4];//tmp3 = (tmp3 << 12) && 0x0000F000;tmp3 = (tmp3 << 12);

tmp4 = Donnee_HEX[3];//tmp4 = (tmp4 << 16) && 0x000F0000;tmp4 = (tmp4 << 16);

tmp5 = Donnee_HEX[2];//tmp5 = (tmp5 << 20) && 0x00F00000;tmp5 = (tmp5 << 20);

tmp6 = Donnee_HEX[1];//tmp6 = (tmp6 << 24) && 0x0F000000;tmp6 = (tmp6 << 24);

tmp7 = Donnee_HEX[0];//tmp7 = (tmp7 << 28) && 0xF0000000;tmp7 = (tmp7 << 28);

Donnee_Hexa_Calc = tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 + tmp7;

if(First_pos_Read==1){

Zero_Hexa_Calc = Donnee_Hexa_Calc;}

if(Reel_pos_Read==1){

Reel_Hexa_Calc = Donnee_Hexa_Calc;}

if(RS==1){

Read_speed_Calc = Donnee_Hexa_Calc;RS=0;

}

}

//***********************************************************************************************************//Conversion de l'angle de degré à pulses //***********************************************************************************************************void Convert_Angle_Pulse(unsigned long ANGLE){

signed long Temp = 0;

Temp = ANGLE;Consigne_Pulse = (Temp * 800000)/360; // Transformation de la consigne angulaire en

consigne Nbre de pulse

}

//***********************************************************************************************************//Consigne Char Function://Mettre la longueur de la consigne sur quatre caractères//***********************************************************************************************************void Consigne_Char(unsigned char caractere1[]){

unsigned int d = 0;

19

Page 111: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

Long = Long-1;if(caractere1[0]==0x47) // Permet de négliger les deux points{

for(d=0;d<Long;d++){consigne_posi[3-d]=caractere1[Long-d]; // Mettre la consigne dans la variable

consigne_posi}Long=0;

}

if(caractere1[0]==0x4C){

for(d=0;d<Long;d++){consigne_load[3-d]=caractere1[Long-d]; // Mettre la consigne dans la variable

consigne_load}Long=0;

}if(caractere1[0]==0x53){

for(d=0;d<Long;d++){consigne_seuil[3-d]=caractere1[Long-d]; // Mettre la consigne dans la variable

consigne_seuil}Long=0;

}}

//***********************************************************************************************************//Convertion De plage de la position://***********************************************************************************************************void Reel_Pulse_Posi(unsigned char caractere3[]){

unsigned int c = 0;signed long tpm_zero = 0;

for(c=0;c<8;c++){

REELPosition[c]=caractere3[c+6]; // Position actuelle = position initiale}

Reel_pos_Read = 1;

Convert_to_hex_Drive(REELPosition); // Conversion de la donnée ASCII de position en donnée Hexadécimale(Position_Hexa_Calc)

STAT_RECEI = 0;Reel_pos_Read=0;

Diff_Hexa_Calc = Reel_Hexa_Calc - Zero_Hexa_Calc;

if (Diff_Hexa_Calc < 0){

Diff_Hexa_Calc = (0xFFFFFFFF - (Diff_Hexa_Calc - 1));}

}

//***********************************************************************************************************

20

Page 112: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

//Checksum() Function://Fonction permettant de faire le calcul du Checksum afin de valider les données transmises POUR 18 CARACTÈRES.//***********************************************************************************************************void Checksum(void){int l;int CS=0;int sum=0;int tmp=0;//DisplayData[] = ":DDFFFfVVVVVVVVCC";

for (l=1; l<15; l++){sum = sum + DisplayData[l];}

CS=256-sum;

//Conv CS1 tmp= CS & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[16] = tmp;

//Conv CS0tmp= CS>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[15] = tmp;

}

//***********************************************************************************************************//Checksum() Function://Fonction permettant de faire le calcul du Checksum afin de valider les données transmises POUR 20 CARACTÈRES.//***********************************************************************************************************void Checksum_LONG(void){int h;int Ch=0;int sum=0;int tmp=0;//DisplayData[] = ":DDFFFfVVVVVVVVCC";

for (h=1; h<17; h++){sum = sum+ DisplayData[h];}

Ch=256-sum;

//Conv CS1 tmp= Ch & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[18] = tmp;

//Conv CS0tmp= Ch>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

21

Page 113: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\ConvertRoutines.c

else tmp+=0x37;

DisplayData[17] = tmp;

}

22

Page 114: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Delay.s

;Symbol/Literal/Immediate Operand Definitions:

;".equ" directives are similar to "#define" pre-processor directives in C

.equ NANOSEC125, 2 ;125ns approx = 2*TCY at 14.7 MIPS

.equ MICROSEC, 8*NANOSEC125 ;8*125ns =1us

.equ MILLISEC, 1000*MICROSEC ;1000*1us = 1000*8*125ns = 1ms

;Global Declarations for Functions and variables:

.global _Delay5us

.global _Delay5ms

.global _Delay125ns

;Code Sections:

;Code sections are named ".text"

.section .text

_Delay5us:

;Function Prototype for C:

; void Delay5us(int Count)

; Note: "_" prefixed to the function name is not used when calling the

; function from a C file.

; Function Execution Time when Count=1 is 5 microseconds at 14.74 MIPS

;

push w1 ;Store w1 on to stack

mov #MICROSEC, w1 ;w1 = MICROSEC

dec w1, w1 ;w1 = w1 - 1

bra nz, $-2 ;If w1 != 0 then Branch to previous instruction

dec w0, w0 ;else w0 = w0 - 1

bra nz, $-8 ;If w0 != 0 then Branch back 4 instructions

pop w1 ;else restore w1 from stack

return ;Return to calling routine

_Delay5ms:

;Function Prototype for C:

; void Delay5ms(int Count)

; Note: "_" prefixed to the function name is not used when calling the

; function from a C file.

; Function Execution Time when Count=1 is 5 milliseconds at 14.74 MIPS

push w1 ;Store w1 on to stack

mov #MILLISEC, w1 ;w1 = MILLISEC

dec w1, w1 ;w1 = w1 - 1

bra nz, $-2 ;If w1 != 0 then Branch to previous instruction

dec w0, w0 ;else w0 = w0 - 1

bra nz, $-8 ;If w0 != 0 then Branch back 4 instructions

pop w1 ;else restore w1 from stack

return ;Return to calling routine

.end ;End of File

1

Page 115: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/extern unsigned int RXsel;extern unsigned int PTR;extern unsigned int RS;

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME *****************************************************************************************************/extern unsigned char DisplayData[];

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE reçu******************************************************************************************************/

extern putsUART1(unsigned int *buffer);extern WriteUART1(unsigned int data);extern WriteUART_to_RS232(void);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS DE DÉLAI*****************************************************************************************************/extern Delay5ms (int);extern Delay5us (int);

/*****************************************************************************************************DÉCLARATION DES FONCTION ACCESSIBLE SEULEMENT SUR CETTE FEUILLE*****************************************************************************************************/void ZERO_VITESSE (void);void GetPosition (void);void Checksum2(void);void Reset_fault (void);void SP_VITESSE_MODE (void);void Drive_Enable (void);void Drive_Disable (void);void Read_speed (void);void Drive_init (void);void Max_speed (void);void Accel (void);void Decel (void);void disable_accel_limit (void);void soft_overtravel (void);void Define_Home (void);void Position_Compar_Init (void);void Digital_Output (void);

/*****************************************************************************************************INITIALISATION DE LA ROUTINE D'INITIALISATION DU VARIATEUR DE VITESSE*****************************************************************************************************/void Drive_init (void) //Fonction permettant d'acquiter une faute sur le variateur de vitesse{

//Drive_Disable();Reset_fault();//Max_speed();Drive_Disable();Delay5ms(1000);Drive_Enable();Define_Home();

}

//*****************************************************************************************************************************//Définir la position initiale du système//*****************************************************************************************************************************

1

Page 116: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

void Define_Home (void){

DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Adresse de HomingDisplayData[3] = 0x30; //0 DisplayData[4] = 0x37; //7 DisplayData[5] = 0x31; //1

//Ecrire 1 pour imposer la position actuelleDisplayData[6] = 0x31; //1

//CheckSumDisplayData[7] = 0x44; //D DisplayData[8] = 0x37; //7

//Carriage returnDisplayData[9] = 0x0D; //<CR>DisplayData[10] = 0x00; //0

WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

}

//************************************************************//Mettre la fonction d'overtravel en fonction//************************************************************void soft_overtravel (void){

DisplayData[0] = 0x3A; //: //: DisplayData[1] = 0x30; //0 //0 DisplayData[2] = 0x30; //0 //0

//Drive OVERTRAVEL ENABLEDisplayData[3] = 0x30; //0 //0 DisplayData[4] = 0x44; //D //D DisplayData[5] = 0x44; //D //D

//EcrireDisplayData[6] = 0x31; //1 //1

//METTRE EN FONCTIONDisplayData[7] = 0x30; //0 //0 DisplayData[8] = 0x30; //1 //0

//CheckSumDisplayData[9] = 0x35; //5 //5DisplayData[10] = 0x37; //6 //7

//Carriage returnDisplayData[11] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[12] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

}

//************************************************************//Mettre HORS FONCTION LES LIMITES D'ACCÉLÉRATION//************************************************************void disable_accel_limit (void){

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

2

Page 117: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//Max speedDisplayData[3] = 0x30; //0DisplayData[4] = 0x41; //ADisplayData[5] = 0x39; //9

//EcrireDisplayData[6] = 0x31; //1

//DataDisplayData[7] = 0x30; //0DisplayData[8] = 0x30; //0

//CheckSumDisplayData[9] = 0x36; //6DisplayData[10] = 0x35; //5

//Carriage returnDisplayData[11] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[12] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232(); Delay5ms(2);

}

//************************************************************////************************************************************void Accel (void){

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Max speedDisplayData[3] = 0x30; //0DisplayData[4] = 0x35; //5DisplayData[5] = 0x46; //F

//EcrireDisplayData[6] = 0x31; //1

//Max speedDisplayData[7] = 0x30; //0DisplayData[8] = 0x30; //0DisplayData[9] = 0x31; //1DisplayData[10] = 0x33; //3

DisplayData[11] = 0x38; //8DisplayData[12] = 0x38; //8DisplayData[13] = 0x30; //0DisplayData[14] = 0x30; //0

//CheckSumDisplayData[15] = 0x30; //3DisplayData[16] = 0x33; //0

//Carriage returnDisplayData[17] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[18] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232(); Delay5ms(2);

3

Page 118: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

}

//************************************************************////************************************************************void Decel (void){

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Max speedDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x30; //0

//EcrireDisplayData[6] = 0x31; //1

//consigne de decelDisplayData[7] = 0x33; //3DisplayData[8] = 0x46; //FDisplayData[9] = 0x46; //FDisplayData[10] = 0x46; //F

DisplayData[11] = 0x46; //FDisplayData[12] = 0x46; //FDisplayData[13] = 0x46; //FDisplayData[14] = 0x46; //F

//CheckSumDisplayData[15] = 0x42; //BDisplayData[16] = 0x43; //C

//Carriage returnDisplayData[17] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[18] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232(); Delay5ms(2);

}

//************************************************************////************************************************************void Max_speed (void) //Fonction permettant d'acquiter une faute sur le variateur de vitesse{

// :00038fddddcc<cr> //((((16378 CNT/SEC)*60SEC)/8000)=122rpm = 0X7A

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Max speedDisplayData[3] = 0x30; //0DisplayData[4] = 0x33; //3DisplayData[5] = 0x38; //8

//EcrireDisplayData[6] = 0x31; //1

4

Page 119: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//Max speedDisplayData[7] = 0x30; //0 0DisplayData[8] = 0x42; //0 B BB8E8 = 3000RPM maxDisplayData[9] = 0x42; //0 BDisplayData[10] = 0x38; //0 8

//CheckSumDisplayData[11] = 0x45; //1 EDisplayData[12] = 0x38; //4 8

//Carriage returnDisplayData[13] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[14] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232(); Delay5ms(2);

}

//************************************************************//FAIRE UNE REMISE À ZÉRO DES ERREURS DANS LE VARIATEUR//************************************************************void Reset_fault (void) //Fonction permettant d'acquiter une faute sur le variateur de vitesse{

// :0006F1C3<cr>

//Drive Fault resetDisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Drive RESETDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x46; //F

//EcrireDisplayData[6] = 0x31; //1

//CheckSumDisplayData[7] = 0x43; //CDisplayData[8] = 0x33; //3

//Carriage returnDisplayData[9] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[10] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232();//Delay5us(1200); Delay5ms(2);

//************************************************************//METTRE LE VARIATEUR DE VITESSE EN CONSIGNE DE VITESSE//************************************************************

//Drive ADRESSDisplayData[0] = 0x3A; //: //: DisplayData[1] = 0x30; //0 //0 DisplayData[2] = 0x30; //0 //0

//Drive velocity preset modeDisplayData[3] = 0x30; //0 //0DisplayData[4] = 0x36; //6 //6DisplayData[5] = 0x31; //1 //1

5

Page 120: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//EcrireDisplayData[6] = 0x31; //1 //1

//Preset velocity modeDisplayData[7] = 0x30; //0 //0DisplayData[8] = 0x31; //1 //0

//CheckSumDisplayData[9] = 0x37; //7 //7 DisplayData[10] = 0x37; //7 //8

//Carriage returnDisplayData[11] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[12] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);//Delay5us(700);

}

//************************************************************//METTRE LE VARIATEUR DE VITESSE EN CONSIGNE DE VITESSE//************************************************************void SP_VITESSE_MODE (void) //Fonction permettant de mettre la drive en asservissement de vitesse{

// :0006110177<cr>

//Drive ADRESSDisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Drive velocity preset modeDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x31; //1

//EcrireDisplayData[6] = 0x31; //1

//Preset velocity modeDisplayData[7] = 0x30; //0DisplayData[8] = 0x31; //1

//CheckSumDisplayData[9] = 0x37; //7DisplayData[10] = 0x37; //7

//Carriage returnDisplayData[11] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[12] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UART

}

//************************************************************//METTRE LE VARIATEUR DE VITESSE EN MODE FONCTIONNEMENT//************************************************************void Drive_Enable (void) //Fonction permettant d'activer le variateur de vitesse{

//Drive ADRESSDisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

6

Page 121: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//Drive Enable/DisableDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x42; //B

//EcrireDisplayData[6] = 0x31; //1

//Enable DriveDisplayData[7] = 0x30; //0DisplayData[8] = 0x31; //1

//CheckSumDisplayData[9] = 0x36; //6DisplayData[10] = 0x36; //6

//Carriage returnDisplayData[11] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[12] = 0x00; //0

//Envoi de la commandeWriteUART_to_RS232();Delay5ms(2);

}

//************************************************************//METTRE LE VARIATEUR DE VITESSE HORS FONCTION//************************************************************void Drive_Disable (void) //Fonction permettant de désactiver le variateur de vitesse{

// :0006B10067<cr>

//Drive ADRESSDisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Drive Enable/DisableDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x42; //B

//EcrireDisplayData[6] = 0x31; //1

//Disable DriveDisplayData[7] = 0x30; //0DisplayData[8] = 0x30; //0

//CheckSumDisplayData[9] = 0x36; //6DisplayData[10] = 0x37; //7

//Carriage returnDisplayData[11] = 0x0D;

//Arret de la transmission rs-232DisplayData[12] = 0x00;

//Envoi de la commandeWriteUART_to_RS232(); Delay5ms(2);

}

//************************************************************//ENVOIE D'UNE CONSIGNE DE LECTURE AU VARIATEUR DE VITESSE//************************************************************void Read_speed (void) //Fonction permettant d'obtenir la vitesse actuelle

7

Page 122: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

{

// :aa085fddddddddcc<cr>

//Drive ADRESSDisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Drive Enable/DisableDisplayData[3] = 0x30; //0DisplayData[4] = 0x38; //8DisplayData[5] = 0x35; //5

//LectureDisplayData[6] = 0x30; //0

//CheckSumDisplayData[7] = 0x44; //DDisplayData[8] = 0x33; //3

//Carriage returnDisplayData[9] = 0x0D;

//Arret de la transmission rs-232DisplayData[10] = 0x00;

//Envoi de la commandeWriteUART_to_RS232();

}

//************************************************************************//Lecture de position et insertion dans PositionData//************************************************************************void GetPosition(void){unsigned int i;

// :aa07Efcc<cr>

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

DisplayData[3] = 0x30; //0DisplayData[4] = 0x37; //7DisplayData[5] = 0x45; //E

//Lire la valeurDisplayData[6] = 0x30; //0

//CheckSumDisplayData[7] = 0x43; //CDisplayData[8] = 0x34; //4

//Carriage return DisplayData[9] = 0x0D; //<CR>

//Arret de la transmission rs-232

DisplayData[10] = 0x00; //0WriteUART_to_RS232(); //Envoi la serie de caractere par

RS-232

PTR=0; //Initialise le pointeur de la reception sur 0

RXsel=1; //Envoi la reception vers PositionData

}

void Position_Compar_Init (void)

8

Page 123: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

{

//************************************************************//Imposer la limite minimale et maximale de dépassement//*********************************************************************************//************************************************************//MAXIMUM---------------------------------------------------------------------

DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x31; //1 DisplayData[4] = 0x35; //5 DisplayData[5] = 0x44; //D

//EcrireDisplayData[6] = 0x31; //1

//Position maximaleDisplayData[7] = 0x30; //0 DisplayData[8] = 0x30; //0

//POSITIONDisplayData[9] = 0x46; //FDisplayData[10] = 0x46; //F DisplayData[11] = 0x46; //FDisplayData[12] = 0x43; //CDisplayData[13] = 0x46; //FDisplayData[14] = 0x32; //2DisplayData[15] = 0x43; //CDisplayData[16] = 0x30; //0

//CheckSumDisplayData[17] = 0x36; //6DisplayData[18] = 0x35; //5

//Carriage returnDisplayData[19] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[20] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

/*

//MINIMUM------------------------------------------------------------DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x31; //1 DisplayData[4] = 0x35; //5 DisplayData[5] = 0x44; //D

//EcrireDisplayData[6] = 0x31; //1

//Position mINIMALEDisplayData[7] = 0x30; //0 DisplayData[8] = 0x31; //1

//POSITIONDisplayData[9] = 0x46; //FDisplayData[10] = 0x46; //F DisplayData[11] = 0x46; //FDisplayData[12] = 0x46; //FDisplayData[13] = 0x41; //D //E //ADisplayData[14] = 0x39; //8 //A //9

9

Page 124: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

DisplayData[15] = 0x33; //F //4 //3DisplayData[16] = 0x32; //0 //D //2

//CheckSumDisplayData[17] = 0x36; //5 //4 //6DisplayData[18] = 0x44; //A //E //D

//Carriage returnDisplayData[19] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[20] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

*/

//TYPE DE COMPARAISON ARRAY_00------------------------------------------------------------DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x31; //1 DisplayData[4] = 0x35; //5 DisplayData[5] = 0x45; //E

//EcrireDisplayData[6] = 0x31; //1

//ARRAY Position 1DisplayData[7] = 0x30; //0 DisplayData[8] = 0x30; //0

//POSITION Less thanDisplayData[9] = 0x30; //0DisplayData[10] = 0x31; //1

//CheckSumDisplayData[11] = 0x30; //0DisplayData[12] = 0x33; //3

//Carriage returnDisplayData[13] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[14] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

//TYPE DE COMPARAISON ARRAY_01------------------------------------------------------------DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x31; //1 DisplayData[4] = 0x35; //5 DisplayData[5] = 0x45; //E

//EcrireDisplayData[6] = 0x31; //1

//ARRAY Position 1DisplayData[7] = 0x30; //0 DisplayData[8] = 0x31; //1

//POSITION Greater thanDisplayData[9] = 0x30; //0DisplayData[10] = 0x30; //0

10

Page 125: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//CheckSumDisplayData[11] = 0x30; //0DisplayData[12] = 0x33; //3

//Carriage returnDisplayData[13] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[14] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

}

void Digital_Output (void){

//************************************************************//Imposer les fonctions des sortie digitales//*********************************************************************************//************************************************************//FONCTION COMPARAISON1---------------------------------------------------------------------

DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x30; //0 DisplayData[4] = 0x43; //C DisplayData[5] = 0x45; //E

//EcrireDisplayData[6] = 0x31; //1

//Position maximaleDisplayData[7] = 0x30; //0 DisplayData[8] = 0x30; //0

//FONCTION DisplayData[9] = 0x30; //0DisplayData[10] = 0x30; //0 DisplayData[11] = 0x30; //0DisplayData[12] = 0x30; //0DisplayData[13] = 0x34; //4DisplayData[14] = 0x30; //0DisplayData[15] = 0x30; //0DisplayData[16] = 0x30; //0

//CheckSumDisplayData[17] = 0x44; //DDisplayData[18] = 0x33; //3

//Carriage returnDisplayData[19] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[20] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

//FONCTION COMPARAISON_2---------------------------------------------------------------------DisplayData[0] = 0x3A; //: DisplayData[1] = 0x30; //0 DisplayData[2] = 0x30; //0

//Drive Comparateur de positionDisplayData[3] = 0x30; //0 DisplayData[4] = 0x43; //C DisplayData[5] = 0x45; //E

11

Page 126: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

//EcrireDisplayData[6] = 0x31; //1

//Position maximaleDisplayData[7] = 0x30; //0 DisplayData[8] = 0x31; //1

//FONCTION DisplayData[9] = 0x30; //0DisplayData[10] = 0x30; //0 DisplayData[11] = 0x30; //0DisplayData[12] = 0x30; //0DisplayData[13] = 0x38; //8DisplayData[14] = 0x30; //0DisplayData[15] = 0x30; //0DisplayData[16] = 0x30; //0

//CheckSumDisplayData[17] = 0x43; //CDisplayData[18] = 0x45; //E

//Carriage returnDisplayData[19] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[20] = 0x00; //0WriteUART_to_RS232(); //Update RS232 via UARTDelay5ms(2);

}

//************************************************************//ENVOI D'UNE CONSIGNE DE VITESSE NULLE AU VARIATEUR DE VITESSE//************************************************************void ZERO_VITESSE (void){

DisplayData[0] = 0x3A; //:DisplayData[1] = 0x30; //0DisplayData[2] = 0x30; //0

//Max speedDisplayData[3] = 0x30; //0DisplayData[4] = 0x36; //6DisplayData[5] = 0x44; //D

//EcrireDisplayData[6] = 0x31; //1

//consigne de VITESSE 0DisplayData[7] = 0x30; //0DisplayData[8] = 0x30; //0DisplayData[9] = 0x30; //0DisplayData[10] = 0x30; //0

DisplayData[11] = 0x30; //0DisplayData[12] = 0x30; //0DisplayData[13] = 0x30; //0DisplayData[14] = 0x30; //0

//CheckSumDisplayData[15] = 0x34; //4DisplayData[16] = 0x35; //5

//Carriage returnDisplayData[17] = 0x0D; //<CR>

//Arret de la transmission rs-232DisplayData[18] = 0x00; //0

//Envoi de la commande

12

Page 127: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Drive_Command(2).c

WriteUART_to_RS232(); //Delay5ms(1); Delay5us(1200);

}

//************************************************************************//EFFECTUER LE CHECKSUM//************************************************************************void Checksum2(void){int l;int CS=0;int sum=0;int tmp;//DisplayData[] = ":DDFFFfVVVVVVVVCC";

for (l=1; l<15; l++){sum = sum + DisplayData[l];}

CS=256-sum;

//Conv CS1 tmp= CS & 0x000F; if (tmp<=9)

tmp+=0x30; else

tmp+=0x37;

DisplayData[16] = tmp;

//Conv CS0tmp= CS>>4 & 0x000F;

if (tmp<=9) tmp+=0x30;

else tmp+=0x37;

DisplayData[15] = tmp;

}

13

Page 128: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

#include <p30f4011.h> //"p30fxxxx.h" is a generic header file for dsPIC30F#include "system.h" //"system.h" is a header file defined for this demo //application.

_FOSC(CSW_FSCM_OFF & XT_PLL8); //Run this project using an external crystal //routed via the PLL in 8x multiplier mode //For the 7.3728 MHz crystal we will derive a //throughput of 7.3728e+6*8/4 = 14.74 MIPS(Fcy) //,~67nanoseconds instruction cycle time(Tcy)._FWDT(WDT_OFF); //Turn off the Watch-Dog Timer._FBORPOR(MCLR_EN & PWRT_OFF); //Enable MCLR reset pin and turn off the //power-up timers._FGS(CODE_PROT_OFF); //Disable Code Protection

/*****************************************************************************************************DÉCLARATION DES FONCTIONS ACCESSIBLE DANS TOUT LE PROGRAMME*****************************************************************************************************/extern UART_Init (void);extern UART2_Init (void);extern SPI_Init(void);extern Timer1_Init(void);extern INTx_Init(void);extern INIT_ADs_SPI(void);extern RXLoadC(void);extern SPILCInit(void);extern WriteUART_to_RS232(void);extern WriteUART2_to_RS232(void);extern AffCell(void);extern AffEMG(void);extern AffPOSI(void);extern GetPosition (void);extern WritePosi (void);extern UART_Init2 (void);extern Drive_init(void); extern Accel (void);extern Decel (void);extern disable_accel_limit (void);extern soft_overtravel (void);extern Timer2_Init(void);extern GetTimeScan(void);extern AffREFRESH(void);extern AffCONSIGNE(void);extern Define_Home (void);extern Position_Compar_Init (void);extern Digital_Output (void);extern ZERO_VITESSE (void);extern Asservi (void);extern convert_load(void);

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À ENVOYER******************************************************************************************************/

extern WriteUART1(unsigned int data);extern TXLoadC(unsigned int SPITX,unsigned int length);extern ConfigIntUART2(unsigned int config);extern WriteL_UART2(unsigned char lenght);extern WriteUART2(unsigned int data);extern Convert_to_hex(unsigned char caractere[]);extern Convert_to_hex_Drive(unsigned char caractere2[]);extern Consigne_Char(unsigned char caractere1[]);extern Reel_Pulse_Posi(unsigned char caractere3[]);extern Convert_Angle_Pulse(unsigned long Consigne_ANGLE);extern Envoi_Vitess_drive(signed long ADRES);extern Envoi_Accel_drive(signed long ADRES2);extern soft_overtravel_positif (signed long ADRES3);extern soft_overtravel_negatif (signed long ADRES4);extern soft_overtravel_pos_limit (signed long ADRES5);

1

Page 129: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

extern soft_overtravel_neg_limit (signed long ADRES6);extern MINIMUM_POSI(signed long ADRES7);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS DE DÉLAI*****************************************************************************************************/extern Delay5us (int);extern Delay5ms (int);

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME *****************************************************************************************************/extern unsigned char Status[]="0000000000000000000000000000000000";extern unsigned char DisplayData[]=":00000000000000000000 ";extern unsigned char ReceivedData[]="0000000000000000";extern unsigned char PositionData[]="0000000000000000";extern unsigned char ZeroPosition[]="00000000";extern unsigned char REELPosition[]="00000000";extern unsigned char ConsigneVitessePos[]="000000000000000000";extern unsigned char Donnee_DEC[]="0000";extern unsigned char Donnee_HEX[]="00000000";extern unsigned char Donnee_Hexa_AFF[] = "00000000";extern unsigned char Read_speed_ASCII[] = "00000000";extern unsigned char consigne_posi[]="0000";extern unsigned char consigne_load[]="0000";extern unsigned char consigne_seuil[]="0000";extern unsigned char Temporaire1[]="0000";extern unsigned char CONSIGNE[]=":000000";extern unsigned char REFRESHVAL[]=":0000000000000000000000";

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR HUIT BITS NON SIGNÉES ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 255)*****************************************************************************************************/

extern unsigned char send = 0;extern unsigned char TX2REFRESHVAL=0;

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/

extern unsigned int TAMPON = 0x0000;extern unsigned int EMG = 0x0000;extern unsigned int AFF = 0x0000;extern unsigned int POSI = 0x0000;extern unsigned int LCSPIRX = 0x0000;extern unsigned int PTR = 0;extern unsigned int PTR2 = 0;extern unsigned int PosAtt = 0;extern unsigned int RX2PTR=0;extern unsigned int cons_ang_stat=0;extern unsigned int cons_load_stat=0;extern unsigned int cons_seuil_stat=0;extern unsigned int First_pos_Read=0;extern unsigned int Reel_pos_Read=0;extern unsigned int Long=0;extern unsigned int Posi_init = 0;extern unsigned int j=0;extern unsigned int l=0;extern unsigned int x=0;extern unsigned int STAT_RECEI=0;extern unsigned int RS=0; extern unsigned int STOP=0; extern unsigned int START=0; extern unsigned int up_down=1;extern unsigned int start_load=1; extern unsigned int DDD;extern unsigned int ZERO_LOAD=0;extern unsigned int TimeScan = 0x0000;extern unsigned int SP_load = 0x0000;extern unsigned int RXsel = 0;

2

Page 130: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

extern unsigned int Consigne_load_Hexa = 0x0000;extern unsigned int Consigne_seuil_Hexa = 0x0000;

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (-32768 À 32767)*****************************************************************************************************/

extern signed int Potentiometer = 0;

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 4 294 967 295)*****************************************************************************************************/

extern unsigned long RX2TEMP=0;extern unsigned long CONSLOAD=0;extern unsigned long Consigne_Pulse = 0;extern unsigned long MAX_Speed=0x00002FFA; // Défénition de la vitesse maximaleextern unsigned long Consigne_ang_Hexa = 0x00000000;extern unsigned long Seuil_Trente_Hexa = 0x00000000;

/*****************************************************************************************************

DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME(-2 147 483 648 À 2 147 483 647)*****************************************************************************************************/

extern signed long SP_vit = 0;extern signed long Donnee_Hexa_Calc = 0x00000000;extern signed long Diff_Hexa_Calc = 0x00000000;extern signed long Reel_Hexa_Calc = 0x00000000;extern signed long Zero_Hexa_Calc = 0x00000000;extern signed long Read_speed_Calc = 0x00000000;extern signed long Posi_Speed = 0x00002FF4;extern signed long Accel_Val_MIN = 0x00001B27; extern signed long Acceleration = 0x00000000; extern signed long Zero_Speed = 0x00000000;extern signed long TEMP_DEEEEEE = 0x00000000;extern signed long soft_positif = 0xFFFFD499;extern signed long soft_negatif = 0xFFFCF2C0;extern signed long positif_limit = 0x000008AE;extern signed long negatif_limit = 0x000008AE;extern signed long Vit_act=0;

/*****************************************************************************************************DÉCLARATION DES VARIABLES EN POINT FLOTTANT (1.17549*10e-38 À 8.5*10e37)*****************************************************************************************************/extern float depass=0; //Depassement de la valeur seuil de l'emg en %extern float SP_EMG = 0x0000;extern float Delta_force = 0;extern float facteur = 7.272; //cnt/sec; //Facteur de correction du systeme (0.007136 tr/N*s * 8000)extern float EMG_CORR_GAIN = 0.025;extern float LOAD_CORR_GAIN = 2;extern float ACCEL_GAIN = 12;extern float LOAD=0;

/*****************************************************************************************************DÉCLARATION DES FONCTION ACCESSIBLE SEULEMENT SUR CETTE FEUILLE*****************************************************************************************************/void main (void);

/***********************************************ENTRÉE DANS LA ROUTINE PRINCIPALE*********************

CETTE ROUTINE EST LE CONTRÔLE PRINCIPALE DU SYSTÈME. ELLE PERMET D'INITIALISER LE VARIATEUR DE VITESSEET DE RECEUILLIR LE CONSIGNES DE FONCTIONNEMENT DE L'APPAREIL. DANS CETTE ROUTINE, BEAUCOUP DE SOUS FONCTIONS DE CONVERSION SONT APPELÉS CE QUI PERMET D'UTILISER LES DIFFÉRENTES VARIABLES LUT PAR LE SYSTÈME. DE PLUS, LA ROUTINE D'ASSERVISSEMENT EST APPELÉ DANS CETTE PARTIE.

3

Page 131: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

*****************************************************************************************************/

void main (void){

//**********************************************************************************************//INITIALISATION DE CERTAINES VARIABLE APPLICABLE À LA ROUTINE PRINCIPALE//**********************************************************************************************unsigned char NEW_PAGE = 12;unsigned char NEW_LINE = 10;unsigned char h,tampon, Tata = 0;

unsigned int cr = 0x0D;unsigned int i = 0;unsigned int count = 0;unsigned int cnt = 0;unsigned int c,d,e,f = 0;

signed int CNT_UPD=0;

//**********************************************************************************************//INITIALISATION DES ENTRÉES SORTIES DU SYSTÈME//**********************************************************************************************TRISBbits.TRISB1 = 0; // Configurer la pin RB3 en sortie (1=entrée, 0 = sortie)TRISBbits.TRISB0 = 0; // Configurer la pin RB3 en sortie (1=entrée, 0 = sortie)TRISBbits.TRISB3 = 0; // Configurer la pin RB3 en sortie (1=entrée, 0 = sortie)TRISBbits.TRISB4 = 0; // Configurer la pin RB4 en sortie (1=entrée, 0 = sortie)TRISBbits.TRISB5 = 1; // Configurer la pin RB5 en entrée (1=entrée, 0 = sortie)

TRISEbits.TRISE2 = 0; // Configurer la pin RE2 en sortie (1=entrée, 0 = sortie) TRISEbits.TRISE3 = 0; // Configurer la pin RE3 en sortie (1=entrée, 0 = sortie) TRISEbits.TRISE4 = 1; // Configurer la pin RE4 en entrée (1=entrée, 0 = sortie) TRISEbits.TRISE8 = 1; // Configurer la pin RE8 en entrée (1=entrée, 0 = sortie)

LATBbits.LATB3 = 1; // Mettre la sortie RB3 ONLATBbits.LATB4 = 1; // Mettre la sortie RB4 ONLATBbits.LATB5 = 0; // Mettre l'entrée RB5 OFF LATEbits.LATE3 = 1; // Mettre la sortie RE3 ON LATEbits.LATE2 = 0; // Mettre la sortie RE3 OFF

ADPCFG = 0xFFFF; // After reset all port pins multiplexed // with the A/D converter are configred analog. // We will reconfigure them to be digital // by writing all 1's to the ADPCFG register. // Note: All dsPIC registers are memory mapped. // The address of ADPCFG and other registers // are defined in the device linker script // in your project.Envoi_Vitess_drive(Zero_Speed); // Permet de s'assurer que le variateur de vitesse sera arrêter

// lors du démarrage du systèmeWriteUART_to_RS232();Delay5ms(200);

//**********************************************************************************************//INITIALISATION DE CERTAINS PARAMÈTRES ESSENTIELS AU FONCTIONNEMENT//**********************************************************************************************UART_Init (); //PERMET DE METTRE EN FONCTION LE PÉRIPHÉRIQUE UART1UART2_Init (); //PERMET DE METTRE EN FONCTION LE PÉRIPHÉRIQUE UART2SPI_Init(); //PERMET DE METTRE EN FONCTION LE PÉRIPHÉRIQUE SPITimer1_Init(); //PERMET DE METTRE EN FONCTION LE PÉRIPHÉRIQUE TIMER1Timer2_Init(); //PERMET DE METTRE EN FONCTION LE PÉRIPHÉRIQUE TIMER2SPILCInit(); //PERMET DE METTRE EN FONCTION LE SYSTÈME SOFTWARE SPI DU A/D DE LA

//CELLULE DE CHARGEDrive_init(); //Initialise certains paramètres dans le variateur de vitessedisable_accel_limit(); //Met hors fonction les limite d'accélérationPosition_Compar_Init(); //Met en fonction les comparateurs internes du variateurDigital_Output(); //Met en fonction et assigne certaines sortie du variateur de vitessesoft_overtravel(); //Met les dépassement hors fonction

4

Page 132: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

//ADC_Init();Envoi_Accel_drive(Accel_Val_MIN);//Envoi une consigne d'accélération minimum au variateur de vitesseWriteUART_to_RS232();Delay5us(1200);

while (1) // Boucle principale qui se fait à l'infinie {

//**********************************************************************************************//DÉMARRAGE DE L'INITIALISATION DU SYSTÈME (RÉCEPTION CONSIGNES, POSITIONNEMENT INITIALE, ETC.//**********************************************************************************************Drive_Enable(); // Appeler la routine permettant de mettre la Drive en mode RUNDelay5us(1200); // Attendre un délais pour la transmission (2.75ms)Envoi_Vitess_drive(Zero_Speed); // Appeler la routine de convertion HEXA en ASCII de la vitesse

// à la drive, envoie vitesse = 0WriteUART_to_RS232(); // Envoyer la vitesse à la DriveDelay5us(1200); // Attendre un délais pour la transmission (4ms)LATBbits.LATB1 = 1; // LED1 pour test de debug à ON

while (!STAT_RECEI) // Attendre la position actuelle du variateur {GetPosition(); // Lire la position actuelle du moteurDelay5us(1200); // Attendre un délais pour la transmission (2.5ms)}

LATBbits.LATB1 = 0; // LED1 pour test de debug à OFFFirst_pos_Read=1; // Flag pour avertir que la position zéro du variateur est reçu

for(c=0;c<8;c++){

ZeroPosition[c]=PositionData[c+6]; // Position actuelle = position initiale su 8 caractères. } // Ceci permet d'éliminer les caractères servant à idiquer

// l'adresse du régistre lu de la drive.

Convert_to_hex_Drive(ZeroPosition); // Conversion de la donnée ASCII de position en donnée // hexadécimale(Position_Hexa_Calc)

STAT_RECEI = 0; // Remise à zéro du FLAG de réception de positionFirst_pos_Read=0; // Remise à zéro du FLAG de position initiale

LATBbits.LATB1 = 1;while (!cons_ang_stat) // Attendre la consigne de position initiale du variateur{}

Consigne_Char(CONSIGNE); // Convertion de la consigne reçu de nombres de caractère // inconnue en 4 caractères

Convert_to_hex(consigne_posi); // Convertion de la consigne de position initiale ASCII en HEXAcons_ang_stat = 0; // Remise à zéro du FLAG de réception de la consigne angulaire

//Positionnnement du bras à sa position initiale******************************************************//****************************************************************************************************Convert_Angle_Pulse(Consigne_ang_Hexa); // Conversion de la consigne angulaire en nombre de pulse

MINIMUM_POSI(Consigne_Pulse);WriteUART_to_RS232(); // Envoyer la Consigne position minimum à la driveDelay5us(1200);LATBbits.LATB1 = 0; // (fonctionnement de la drive en nombre de pulses)

Envoi_Accel_drive(0x0F000000); // Envoi du consigne d'accélération énorme pour un arrêt brusque WriteUART_to_RS232();Delay5us(2000);

while (!Posi_init) // Faire la boucle tant que la position != à la consigne de position {

Envoi_Vitess_drive(Posi_Speed); // Appeler la routine de convertion HEXA en ASCII de la vitesse à // la drive, envoie vitesse = 12282 cnt/sec

5

Page 133: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

WriteUART_to_RS232(); // Envoyer la vitesse à la DriveDelay5us(1200); // Attendre un délais pour la transmission (4.5ms)GetPosition(); // Lire la position actuelle du moteurLATBbits.LATB0 = 1;

while (!STAT_RECEI) // Attendre qu'une vitesse soit entrée {}

STAT_RECEI = 0;

Reel_Pulse_Posi(PositionData); // Convertion de la vitesse ASCII en HEXA

if (Diff_Hexa_Calc > Consigne_Pulse)// Vérifier si la position actuel est plus grande que la // consigne de position

{Posi_init = 1;Envoi_Vitess_drive(Zero_Speed); // Arrête le système avec une consigne de vitesse nulleWriteUART_to_RS232();Delay5us(1200);

}}Envoi_Accel_drive(Accel_Val_MIN); // Envoi d'une consigne normale d'accélération pour un

// fonctionnement normaleWriteUART_to_RS232();Delay5us(2000);

LATBbits.LATB0 = 0;

//Réception de la consigne de charge******************************************************************//****************************************************************************************************count = 0;while (!cons_load_stat) // Attendre la consigne de charge initiale du variateur{

if(!PORTBbits.RB5) // Lecture de la cellule de charge{RXLoadC();ZERO_LOAD = LCSPIRX; // Zero de la cellule de charge}

}

count = 0;Consigne_Char(CONSIGNE); // Convertion de la consigne recu en chaine de caractère

// possédant la bonne longueurConvert_to_hex(consigne_load); // Conversion de la chaine de caractère en données hexadécimale

// permettant leur traitementcons_load_stat = 0;SP_load = (Consigne_load_Hexa * 1000); // Transformer la consigne de charge de kilogramme à gramme pour

// une meilleure précision

//Réception de la consigne de seuil EMG***************************************************************//****************************************************************************************************while (!cons_seuil_stat){

INIT_ADs_SPI(); // Effectuer une lecture du capteur EMG

/*************************************************Le système entame la séquence d'affichage une fois par 50 cycles*************************************************/if (i == 50){

AFF = EMG;AffEMG(); // Envoi la valeur lu sur l'EMG dans une variable d'affichageWriteUART2_to_RS232(); // Envoi la donnée à l'affichagei=0;

}

6

Page 134: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

i++;}

Consigne_Char(CONSIGNE); // Convertion de la consigne recu en chaine de caractère // possédant la bonne longueur

Convert_to_hex(consigne_seuil); // Conversion de la chaine de caractère en données hexadécimale

// permettant leur traitementcons_seuil_stat=0;SP_EMG = (Consigne_seuil_Hexa * 0.3); // Établie le seuil de dépassement à trente pourcent de la

// valeur maximum envoyé

//Démarrage de la routine permettant l'asservissement de l'entraînement*******************************//****************************************************************************************************

while (!START);

while (!STOP) //Entrainement actif jusqu'a ce que le bouton stop sois declanche

{

//EN MONTÉ********************************************************************************//****************************************************************************************

if(up_down==1) //Monter{

/*************************************************Si cette condition est vrai, le système arrête brusquement*************************************************/if(PORTDbits.RD1)

{Envoi_Accel_drive(0x0F000000); //Envoyer une consigne énorme d'accélération

//au variateur de vitesse pour un arrêt brusqueWriteUART_to_RS232();Delay5us(2000);

Envoi_Vitess_drive(Zero_Speed); //Envoi d'une commande de vitesse = 0WriteUART_to_RS232();Delay5ms(60);

Envoi_Accel_drive(Accel_Val_MIN);//Envoyer la consigne initiale d'accélération //pour continuer l'exercice

WriteUART_to_RS232();Delay5us(2000);

up_down=0; //Indiquer que le prochain mouvement //sera en descente

SP_load = (Consigne_load_Hexa*1000);//Remettre la consigne de charge à la valeur//de la consigne initiale

POSI = 0x005A; //Envoyer une position de 90 degré à l'affich//Appel des routine d'envoi de données à l'affichage AffCell();AffEMG();AffPOSI();AffCONSIGNE();WriteUART2_to_RS232();//Fin envoi affichage

}

/*************************************************Le système entame la séquence d'asservissement lorsque la position max n'est pas atteinte*************************************************/

else

{GetTimeScan(); // Appel une fonction permettant de calculer le temps de scan

7

Page 135: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

AffREFRESH(); // Envoi le temps de scan pour l'affichageWriteUART2_to_RS232();

Asservi();}

}

//EN DESCENTE*****************************************************************************//****************************************************************************************

else

{/*************************************************Si cette condition est vrai, le système arrête brusquement*************************************************/if(PORTDbits.RD2){

Envoi_Accel_drive(0x0F000000); //Envoyer une consigne énorme //d'accélération au variateur de vitesse //pour un arrêt brusque

WriteUART_to_RS232();Delay5us(2000);

Envoi_Vitess_drive(Zero_Speed); //Envoi d'une commande de vitesse = 0WriteUART_to_RS232();Delay5ms(60);

Envoi_Accel_drive(Accel_Val_MIN); //Envoyer la consigne initiale d'accélération//pour continuer l'exercice

WriteUART_to_RS232();Delay5us(2000);

up_down=1; //Indiquer que le prochain mouvement sera en //monté

SP_load = (Consigne_load_Hexa*1000);//Remettre la consigne de charge à la valeur//de la consigne initiale

POSI = 0x0000; //Envoyer une position de 0 degré à //l'affichage

//Appel des routine d'envoi de données à l'affichage AffCell();AffEMG();AffPOSI();AffCONSIGNE();WriteUART2_to_RS232();//Fin envoi affichage

}

/*************************************************Le système entame la séquence d'asservissement lorsque la position min n'est pas atteinte*************************************************/

else

{GetTimeScan(); // Appel une fonction permettant de calculer le temps

// de scan.AffREFRESH(); // Envoi le temps de scan pour l'affichageWriteUART2_to_RS232();

Asservi();}

}}

//ARRÊT DU SYSTÈME************************************************************************//****************************************************************************************Envoi_Vitess_drive(Zero_Speed); // Appeler la routine de convertion HEXA en ASCII de

// la vitesse à la drive, envoie vitesse = 0WriteUART_to_RS232(); // Envoyer la vitesse à la Drive

8

Page 136: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\Main.c

Delay5ms(2); // Attendre un délais pour la transmission (10ms)LATBbits.LATB0 = 0;}

return 0; }

9

Page 137: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\SPI_LoadCell.c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"#include "math.h"

/**************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 4 294 967 295)**************************************************************************************************************/extern unsigned int LCSPIRX;

/*****************************************************************************************************DÉCLARATION DES FONCTIONS RELIÉES SEULEMENT SUR CETTE FEUILLE*****************************************************************************************************/

void Timer1_Init(void);void SPILCInit(void);void RXLoadC(void);

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À REÇU******************************************************************************************************/

void TXLoadC(unsigned int SPITX,unsigned int length);

void Timer1_Init(void){ T1CON = 0b0000000000000000; //TCKPS1 Timer1 set up to count on instruction cycle

//edge with 1:1 prescaler applied initially. PR1 = 0x0006; //Period Register, PR1, set to maximum count IFS0bits.T1IF = 0; //Clear the Timer1 Interrupt Flag IEC0bits.T1IE = 0; //Enable Timer1 Interrupt Service Routine

T1CONbits.TON=0; //Stop Timer 1}

/***********************************************ENTRÉE DANS LA ROUTINE D'INITIALISATION*********************************************

CETTE ROUTINE EFFECTUE L'INITIALISATION PRÉLÉMINAIRE DU CONVERTISSEUR ANALOGIQUE À NUMÉRIQUE DE LA CELLULE DE CHARGE

***********************************************************************************************************************************/void SPILCInit(void){

unsigned int CONFIG;//RESET DU ADLATBbits.LATB3 = 0;

TXLoadC(0xFFFF,32); //RESET ADC TXLoadC(0xFFFF,32); //RESET ADC

Delay5us(125); //DELAY 500uS

//CONFIGURAION DU MODE REGISTER

TXLoadC(0x0008,16); //MODE REGISTER//TXLoadC(0x4003,32); //IDLE MODE, 123 Hz,TXLoadC(0x4004,32); //IDLE MODE, 62 Hz,

//TXLoadC(0x4008,32); //IDLE MODE, 19.6 Hz

// CONFIGURAION DU CONFIGURATION REGISTER

TXLoadC(0x0010,16); //CONFIGURATION REGISTER //TXLoadC(0x0410,32); //BUFFER MODE, BIPOLAR, GAIN 16, AN1, ADC input = 39.06 mV

//TXLoadC(0x0510,32); //BUFFER MODE, BIPOLAR, GAIN 32, AN1, ADC input = 39.06 mV

1

Page 138: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\SPI_LoadCell.c

TXLoadC(0x0610,32); //BUFFER MODE, BIPOLAR, GAIN 64, AN1, ADC input = 39.06 mV

//CONFIGURAION DU MODE REGISTER

TXLoadC(0x0008,16); //MODE REGISTER//TXLoadC(0x8003,32); //ZERO SCALE CALIBRATION, // Fréquence de convertion =

123 HzTXLoadC(0x8004,32); //ZERO SCALE CALIBRATION, // Fréquence de convertion = 62

Hz //TXLoadC(0x8008,32); //ZERO SCALE CALIBRATION, // Fréquence de convertion = 19.6 Hz

while (PORTBbits.RB5){}

//CONFIGURAION DU MODE REGISTER

TXLoadC(0x0008,16); //CONFIGURATION REGISTER //TXLoadC(0xA003,32); //FULL SCALE CALIBRATION, // Fréquence de convertion = 123 Hz TXLoadC(0xA004,32); //FULL SCALE CALIBRATION, // Fréquence de convertion = 62 Hz //TXLoadC(0xA008,32); //FULL SCALE CALIBRATION, // Fréquence de convertion = 19.6 Hz

while (PORTBbits.RB5){}

// CONFIGURAION DU CONFIGURATION REGISTER

TXLoadC(0x0010,16); //CONFIGURATION REGISTER //TXLoadC(0x0410,32); //Gain = 16, ADC input = 39.06 mV

//TXLoadC(0x0510,32); //Gain = 32, ADC input = 39.06 mV TXLoadC(0x0610,32); //Gain = 64, ADC input = 39.06 mV

//CONFIGURAION DU MODE REGISTER

TXLoadC(0x0008,16); //MODE REGISTER //TXLoadC(0x0003,32); //CONTINUOUS CONVERTION, Fréquence de convertion = 123 Hz

TXLoadC(0x0004,32); //CONTINUOUS CONVERTION, Fréquence de convertion = 62 Hz //TXLoadC(0x0008,32); //CONTINUOUS CONVERTION, Fréquence de convertion = 19.6 Hz

TXLoadC(0x005C,16); //CONTINUOUS CONVERTION}

/***********************************************ENTRÉE DANS LA ROUTINE DE TRANSMISSION*********************************************

ENVOIE DES VARIABLES VOULUES DANS LE CONVERISSEUR

***********************************************************************************************************************************/void TXLoadC(unsigned int SPITX,unsigned int length)

{LATEbits.LATE3 = 1; //Latch bit for RE3 port pin //SPICLKunsigned char COUNT=0;unsigned char COUNT1=0;unsigned char COUNT2=0;

T1CONbits.TON=1;TMR1 = 0x0000;

PR1 = 0x0006;IFS0bits.T1IF=0;

while (!IFS0bits.T1IF)

2

Page 139: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\SPI_LoadCell.c

if(((SPITX>>((length/2)-1))&0x0001)==1){LATEbits.LATE2 = 1; //Latch bit for RE2 port pin}else

{LATEbits.LATE2 = 0; //Latch bit for RE2 port pin}

LATEbits.LATE3 = 0; //Latch bit for RE3 port pin //SPICLK

for (COUNT2=0; COUNT2<(length-1); COUNT2++){

T1CONbits.TON=1; TMR1 = 0x0000;

PR1 = 0x0006;IFS0bits.T1IF=0;

while (!IFS0bits.T1IF){}

COUNT1++;if(((SPITX>>(((length/2)-1)-COUNT))&0x0001)==1)

{LATEbits.LATE2 = 1; //Latch bit for RE2 port pin}

else

{LATEbits.LATE2 = 0; //Latch bit for RE2 port pin}

if(PORTEbits.RE3&&(COUNT2<length)){ LATEbits.LATE3 = 0; //Clear bit for RE3 port pin}

else

{LATEbits.LATE3 = 1; //Latch bit for RE3 port pin}

if (COUNT1==2){COUNT++;COUNT1=0;}

}

}

/***********************************************ENTRÉE DANS LA ROUTINE DE TRANSMISSION*********************************************

RÉCEPTION DE LA CHARGE

***********************************************************************************************************************************/void RXLoadC(void){

unsigned char COUNT=0;unsigned char COUNT1=0;unsigned char COUNT2=0;

LATEbits.LATE2 = 0; //Clear Latch bit for RE2 port pin //DATAOUT LATEbits.LATE3 = 0; //Latch bit for RE3 port pin //SPICLK

T1CONbits.TON=1; TMR1 = 0x0000;

PR1 = 0x0006;

3

Page 140: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\SPI_LoadCell.c

IFS0bits.T1IF=0; //Start Timer 1 LCSPIRX=0x0000;

for (COUNT2=0; COUNT2<31; COUNT2++){while(!IFS0bits.T1IF)

{}

COUNT1++;

if(PORTEbits.RE3){ LATEbits.LATE3 = 0; //Clear bit for RE3 port pin}

else {LATEbits.LATE3 = 1; //Latch bit for RE3 port pin}

if(PORTEbits.RE4&&(COUNT2<32)&&(COUNT1<2)){ LCSPIRX=LCSPIRX+(1<<(15-COUNT)); }

if (COUNT1==2){COUNT++;COUNT1=0;}

}

}

4

Page 141: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\TimeScan(1).c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"#include "math.h"

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/

extern unsigned int TimeScan;

/*****************************************************************************************************DÉCLARATION DES FONCTIONS UTILISÉES SUR CETTE FEUILLE*****************************************************************************************************/void Timer2_Init(void);void GetTimeScan(void);

/*****************************************ENTRÉE DANS LA ROUTINE D'INITIALISATION DES TIMERS***************************************

CETTE ROUTINE PERMET D'INITIALISER LES PARAMÈTRES NÉCÉSSAIRE AU BON FONCTIONNEMENT DES TIMERS

***********************************************************************************************************************************/void Timer2_Init(void){

T2CON = 0b0000000000011000; //TCKPS1 Timer2 set up to count on instruction cycle //0123456789012345 //edge with 1:8 prescaler applied initially. PR2 = 0xFFFF; //Period Register, PR2, set to maximum count PR3 = 0xFFFF; //Period Register, PR3, set to maximum count

TMR3HLD = 0x0000;TMR2 = 0x0000;

IFS0bits.T2IF = 0; //Clear the Timer2 Interrupt Flag IEC0bits.T2IE = 0; //Enable Timer1 Interrupt Service Routine IFS0bits.T3IF = 0; //Clear the Timer3 Interrupt Flag IEC0bits.T3IE = 0; //Enable Timer1 Interrupt Service Routine

T2CONbits.TON = 0; //Stop Timer 2}

/********************************ENTRÉE DANS LA ROUTINE QUI CALCUL LE TEMPS DE SCAN DE CHAQUE BOUCLE********************************

CETTE ROUTIME PERMET LE CALCUL DU TEMPS DE SCAN DE CHAQUE BOUCLE EN MILLISECONDE

***********************************************************************************************************************************/void GetTimeScan(void){unsigned long temp1=0;unsigned long temp2=0;float temp3=0;

temp2=TMR2;temp1=TMR3HLD;

//7.3728*8/4 MHz/8 = 1843200Hztemp3 = (temp2*0.0005425); //(1000/1843200 clk/s )=0.0005425 (*1000 (ms))

if(temp3>=65535){TimeScan=0xFFFF;}else

{TimeScan=(temp3*100); //Timescan (XXXX) = temp3 (XX,XX) ms }

PR2 = 0xFFFF; //Period Register, PR2, set to maximum count PR3 = 0xFFFF; //Period Register, PR2, set to maximum count

TMR3HLD = 0x0000;TMR2 = 0x0000;

1

Page 142: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\TimeScan(1).c

T2CONbits.TON = 0; //Stop Timer 2 IFS0bits.T3IF = 0; //Clear the Timer3 Interrupt Flag IFS0bits.T2IF = 0; //Clear the Timer2 Interrupt Flag

T2CONbits.TON = 1; //Start Timer 2}

2

Page 143: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART_BON.c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"#include <uart.h>

#define BAUDRATE 38400 //Desired Baud Rate#define BRGVAL ((FCY/BAUDRATE)/16)-1 //Formula for U1BRG register //from dsPIC30F Family //Reference Manual

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME ET UTILISÉ DANS CETTE FEUILLE*****************************************************************************************************/extern unsigned char DisplayData[];extern unsigned char ReceivedData[];extern unsigned char PositionData[];

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/extern unsigned int RS;extern unsigned int PTR;extern unsigned int RXsel;extern unsigned int STAT_RECEI;

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À REÇU******************************************************************************************************/

void ConfigIntUART1(unsigned int config);void putsUART1(unsigned int *buffer);void WriteUART1(unsigned int data);void OpenUART1(unsigned int config1,unsigned int config2, unsigned int ubrg);

/*****************************************************************************************************DÉCLARATION DES FONCTIONS UTILISÉS SUR CETTE FEUILLE *****************************************************************************************************/void UART_Init (void);void WriteUART_to_RS232(void);void ReadUART_from_RS232(void);char BusyUART1(void);void CloseUART1(void);

/*****************************************************************************************************DÉCLARATION DES POINTEURS UTILISÉ SUR CETTE FEUILLE*****************************************************************************************************/unsigned int *UARTCharPtr;

/***********************************ENTRÉE DANS LA ROUTINE D'INITIALISATION DU PÉRIFÉRIQUE UART1**************************************

CETTE ROUTIME PERMET D'ENTRER LES PARAMÈTRES ADÉQUATS PERMETTANT LE FONCTIONNEMENT DE LA COMMUNICATION SÉRIE AVEC LE PÉRIFÉRIQUE UART1.

**************************************************************************************************************************************/void UART_Init (void){

unsigned int conf = 2; ConfigIntUART1(conf);

U1MODE = 0x0000; //Clear UART1 registers U1STA = 0x0000; U1MODEbits.ALTIO = 1; //Enable U1ATX and U1ARX

U1MODEbits.UARTEN = 1; //Enable UART1 module U1BRG = BRGVAL; //Load UART1 Baud Rate Generator

1

Page 144: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART_BON.c

IFS0bits.U1RXIF = 0; //Clear UART1 Receiver Interrupt Flag IFS0bits.U1TXIF = 0; //Clear UART1 Transmitter Interrupt Flag IEC0bits.U1RXIE = 1; //Enable UART1 Receiver ISR IEC0bits.U1TXIE = 1; //Enable UART1 Transmitter ISR U1STAbits.UTXISEL = 1; //Setup UART1 transmitter to interrupt //when a character is transferred to the //Transmit Shift register and as result, //the transmit buffer becomes empty. U1STAbits.URXISEL =0; //Setup UART1 Receiver to interrupt //when a character is transferred to the //Transmit Shift register and as result, //the transmit buffer becomes empty.

U1STAbits.UTXEN = 1; //Enable UART1 transmitter UARTCharPtr = &DisplayData[0]; //Initialize UARTCharPtr to point //to the first character in the Display buffer

IFS0bits.U1TXIF = 0; //Clear the UART1 transmitter interrupt flagIFS0bits.U1RXIF = 0; //Clear the UART1 Receiver interrupt flag

}

/*****************************************ENTRÉE DANS LA ROUTINE DE TRANSMISSION SÉRIE RS-232***************************************

CETTE ROUTIME PERMET DE TRANMETTRE DES CHAÎNE DE CARACTÈRES AU VARIATEUR DE VITESSE.

***********************************************************************************************************************************/void WriteUART_to_RS232(void){

UARTCharPtr = &DisplayData[0]; //Initialize UARTCharPtr to pointputsUART1(UARTCharPtr);IFS0bits.U1TXIF = 0; //Clear the UART1 transmitter interrupt flag

}

/*********************************************************************** Function Name : ConfigIntUART1 ** Description : This function sets priority for RX,TX interrupt * * and enable/disables the interrupt ** Parameters : unsigned int config enable/disable and priority ** Return Value : None * **********************************************************************/void ConfigIntUART1(unsigned int config){ /* clear IF flags */ _U1RXIF = 0; _U1TXIF = 0;

/* set priority */ _U1RXIP = 0x0007 & config; _U1TXIP = (0x0070 & config) >> 4;

// /* enable/disable interrupt */ _U1RXIE = (0x0008 & config) >> 3; _U1TXIE = (0x0080 & config) >> 7;}

/************************************************************************** Function Name : BusyUART1 ** Description : This returns status whether the transmission ** is in progress or not, by checking Status bit TRMT ** Parameters : None ** Return Value : Info about whether transmission is in progress. **************************************************************************/

char BusyUART1(void){

2

Page 145: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART_BON.c

return(!U1STAbits.TRMT);}

//----------------------------------------------------------------------------------------------------------------------------------------/********************************************************************** Function Name : CloseUART1 ** Description : This function disables the UART and clears the ** Interrupt enable & flag bits * * Parameters : None ** Return Value : None * *********************************************************************/

void CloseUART1(void){ U1MODEbits.UARTEN = 0;

IEC0bits.U1RXIE = 0; IEC0bits.U1TXIE = 0;

IFS0bits.U1RXIF = 0; IFS0bits.U1TXIF = 0;}

//----------------------------------------------------------------------------------------------------------------------------------------/**************************************************************************** Function Name : putsUART1 ** Description : This function puts the data string to be transmitted ** into the transmit buffer (till NULL character) ** Parameters : unsigned int * address of the string buffer to be * * transmitted ** Return Value : None ****************************************************************************/

void putsUART1(unsigned int *buffer){ char * temp_ptr = (char *) buffer;

/* LA TRANSMISSION SE FAIT JUSQU'À LA DÉTECTION D'UN CARACTÈRE NULL */

while(*temp_ptr != '\0') { while(U1STAbits.UTXBF); /* wait if the buffer is full */ U1TXREG = *temp_ptr++; /* transfer data byte to TX reg */ } }

//----------------------------------------------------------------------------------------------------------------------------------------/**************************************************************************** Function Name : ReadUART1 ** Description : This function returns the contents of UxRXREG buffer * * Parameters : None ** Return Value : unsigned int value from UxRXREG receive buffer ****************************************************************************/

unsigned int ReadUART1(void){ if(U1MODEbits.PDSEL == 3) return (U1RXREG); else return (U1RXREG & 0xFF);}

//----------------------------------------------------------------------------------------------------------------------------------------/********************************************************************** Function Name : WriteUART1 *

3

Page 146: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART_BON.c

* Description : This function writes data into the UxTXREG, ** Parameters : unsigned int data the data to be written ** Return Value : None **********************************************************************/

void WriteUART1(unsigned int data){ while(U1STAbits.UTXBF)

{}

if(U1MODEbits.PDSEL == 3) U1TXREG = data; else

U1TXREG = data & 0xFF;}

//----------------------------------------------------------------------------------------------------------------------------------------//_U1TXInterrupt() is the UART1 Interrupt Service Routine.//The routine must have global scope in order to be an ISR.//The ISR name is the same name provided for the module in the device linker//script.void __attribute__((__interrupt__)) _U1TXInterrupt(void){ IFS0bits.U1TXIF = 0; //Clear the UART1 transmitter interrupt flag}

/*****************************************ENTRÉE DANS LA ROUTINE DE RÉCEPTION SÉRIE RS-232******************************************

CETTE ROUTIME PERMET DE RECEVOIR LES DONNÉES PROVENANT DU VARIATEUR DE VITESSE ET FONCTIONNE EN INTÉRUPTION.

***********************************************************************************************************************************/void __attribute__((__interrupt__)) _U1RXInterrupt(void){unsigned int temp=0;temp=U1RXREG;

if(RXsel==1) //Envoi la valeur recu dans posidata{

if(PTR<16 && temp!=13 && temp!=58){

PositionData[PTR]=temp; PTR=PTR+1;

}

if(PTR==16|| temp==13 || temp==58){

if(temp==13){STAT_RECEI=1;RXsel=0;}

PTR=0;

}}

if(RXsel==0){if(PTR<16 && temp!=13 && temp!=58)

{ ReceivedData[PTR]=temp; PTR=PTR+1;

}

if(PTR==16|| temp==13 || temp==58)

4

Page 147: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART_BON.c

{

if(temp==13){RS = 1;}

PTR=0;}

}

IFS0bits.U1RXIF = 0; //Clear the UART1 Receiver interrupt flag}

5

Page 148: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART2.c

///Pre-Processor Directives:#include <p30f4011.h>#include "system.h"#include <uart.h>.

#define BAUDRATE 921600 //Desired Baud Rate#define BRGVAL ((FCY/BAUDRATE)/16)-1 //Formula for U2BRG register //from dsPIC30F Family //Reference Manual

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR SEIZE BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 65535)*****************************************************************************************************/extern unsigned int RX2PTR;extern unsigned int PTR2;extern unsigned int Long;extern unsigned int DDD=0; extern unsigned int START; extern unsigned int STOP; extern unsigned int cons_ang_stat;extern unsigned int cons_load_stat;extern unsigned int cons_seuil_stat;

/**************************************************************************************************************DÉCLARATION DES VARIABLES SUR TRENTE-DEUX BITS NON SIGNÉS ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 4 294 967 295)**************************************************************************************************************/extern unsigned long RX2TEMP;extern unsigned long CONSLOAD;

/*****************************************************************************************************DÉCLARATION DES VARIABLES SUR HUIT BITS NON SIGNÉES ACCESSIBLE DANS TOUT LE PROGRAMME (0 À 255)*****************************************************************************************************/extern unsigned char TX2REFRESHVAL;

/*****************************************************************************************************DÉCLARATION DES CHAINES DE CARACTÈRES DISPONIBLES DANS TOUT LE PROGRAMME ET UTILISÉ DANS CETTE FEUILLE*****************************************************************************************************/extern unsigned char CONSIGNE[];extern unsigned char REFRESHVAL[];extern unsigned char consigne_posi[];extern unsigned char consigne_load[];extern unsigned char consigne_seuil[];extern unsigned char DisplayData[];

/*****************************************************************************************************DÉCLARATION DES FONCTIONS UTILISÉS SUR CETTE FEUILLE *****************************************************************************************************/void WriteUART2_to_RS232(void);void UART2_Init (void);

/******************************************************************************************************

DÉCLARATION DES FONCTIONS ACCESSIBLE PARTOUT DANS LE PROGRAMME AVEC VARIABLE À REÇU******************************************************************************************************/

void ConfigIntUART2(unsigned int config);void WriteUART2(unsigned int data);

/*****************************************************************************************************DÉCLARATION DES POINTEURS UTILISÉ SUR CETTE FEUILLE*****************************************************************************************************/unsigned int *UART2CharPtr;

//----------------------------------------------------------------------------------------------------------------------------------------//Functions//UART_Init() sets up the UART2 for a 8-bit data, No Parity, 1 Stop bit//at 38400 baud with transmitter interrupts enabled

1

Page 149: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART2.c

//Port Alternate uart1 jumper sur H4 = 1 void UART2_Init (void){

unsigned int conf = 2; ConfigIntUART2(conf);

U2MODE = 0x0000; //Clear UART2 registers U2STA = 0x0000; U2MODEbits.ALTIO = 1; //Enable U2ATX and U2ARX U2MODEbits.UARTEN = 1; //Enable UART2 module U2BRG = BRGVAL; //Load UART2 Baud Rate Generator

IFS1bits.U2RXIF = 0; //Clear UART2 Receiver Interrupt Flag IFS1bits.U2TXIF = 0; //Clear UART2 Transmitter Interrupt Flag IEC1bits.U2RXIE = 1; //Enable UART2 Receiver ISR IEC1bits.U2TXIE = 1; //Enable UART2 Transmitter ISR U2STAbits.UTXISEL = 1; //Setup UART2 transmitter to interrupt //when a character is transferred to the //Transmit Shift register and as result, //the transmit buffer becomes empty. U2STAbits.URXISEL =0; //Setup UART2 Receiver to interrupt //when a character is transferred to the //Transmit Shift register and as result, //the transmit buffer becomes empty.

U2STAbits.UTXEN = 1; //Enable UART2 transmitter IFS1bits.U2TXIF = 0; //Clear the UART2 transmitter interrupt flag

IFS1bits.U2RXIF = 0; //Clear the UART2 Receiver interrupt flag

}//----------------------------------------------------------------------------------------------------------------------------------------/*********************************************************************** Function Name : ConfigIntUART2 ** Description : This function sets priority for RX,TX interrupt * * and enable/disables the interrupt ** Parameters : unsigned int config enable/disable and priority ** Return Value : None * **********************************************************************/void ConfigIntUART2(unsigned int config){ /* clear IF flags */ _U2RXIF = 0; _U2TXIF = 0;

/* set priority */ _U2RXIP = 0x0007 & config; _U2TXIP = (0x0070 & config) >> 4;

// /* enable/disable interrupt */ _U2RXIE = (0x0008 & config) >> 3; _U2TXIE = (0x0080 & config) >> 7;}

/**********************************ENTRÉE DANS LA ROUTINE DE TRANSMISSION SÉRIE RS-232 (INTERFACE)**********************************

CETTE ROUTIME PERMET DE TRANMETTRE DES CHAÎNE DE CARACTÈRES A`L'INTERFACE DE CONTRÔLE.

***********************************************************************************************************************************/void WriteUART2_to_RS232(void){

UART2CharPtr = &REFRESHVAL[0]; //Initialize UARTCharPtr to pointputsUART2(UART2CharPtr);IFS1bits.U2TXIF = 0; //Clear the UART1 transmitter interrupt flag

}

2

Page 150: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART2.c

/********************************************************************** Function Name : WriteUART2 ** Description : This function writes data into the UxTXREG, ** Parameters : unsigned int data the data to be written ** Return Value : None **********************************************************************/void WriteUART2(unsigned int data){ while(U2STAbits.UTXBF)

{}

if(U2MODEbits.PDSEL == 3) U2TXREG = data; else

U2TXREG = data & 0xFF;}//----------------------------------------------------------------------------------------------------------------------------------------//_U1TXInterrupt() is the UART2 Interrupt Service Routine.//The routine must have global scope in order to be an ISR.//The ISR name is the same name provided for the module in the device linker//script.void __attribute__((__interrupt__)) _U2TXInterrupt(void){ IFS1bits.U2TXIF = 0; //Clear the UART2 transmitter interrupt flag}

/***********************************ENTRÉE DANS LA ROUTINE DE RÉCEPTION SÉRIE RS-232 (INTERFACE)************************************

CETTE ROUTIME PERMET DE RECEVOIR LES DONNÉES PROVENANT DE L'INTERFACE DE CONTRÔLE EN INTÉRUPTION.

***********************************************************************************************************************************/void __attribute__((__interrupt__)) _U2RXInterrupt(void){

unsigned int temp=0;unsigned int d=0;temp=U2RXREG;

if(((PTR2<6) && (temp!=13) && (temp!=58))&&((temp==48) || (temp==49) || (temp==50) || (temp==51) || (temp==52) || (temp==53) || (temp==54) || (temp==55) || (temp==56) || (temp==57) || (temp==71) || (temp==76) || (temp==83) || (temp==70) || (temp==78) ||(temp==79)))

{ CONSIGNE[PTR2]=temp; PTR2=PTR2++;}

if(temp==13) // Longueur ou : ou <cr>{

if(CONSIGNE[0]==0x47) // Permet de négliger les deux points{

cons_ang_stat=1;Long = PTR2;PTR2 = 0;//Long=4-RX2PTR;

}if(CONSIGNE[0]==0x4C){

cons_load_stat=1;Long = PTR2;PTR2 = 0;//Long=4-RX2PTR;

}if(CONSIGNE[0]==0x53){

cons_seuil_stat=1;Long = PTR2;PTR2 = 0;

3

Page 151: Rapport final - uqac.ca

C:\Users\Ben\Desktop\Ecole_2\Projet de conception 5 Crédits\Code final CEME New\Code final CEME\UART2.c

//Long=4-RX2PTR;}if((CONSIGNE[0]==0x4F) && (CONSIGNE[1]==0x4E) && (CONSIGNE[2]==0x4E)){

START = 1;PTR2 = 0;

}if((CONSIGNE[0]==0x4F) && (CONSIGNE[1]==0x46) && (CONSIGNE[2]==0x46)){

STOP = 1;PTR2 = 0;

}

}

if(temp==58){PTR2=0;}

IFS1bits.U2RXIF = 0;}

//**********************************************************************************************************************//putsUART2//**********************************************************************************************************************void putsUART2(unsigned int *buffer2){ char * temp_ptr2 = (char *) buffer2;

/* LA TRANSMISSION SE FAIT JUSQU'À LA DÉTECTION D'UN CARACTÈRE NULL */

while(*temp_ptr2 != '\0') { while(U2STAbits.UTXBF); /* wait if the buffer is full */ U2TXREG = *temp_ptr2++; /* transfer data byte to TX reg */ } }

4