Réalisation d'un oscilloscope.

J'ai pour mon projet de fin d'étude, réalisé un oscilloscope.
Il utilise un PIC 18F4550, et est relié au PC par le port USB.
Ce projet m'a permis de toucher à l'electronique, à la programmation des PIC, à l'USB, à l'OpenGL et à la programmation en C++.
J'ai donc décidé de mettre mon projet sur internet, car c'est toujours agréable de trouver des exemples de code ou de montage.

Tout est en téléchargement ici :

Dessin de la carte électronique. (Fait avec TCI).

Programme du PIC. (Développé avec MPLAB, en langage C).

Pilotes du PIC (fournis par Microchip(c)).

Logiciel "Oscilloscope". (Développé avec Visaul C++ Express Edition 2008).

Fichier HEX. (Peut être directement écrit dans le PIC mais je vous conseille de le compiler vous-même pour apporter des modifications).

Datasheets des composants utilisés.

Fichier d'entête de configuration du PIC 18F4550 Ce fichier m'a été envoyé par un internaute (merci Michel). Il contient toutes les directives de configuration, ce qui est assez pratique. De plus, sans ce fichier, vous ne pouvez pas être sur de la coniguration de votre PIC. Je conseil donc de l'ajouter au projet.

Photos & screenshot :






Et voilà mon rapport de projet, qui apporte des explications.
1. But du projet.
Bien qu'essentiel dans le travail des électroniciens, les oscilloscopes restent des outils peu abordables pour une utilisation par des amateurs. Les premiers prix se situent aux alentours de 200 euros. Le but de ce projet a donc été de développer un oscilloscope à bas prix, avec des composants répandus, pour ensuite mettre le schéma et les codes en ligne, et ainsi permettre aux internautes électroniciens amateurs, de pouvoir fabriquer eux-mêmes un oscilloscope.

2. Choix des composants.
L'utilisation d'un écran cathodique ou plat aurait été une solution trop chère. Utiliser l'écran d'un ordinateur était donc plus raisonnable. L'oscilloscope a pour but de réaliser l'échantillonnage des signaux, et de les envoyer à l'ordinateur.

La vitesse d'une liaison série (ou RS232) est de 9600 baud au maximum. Si chaque échantillon est codé sur 8 bits, la vitesse maximal atteignable avec un port série est de 9600/8 = 1200 HZ, ce qui est complètement insuffisant. De plus le port série est malheureusement voué à disparaître. Le port USB était donc plus adapté, car en haute vitesse (USB2.0), il peut théoriquement atteindre les 12Mbits/seconde, ce qui est bien supérieur à nos besoins.

Un micro-contrôleur capable de gérer l'USB 2.0 était donc nécessaire, ayant au moins 2 entrées analogique-numérique, et fonctionnant avec une alimentation de 5.0V, pour permettre une alimentation par le port USB. Le PIC 18F4550 à été choisis car il a les caractéristiques nécessaires, pour son bas prix, pour la qualité des exemples fournis par Microchip©, et pour sa popularité.

3. Fonctionnement général.
Schéma général de fonctionnement :

Prises Coaxiales



Oscilloscope

Conversion Analogique-Numérique
µ-contrôleur
(main.c)
Trames de données


USB



Décodage des trames Form1.cpp


Ordinateur

Ecran logiciel Ecran.dll

Ecran de l'ordinateur

Ce projet a été décomposé en deux parties, une première partie de développement autour du micro-contrôleur, puis une deuxième partie de développement purement logicielle.
4. Schéma électronique.

Notes :
La tension de référence à + 5.0 Volt a posé problème. En effet l'alimentation par le port USB n'est absolument pas stable. De plus, la résistance du fusible fait que la tension du circuit est de 4,75 V. Un oscilloscope étant avant tout un appareil de mesure, il était nécessaire d'avoir une tension stable et précise. Elle a été obtenue comme ceci :

A l'aide d'un ICL 7660, on alimente le circuit d'un doubleur de tension idéal. Voici le schéma de ce circuit :
On a V+ = 4,75V, et 0,6V environ au bornes des diodes. On a donc Vout = 8,4V.
Cette tension est alors suffisante pour alimenter une référence de tension de 5.0V (LM136-5.0).

Un autre problème s'est posé, l'impossibilité d'échantillonner des signaux négatifs. Un cavalier a donc été ajouté, qui permet de choisir la masse des bornes d'acquisition. Dans le mode « normal » la masse des bornes correspond à la masse du circuit. On ne peut échantillonner que des signaux entre 0 et +5.0V. Dans l'autre mode, la masse est à 2,5V, ce qui permet d'échantillonner des signaux entre -2,5V et +2,5V. Mais attention, le système sur lequel on fait les mesures, et l'ordinateur, ne doivent avoir aucune masse commune.

Les 2,5V sont déterminés par une référence de tension (AD580JH).

5. Le code du micro-contrôleur :

Le micro-contrôleur fonctionne à une fréquence de 20 MHZ.

La conversion analogique numérique est configurée avec les registres ADCON. A l'initialisation, on configure les entrées AN1 et AN2 en mode analogique, et on indique qu'on se réfère à Vref+ et Vref- comme bornes de l'acquisition.
Pour faire une conversion, on sélectionne d'abord sur quelle voie on veux faire une acquisition, puis on met le bit ADCON0bits.GO_DONE à 1. Cela va lancer l'acquisition. Ce bit repassera à 0 dès que l'acquisition sera terminée.
Le résultat sera alors stocké sur 10 bits dans le registre ADRES.

L'écran affiché sur l'ordinateur fait 600 pixels de large. A chaque rafraichissement de l'écran (soit toutes les 40msec), l'oscilloscope doit échantillonner 600 points, à la fréquence choisie par l'utilisateur. Chaque points est codé sur 2 octets, chaque écran utilise donc 1200 octets.

La fréquence d'acquisition détermine le temps/division à l'affichage. Pour les modes les plus rapides, le micro-contrôleur joue sur le registre ADCON2, qui modifie le temps nécessaire à une acquisition. Pour les modes plus lents, un delay permet d'obtenir la fréquence désirée.

Il y a dans le micro-contrôleur trois types de mémoires :
La RAM étant limitée à 256 octets, le micro-contrôleur est forcé de stocker les « écrans » de conversion dans la mémoire flash.
Mais cette mémoire étant plus lente, le résultat de chaque point d'acquisition est d'abord stocké temporairement en RAM. Le résultat y est codé, puis stocké en mémoire flash pendant une conversion, et non entre deux conversions.

A chaque requête d'un « écran », le micro-contrôleur lance 600 acquisitions, selon le modèle suivant.
  1. Lancement d'une acquisition. Cette acquisition va durer un certain temps, mais ne va pas bloquer le micro contrôleur.
  2. Changement si nécessaire de la variable «tour» qui permet d'échantillonner alternativement sur les 2 voies, si l'utilisateur le désir.
  3. Calcul du codage de trame (on ajoute un bit pour indiquer si le point vient de la voie 1 ou 2).
  4. Stockage en mémoire flash du résultat de la conversion précédente. L'accès à la mémoire flash étant assez lent, on y accède pendant une conversion, pour ne pas perdre de temps.
  5. Attente de la fin de la conversion.
  6. Stockage temporaire du résultat en mémoire RAM.
  7. Retour à l'étape 1.

Il est important de limiter au maximum le nombre d'instruction entre deux acquisitions, car ce temps perdu va jouer sur la fréquence d'acquisition, et donc sur la précision temporelle. Les instructions sont donc toutes placées, si possible, entre les étapes 1 et 5.

Ensuite, le micro-contrôleur envoi l' « écran » à l'ordinateur via le port USB.

Les librairies fournies par Microchip© ont rendues l'utilisation de l'USB assez simple. Le micro-contrôleur n'utilise que les primitives suivantes :
Les 600 points d'acquisition d'un écran, sont stockés en réalité dans 10 buffers de 120 octets, pour des problèmes de mémoire, et parce que l'USB ne peut envoyer des buffers supérieurs à 128 octets.

Le micro-contrôleur va donc envoyer ces 10 buffers successivement via l'USB, selon le modèle suivant :
  1. Vérification que le bus est libre (mUSBUSARTIsTxTrfReady).
  2. Préparation de l'envoi (mUSBUSARTTxRam).
  3. Taches de communication, envoi (CDCTxService).
  4. Taches USB(USBTasks).
  5. Retour à l'étape 1.

Ensuite, le micro-contrôleur attendra la prochaine requête d'un écran.


6. Le protocole de communication.

La détermination des règles de communication entre le micro-contrôleur et l'ordinateur a été cruciale.

Le micro-contrôleur peut recevoir les commandes suivantes :
Si la commande est de démarrer une acquisition, un deuxième caractère indique le temps d'une acquisition:
Le micro-contrôleur peut être complètement piloté avec ces commandes précédentes.

Le micro-contrôleur envoi des trames de 16 bis, pour chaque point de l'acquisition :
V1 V2 0 0 0 0 AN9 AN8 AN7 AN6 AN5 AN4 AN3 AN2 AN1 AN0

V1 : 1 acquisition venant de la voie 1, 0 sinon.
V2 : 1 acquisition venant de la voie 2, 0 sinon.
(V1 et V2 ne peuvent pas être à 1 tous les deux en même temps.)
AN9 -> AN0 : Résultat de la CAN, sur 10 bits.

Ces trames sont simples à coder et à décoder, et permettent une légère détection d'erreur. Mais elles ont un inconvénient, 4 bits ne sont pas utilisés, et le codage de V1 et V2 est redondant. On aura toujours V1 = not(V2). Ce codage est simple, mais pas optimal. Mais comme la fréquence d'acquisition n'est pas limitée par la vitesse de transmission des données, il n'a pas été jugé utile de l'optimiser.

La communication n'est pas synchronisée, tous les buffers envoyés par le micro-contrôleur vont être stocker dans une pile, en attendant d'être lu par l'ordinateur. L'ordinateur ne verra donc pas les 10 buffers de 120 octets, mais un seul buffer de 1200 octets.
7. Le logiciel «Oscilloscope».

Le développement a été fais avec Microsoft Visual C++ 2005 Express Édition, car il permet de développer simplement une interface graphique, et que l'on peut y intégrer des composants graphique utilisant l'OpenGL. De plus, ce logiciel est gratuit, a un compilateur extrêmement bien fait, et est en français.

Voici la face avant du logiciel « Oscilloscope » :

Il comprend les fonctions principales d'un oscilloscope.
Il permet de modifier les échelles en temps et en tension, et l'utilisation de 2 voies.
Il affiche la moyenne et l'amplitude du signal, ainsi que la fréquence d'échantillonnage.
Le bouton «Start/Stop» permet de lancer l'oscilloscope, ou bien de figer le signal.

Son principe est le suivant, à chaque rafraîchissement de l'écran, il doit lire les données envoyées par le micro-contrôleur, puis les afficher à l'écran, et enfin, demander au micro-contrôleur une autre acquisition.

Tout d'abord, le développement du module d'affichage, en OpenGL. Le module d'affichage est le composant qui permet de dessiner l'écran de l'oscilloscope ainsi que les signaux. Sans trop rentrer dans les détails, une seule fonction de dessin a été utilisée : les lignes brisées. Ce module comprend 2 tableaux de 600 valeurs. Les valeurs sont de type float. Il a deux propriétés essentiel : il affiche les points sous formes de lignes brisées, et ne prend pas en compte les points à 0. Ce module est compilé dans le fichier «ecran.dll» et peut ainsi être inséré dans Visual C++ comme un composant standard.

Grâce aux pilote fournit par microchip (mchpcdc.inf), le micro-contrôleur est reconnu en tant que «communication device» (ou CDC). Cela permet de communiquer avec lui comme s'il était branché sur le port série.
La librairie «LiaisonRS232.h» (trouvée sur internet) permet de communiquer avec un port série, ou un port série émulé, avec les fonctions suivantes :
int OpenCOM(int nId); Ouverture de la liaison série. Le micro-contrôleur est reconnu par l'ordinateur comme branché sur le port COM 6.
int ReadCOM(void* buffer, int nBytesToRead, int* pBytesRead); Lecture des données envoyées par le micro-contrôleur.
int WriteCOM(void* buffer, int nBytesToWrite, int* pBytesWritten); Envoi de données au micro-contrôleur.
int CloseCOM(); Fermeture de la connection.

Ces quatres fonctions sont suffisantes pour communiquer avec le micro-contrôleur. Ensuite dans le logiciel, un timer va lire le port COM toutes les 40 msec (ce qui fera 25 fois par seconde, fréquence de rafraichissement de l'écran).

Voici les différentes étapes de cette fonction activée par le timer :
  1. Déclaration des variables locales
  2. Définition des offsets en fonction de la référence des bornes d'acquisition (0 ou 2,5V).
  3. Lecture des données envoyées par le micro-contrôleur.
  4. Parcours des 600 points des buffers.
    1. Test d'appartenance à la voie 1 ou 2.
    2. Retrait du codage de la voie (-128 ou -64). Pour que le point rentre dans l'écran, cette valeur est multipliée par un coefficient (les valeures échantillonées se situent entre 0 et 1023, alors que le module d'affichage affiche des valeurs comprises entre -100 et 100).
  5. Affichage de la fréquence d'échantillonnage.
  6. Une fois sur dix, calcul de l'amplitude et de la moyenne. (Les calculs ne sont effectués qu'une fois sur dix pour faciliter la lecture).
  7. Envoi d'une requête pour l'acquisition suivante.

Le timer peut être interompu à n'importe quel moment par l'utilisateur pour figer l'écran.

8. Conclusion.

La fréquence maximal d'échantillonage atteinte (120 kHZ) est assez satisfaisante, compte tenu que la fréquence de fonctionnement du micro-contrôleur n'est que de 20 MHZ.

La précision de cet oscilloscope en tension est d'environ 2 %, ce qui est là aussi tout à fait satisfaisant.

Le coût total des composants de ne dépasse pas les 50€, ce qui est tout à fait dans la gamme fixée. Le seul écart au budget est l'achat d'une référence de tension à 6,80€.


Le convertisseur analogique numérique du micro-contrôleur n'était malheureusement pas optimal pour ce projet. Son amplitude de 5.0V est bien trop limitée, et il est assez bruité.

La tension de référence à 5.0V est fiable en théorie à 1% (en pratique on constate un écart de 2%). Or la tension de référence à 2,5V est fiable à 0,4%. Il aurais été plus intelligent de prendre la même fiablilité sur les deux références, 1% aurais largement suffi, et aurais été moins cher.

Il aurais été préférable que la valeur des bornes négatives ait été pilotée par le micro-contrôleur, plutôt qu'avec un cavlier.


Seuls des logiciels gratuits et distribués librement sur internet ont été utilisés. C'était important dans l'esprit du projet. Ainsi, les internautes qui voudraient fabriquer cet oscilloscope chez eux n'auront pas besoin de logiciels chers, et souvent plus compliqué à prendre en main.


Bien que centré sur une seule application, ce projet à demandé des connaissances aussi bien en électronique, qu'en programmation temps-réel ou en développement logiciel. Il permet de comprendre toutes les étapes à la réalisation d'un composant USB, pilotable par ordinateur. La diversité de ce projet a été grandement enrichissante.

9. Annexes.

I. Programme du micro-contrôleur : main.c.

//INCLUDES
#include <p18f4550.h>
#include <delays.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"

//DEFINES
#define TAILLE_BUFFER 120
#define NOMBRE_BUFFER 10
#define LED0 PORTBbits.RB0 //Voie 1
#define LED1 PORTBbits.RB3 //Voie 2
#define LED2 PORTCbits.RC6 //Connexion

//VARIABLES
#pragma udata gpr1
volatile char output_buffer0[TAILLE_BUFFER];
#pragma udata
[...]
#pragma udata gpr5
volatile char output_buffer9[TAILLE_BUFFER];
#pragma udata


char * bufferActuel;
char input_buffer[2];
char useAN0, useAN1, etat, tour, buffer, delai;
char tempH; char tempL;

//MAIN
void main(void){
InitializeSystem();
while(1){
USBTasks(); // Taches USB
CAN(); // Voir user\user.c & .h
}
}

// CONVERSION ANALOGIQUE NUMERIQUE
void CAN(void){
char i;
if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;

if(etat == 0) { //Etat "Attente des instructions".
if(getsUSBUSART(input_buffer,2)){ //Recoie les données du PC
switch(input_buffer[0]) {
case '0' : //Ne rien faire
useAN0 = 0; useAN1 = 0;
break;
case '1' : //Acquisition voie 1
useAN0 = 1; useAN1 = 0;
break;
case '2' : //Acquisition voie 2
useAN0 = 0; useAN1 = 1;
break;
case '3' : //Acquisition voie 1 et 2
useAN0 = 1; useAN1 = 1;
break;
case 'c' : //Allume la LED CONNEXION
LED2 = 1;
break;
case 'd' : //Eteint la LED CONNEXION
LED2 = 0;
break;
}
LED0 = useAN0; LED1 = useAN1;
// ADCON2 : Vitesse de l'acquisition.
switch (input_buffer[1]){
case '1' : //500us
ADCON2 = 0b10111001;
delai = 0;
break;
case '2' : //1ms
ADCON2 = 0b10101010;
delai = 0;
break;
case '3' : //2ms
ADCON2 = 0b10101110;
delai = 0;
break;
case '4' : //5ms
ADCON2 = 0b10101110;
delai = 95;
break;
case '5' : //10ms
ADCON2 = 0b10101110;
delai = 190;
break;
default :
break;
}
}
tempH = 0; tempL = 0;
tour = useAN1;
if (useAN0 || useAN1) {//Si une acquisition est lancée
/* Dans la partie qui suit, le code doit être le plus optimisé possible, car
** chaque instruction ralentira l'échantillonage. Il faut donc que le code soit
** le plus simple possible. De plus, il faut optimiser le temps de conversion,
** pour ne pas perdre du temps à attendre que l'acquisition soit finie.
*/
for(buffer = 0; buffer < NOMBRE_BUFFER; buffer++){
adressBuffer();
for(i=0; i<(TAILLE_BUFFER-2); i+=2) {
if (tour){
ADCON0 = 0x05; //Selection de la voie 2
ADCON0 = 0x07; //Lancement de l'aquisition.
} else {
ADCON0 = 0x01; //Selection de la voie 1
ADCON0 = 0x03; //Lancement de l'aquisition.
}
if (useAN0 && useAN1) { //Permet d'alterner les voies si
tour = !tour; //elles sont actives toutes les deux.
}
if (tour) {
tempH +=64; //Voie 0
} else {
tempH +=128; //Voie 1
}
bufferActuel[i] = tempH; //Stockage en FLASH
bufferActuel[i+1] = tempL;
if(delai) {Delay10TCYx(delai);}
while (ADCON0bits.GO_DONE); //Attend la fin de la conversion
tempH = ADRESH; //Stockage du résultat en RAM
tempL = ADRESL;
}
}
etat = 1; //Il y a des données à envoyer.
useAN0 = 0; useAN1 = 0; buffer = 0;
}
}

if (etat == 1) { // Etat : "données à envoyer"
if(mUSBUSARTIsTxTrfReady()){
adressBuffer();
mUSBUSARTTxRam((byte*)bufferActuel, TAILLE_BUFFER);
buffer++;
CDCTxService();
}
if (buffer == NOMBRE_BUFFER) {
buffer = 0;
etat = 0;
}
}
}

static void InitializeSystem(void){
TRISBbits.TRISB3 = 0; // Configure ces 3 pins en sortie.
TRISBbits.TRISB0 = 0;
TRISCbits.TRISC6 = 0;
mInitializeUSBDriver();

//Configuration des entrées analogique.
TRISA = 0b00001111; //PORTA en tant que sortie, AN0 et AN1 en entrée
ADCON1 = 0b00111101;//AN0 et AN1 en analogique
//Utilisation des références de tension

//Initialisation des variables.
etat = 0; useAN0 = 0; useAN1 = 0;
tour = 0; LED0 = 0; LED1 = 0;
LED2 = 0;
}

// TACHES USB
void USBTasks(void){
USBCheckBusStatus();
if(UCFGbits.UTEYE!=1)
USBDriverService();
#if defined(USB_USE_CDC)
CDCTxService();
#endif
}

// Cette fonction permet d'attribuer à bufferActuel, le buffer dont on a besoin.
void adressBuffer(){
switch(buffer) {
case 0 :
bufferActuel = output_buffer0;
break;
[...]
case 9 :
bufferActuel = output_buffer9;
break;
}
}


II. Fonctions principales du logiciel.

#define TAILLE_BUFFER 10000
using namespace System;

//VARIABLES GLOBALES
LiaisonRS232 maLiaisonRS232;
unsigned char buffer [TAILLE_BUFFER];
int calculs = 0;

namespace oscilloscope {
//Bouton Start
void Form1::clicStart(System::Object^ sender, System::EventArgs^ e){
int nBytesWritten = 0;
if (timer->Enabled) { //STOP
char buf[1];
buf[0] = '0';
if(maLiaisonRS232.WriteCOM(buf, 1, &nBytesWritten)){
timer->Enabled = false;
start->Text = "Start";
connect->Enabled = true;
CBvoie1->Enabled = true;
CBvoie2->Enabled = true;
Sleep(1);
maLiaisonRS232.ReadCOM(buffer, TAILLE_BUFFER , &nBytesWritten);
}
else{
MessageBox::Show("Erreur lors de l'arrêt de l'oscilloscope.");
}
} else { //START
char buf[2];
buf[0] = '0';
if (ecran->Voie1Active) {
buf[0]+=1;
}
if (ecran->Voie2Active) {
buf[0]+=2;
}
buf[1] = '1' + timeDivision;
if(maLiaisonRS232.WriteCOM(buf, 2, &nBytesWritten)){
timer->Enabled = true;
start->Text = "Stop";
connect->Enabled = false;
CBvoie1->Enabled = false;
CBvoie2->Enabled = false;
}
else{
MessageBox::Show("Erreur lors du démarage de l'oscilloscope.");
}
}
}
// TIMER 25 FOIS PAR SECONDE
void Form1::tickTimer(System::Object^ sender, System::EventArgs^ e){
int nbOctetsLus = 0;
int nBytesWritten;
int offset1; int offset2;
int k;

if (CB25->Checked) { //CB25 : référence ou masse à 2,5V
offset1 = 512;
offset2 = 0;
}else {
offset1 = 0;
offset2 = 100;
}
//Reception des données du micro-contrôleur
maLiaisonRS232.ReadCOM(buffer, TAILLE_BUFFER , &nbOctetsLus);

for (int i=0; i<=600; i++) {
if ((buffer[2*i] >= 128) && (buffer[2*i] <= 131)) { //VOIE1
ecran->Voie1[i] = (float)((((buffer[2*i]-128)*256 +
buffer[(2*i)+1])-offset1) / (voltDivision1)) - offset2;
ecran->Voie2[i] = 0.0f;
} else if ((buffer[2*i] >= 64 ) && (buffer[2*i] <= 67)) {//VOIE2
ecran->Voie2[i] = (float) ((((buffer[2*i]-64)*256 +
buffer[(2*i)+1])-offset1) / (voltDivision2)) - offset2;;
ecran->Voie1[i] = 0.0f;
} else {
MessageBox::Show("Erreur : Des données ont été perdues.");
ecran->Voie1[i] = 0.0f;
ecran->Voie2[i] = 0.0f;
}
}

if (!(calculs%10)){ //Les calculs ne sont fait qu'une fois sur 10
float min1 = 1024.0f; //pour plus de lisibilité.
float max1 = 0.0f;
float moy1 = 0.0f;
int m1 = 0;

float min2 = 1024.0f;
float max2 = 0.0f;
float moy2 = 0.0f;
int m2 = 0;

for(int i = 0; i<600; i++) {
if ((buffer[2*i]>=128)&&(buffer[2*i]<=131)&&(CBvoie1->Checked)){
min1=Math::Min(min1,(buffer[i*2]-128)*256+buffer[(i*2)+1]);
max1=Math::Max(max1,(buffer[i*2]-128)*256+buffer[(i*2)+1]);
moy1 +=((buffer[i*2]-128)*256 + buffer[(i*2)+1]);
m1++;
} else if((buffer[2*i]>=64)&&(buffer[2*i]<=67)&&(CBvoie2->Checked)){
min2 = Math::Min(min2,(buffer[i*2]-64)*256+buffer[(i*2)+1]);
max2 = Math::Max(max2,(buffer[i*2]-64)*256+buffer[(i*2)+1]);
moy2 +=((buffer[i*2]-64)*256 + buffer[(i*2)+1]);
m2++;
}
}
[...]//Affichage de la fréquence d'échantillonnage.
if (CB25->Checked) {
moy1 = (moy1 / m1) * ( 5.0f / 1024.0f ) - 2.5f;
moy2 = (moy2 / m2) * ( 5.0f / 1024.0f ) - 2.5f;
} else {
moy1 = (moy1 / m1) * ( 5.0f / 1024.0f );
moy2 = (moy2 / m2) * ( 5.0f / 1024.0f );
}

if(CBvoie1->Checked){
TBamplitude1->Text = ((max1 - min1)*( 5.0f / 1024.0f )).ToString();
TBmoyenne1->Text = moy1.ToString();
}
if(CBvoie2->Checked){
TBamplitude2->Text = ((max2 - min2)*(5.0f / 1024.0f )).ToString();
TBmoyenne2->Text = moy2.ToString();
}
}
calculs++;

//Demande de la prochaine acquisition :
char buf[2];
buf[0] = '0';
if (ecran->Voie1Active) {
buf[0]+=1;
}
if (ecran->Voie2Active) {
buf[0]+=2;
}
buf[1] =(char) '1' + timeDivision;
maLiaisonRS232.WriteCOM(buf, 2, &nBytesWritten);
}

void Form1::clicConnect (System::Object^ sender, System::EventArgs^ e){
char buf [1];
int nBytesWritten;
if (start->Enabled == false) {
if(maLiaisonRS232.OpenCOM(Convert::ToInt32(TBcom->Text))){
connect->Text = L"Disconnect";
etatOscillo->Text = L"Oscilloscope connecté.";
start->Enabled = true;
buf [0] = 'c';
maLiaisonRS232.WriteCOM(buf, 1, &nBytesWritten);
} else {
MessageBox::Show("Impossible d'ouvrir le port " +
Convert::ToInt32(TBcom->Text) + ".");
}
} else {
buf [0] = 'd';
maLiaisonRS232.WriteCOM(buf, 1, &nBytesWritten);
if(maLiaisonRS232.CloseCOM()){
connect->Text = L"Connect";
etatOscillo->Text = L"Oscilloscope non connecté.";
start->Enabled = false;
} else {
MessageBox::Show("Impossible de fermer le port COM12.");
}
}
}
[...]//Autres fonctions retirées faute de place.
}

III. Mode d'emploi.

  1. Connecter l'oscilloscope sur le port USB de votre ordinateur.
  2. La led "alimentation" doit alors s'allumer.
  3. Lors de la première installation, indiquer à votre ordinateur l'emplacement du pilote (mchpcdc.inf).
  4. Lancer le logiciel Oscilloscope.
  5. Rentrer le port sur lequel votre oscilloscope est connecté (pour le connaître, vous pouvez utiliser le gestionnaire de periphériques, ou l'hyper terminal).
  6. Cliquer sur "connecter".
  7. La led "connexion" doit s'allumer.
  8. Selectionner la ou les voies que vous voulez observer.
  9. Cliquer sur "start".
  10. La ou les leds rouges correspondantes doivent s'allumer.
  11. Pour figer une acquisition, cliquer sur stop.
  12. La ou les leds rouges correspondantes doivent s'éteindre.
  13. Cliquer sur "deconnecter".
  14. Vous pouvez alors débrancher votre oscilloscope.


Notes :


IV. Composants utilisés.

Composant

Quantité

Prix

PIC 18F4550

1

18,00 €

ICL 7660

1

1,30 €

AD580JH

1

6,80 €

LM336Z-5.0

1

0,65 €

Quartz 20 MHZ

1

2,60 €

Fusible

1

1,65 €

Connecteur USB

1

1,10 €

Diode 75mA

2

0,04 €

Diode lumineuse

4

1,20 €

Condensateur 470nF

1

0,50 €

Condensateur 10uF

2

0,20 €

Condensateur 100nF

2

0,50 €

Condensateur 22pF

2

0,50 €

Résistance 150Ω

4

0,18 €

Support DIL 40

1

1,30 €

Plaque

1

3,80 €

Boitier

1

5,60 €




Total


45,92 €


V. Logiciels utilisés.