Le logiciel windows
L'exemple de client que nous allons écrire sera en Delphi. Il existe des versions gratuite de Delphi disponible sur http://www.codegear.com.
Pour nous simplifier la tâche, nous allons utiliser une DLL écrite par Mecanique (http://www.mecanique.co.uk). Dans le dossier téléchargeable à la fin de l'article, vous trouverez cette DLL. Celle-ci était fournir avec le logiciel EasyHID, les copyright de ce dernier nous empêchant de le distribuer, nous ne vous transmettrons que la DLL et le code source du programme que nous avons réalisé.
Le logiciel - Exploration du code
Premièrement nous avons quatre constantes importantes :
BufferInSize = 64;
BufferOutSize = 64;
VENDOR_ID = 1240;
PRODUCT_ID = 0005;
Nous nous rappellerons que lorsque nous avons travaillé le firmware de la carte, nous avons brièvement parlé du descripteur, dans lequel nous configurons le VID (Vendor ID) PID (product ID). Ces deux valeurs identifiant auprès de l'ordinateur le périphérique branché. Dans le client qui va communiquer avec la carte, ces deux valeurs doivent se retrouver. Nous avons aussi la taille du buffer d'entrée et de sortie que nous avons configuré à 64 octets.
Nous sautons volontairement dans le code de nombreuses lignes de codes propres à la création des objets et la déclaration des procédures qui est automatique générée par delphi pour en arriver à l'envoie des informations. Pour ça nous avons un petit commentaire bien sympathique que nous allons analyser :
(*
if you want to write some data to the USB device, then
try using something like this...
// first element is report ID, set to 0...
FBufferOut[0] := $0;
// fill the buffer with some data...
for index := 1 to BufferOutSize do
FBufferOut[index] := index;
DevHandle := GetHandle(VendorID, ProductID);
Write(DevHandle,@FBufferOut);
*)
Le programme nous trouvons un tableau utilisable dans toute l'application de 65 éléments qui s'appelle FBufferOut. C'est dans ce tableau que l'on place les données à envoyer. Pourquoi 65 ??? Parce que l'élément 0 du tableau c'est le reportID, il devra toujours est mis à 0 comme indiqué dans le commentaire. Nous pouvons ensuite mettre dans les case 1 à 64 toutes nos données.
Une fois les données prêtes, nous devons créer la communication avec la carte. La première étape est de dire au programme à quelle adresse il doit envoyer son paquet. Pour ça DevHandler, variable de type cardinal, se voit attribuer une valeur, et cette valeur sera donnée par la fonction GetHandle (VendorID, ProductID). C'est là que l'on remarque l'importance de ces deux nombres. En effet lorsque l'on connecte la carte à l'ordinateur, celui-ci lui octroit un « Handle » et pour retrouver cet « Handle » et pouvoir communiquer avec la carte, il faut demander à l'ordinateur quel valeur il a attribué à la carte possédant tel et tel VID et PID. Il nous suffit plus que d'envoyer le tout par la fonction Write(DevHandle, @FBufferOut) . « @ » Car nous envoyons à la fonction la référence du tableau contenant les informations afin que celle-ci récupére chaque élément en mémoire.
La lecture de donnée se passe de façon différente. Nous avons dans le code du programme, une fonction préécrite :
function TForm1.USBEvent(var Msg: TMessage): Boolean;
Cette fonction réagit à chaque événement qui se produit sur le port USB. Si l'on connecte ou déconnecte une carte… Si elle envoie des données… C'est-à-dire que chaque fois qu'il va y avoir un échange entre une carte et l'ordinateur, cette fonction va réagir automatiquement. Et dans cette fonction nous avons justement :
NOTIFY_READ :
begin
DevHandle := Msg.LParam; // handle of HID device in this message
if (GetVendorID(DevHandle) = VENDOR_ID) and (GetProductID(DevHandle) = PRODUCT_ID) then begin
// read the data - remember that first byte is report ID...
Read(DevHandle,@FBufferIn);
// process data here...
end;
Une fois que la carte va créer un évènement en voulant envoyer quelque chose, le logiciel va détecter qu'il s'agit de donnée à recevoir, il va alors entrer dans cette partie de procédure NOTIFY_READ.
Première étape il va regardé le « Handle » de la carte qui envoie une donnée, et va comparé celui-ci au « Handle » de notre carte, s'il s'agit du bon, il va lire les données envoyées par la carte. Nous pouvons alors placer notre code à la suite de cette instruction Read(DevHandle, @FBufferIn). Toutes les données reçues se trouveront dans le tableau FBufferIn.
Le Logiciel - Réalisation de notre interface
Pour cette opération, nous aurons besoins de :
-
3 Labels
-
1 Gauge
-
2 Boutons
-
2 SpinEdits
-
1 Memo
Placé comme sur l'image ci-dessus.
La gauge nous donnera en pourcent la valeur de la tension par rapport 5V, le bouton "mesurer" demandera une mesure, le premier label nous affichera la valeur mesurée, le bouton "Clignoter" enverra un paquet avec le nombre de clignotement et la période de ceux-ci. Et les deux spinedits permettront de configurer ces deux derniers paramètres.
Pour demander une mesure, nous devons simplement envoyer un paquet où l'élément 1 du paquet vaut 0 :
// mise à 0 du buffer
FBufferOut[1] := $0; // on met le buffer[0] a 0
// Attribution de la carte usb
DevHandle := GetHandle(VENDOR_ID , PRODUCT_ID);
Write(DevHandle,@FBufferOut);
Pour faire clignoter la led, nous devons placer 1 dans l'élément 1 du buffer, placer le nombre de fois dans l'élément 2 et la pause entre chaque changement d'état dans l'élément 3
// mise à 0 du buffer
FBufferOut [1]:= 1 ;
FBufferOut [2]:= spinedit1.value ; // N° de fois
FBufferOut [3]:= spinedit2.value ; // la pause
// Attribution de la carte usb
DevHandle := GetHandle(VENDOR_ID , PRODUCT_ID);
Write(DevHandle,@FBufferOut);
Petit conseil pour éviter les erreurs, dans les paramètres du spinedit, placez que celui-ci ne peut pas prendre de valeur supérieur à 255.
Maintenant la réception des données, comme nous l'avons vu précédemment, lorsque la carte va nous envoyer quelque chose, le programme va directement réagir, nous allons donc créer une nouvelle fonction « Refresh » qui sera appelée par la fonction USBEvent lorsque celle-ci réagira pour un envoie de donnée :
NOTIFY_READ :
begin
DevHandle := Msg.LParam; // handle of HID device in this message
if (GetVendorID(DevHandle) = VENDOR_ID) and (GetProductID(DevHandle) = PRODUCT_ID) thenbegin
// read the data - remember that first byte is report ID...
Read(DevHandle,@FBufferIn);
Refresh ; // On appelle alors la fonction refresh !
// process data here...
end;
La fonction "refresh" va premièrement regarder ce qui lui est envoyé, la carte enverra en élément 1 du paquet '255' s'il s'agit d'une mesure, le seul cas qui nous intéresse. S'il s'agit bien de 255, l'élément 2 possédera les 8 bits de poids fort et l'élément 3 les deux bits de poids faible restant de la conversion analogique (qui s'effectue sur 10 bits, ouf on a assez de doigts). Par une petite opération mathématique, nous reconstituons une seule valeur binaire regroupant les deux parties du message. Et nous affichons le résultat :
function TForm1.Refresh(): integer;
var i : integer;
var valeur : integer;
begin
if (FBufferIn[1]=255) then begin
valeur := FBufferIn[2]*4 + round(FBufferIn[3]/64);
gauge1.Progress :=round(100*valeur/1024);
label3.caption :='La valeur est : '+floattostrf(5 * valeur/1024,ffFixed,3,2)+' Volt';
end;
result := 0;
end;
Installation du tout :
Il nous reste plus qu'à monter le tout, nous laisserons le soin à l'utilisateur de monter la carte par ses propres moyens, sachant que schéma et pcb sont mis à disposition. Pour la programmation du 18f4550, le programmateur de pic disponible sur ce site fonctionne très bien avec le 18f4550 en utilisant le logiciel WinPic800. Il ne suffit plus que de charger le firmware avec ce programme, toutes les options se configureront automatiquement.
Pour le logiciel, voici un screen de l'application en fonctionnement, vous remarquerez que la fonction « mesurer » est identique à l'action de pousser sur le bouton. Et que la gauge évolue en fonction de ce qui se trouve sur l'entrée analogique 0. Ceux muni d'un chronomètre pourront aussi vérifié le bon fonctionnement du clignotement.
Autres informations et liens
Dès à présent, il vous est possible de réaliser vos propres interface usb, celle-ci est compatible avec toutes les versions de Windows supérieur où égale à 98. N'oubliez par de munir votre programme du fichier mcHID.dll.
Pour ceux qui voudrait en savoir plus sur les PID/VID et tout le reste :
http://www.abcelectronique.com/acquier/USB.html
Pour ceux qui voudrait utiliser autre chose que la DLL de mencanique, voici un composant pour Delphi permettant de communiquer avec les interface HID :
ftp://ftp.delphi-jedi.org/api/hid.zip
Pour ceux qui veulent en savoir plus sur le 18f4550 :
L'ensemble des fichiers nécessaire et suffisant à la réalisation de l'exemple de cet article est disponible directement ici:
Télécharger le dossier relatif à la carte d'interface USB HID