Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Commentez, partagez et proposez des Tutos en langage C !
Convertisseur Analogique/Numérique avec Vref interne
Jérémy
Administrateur du site
Administrateur du site
Messages : 2095
Âge : 39
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » jeu. 12 janv. 2017 11:48

Bonjour à tous,


Je vous propose de voir ici le convertisseur Analogique/numérique avec référence de tension interne !



Configuration :
Plaque easyPIC7.jpg

- PIC18F46K22
- Plaque EasyPIC V7
- IDE : MikroC Pro for PIC Version 7.0.0
- Compilateur : Mikro prog suite fo PIC V 2.5

Pré-requis :

- Lire le tutoriel Convertisseur analogique/numérique

Le but :

La fonction de mikroC Read_ADC, ne fonctionne pas avec une référence de tension interne. C'est pourquoi il faut faire sa propre routine. Je vous propose donc de voir les différents registres à "régler" ainsi que le lancement d'une mesure, pour obtenir un comportement correct de votre ADC avec une référence interne !


1/ Préambule:

La référence interne, appelée FVR pour Fixed Voltage référence, va nous permettre d'avoir une référence FIXE quelque soit la tension qui alimente notre PIC.
Bien évidemment la FVR devra toujours être inférieur à la tension d’alimentation de votre PIC (Vdd). Dur dur d'avoir une référence de 4.096V si on alimente notre PIC en 3.3V :shock:

La tension FVR de "base" est de 1.024V. En la multipliant en interne, on peut obtenir une tension 2.048 et 4.096V.
Cependant tous les PIC ne supporte pas cette FVR, il vous faut vous referez à sa feuille de données.

dans 90% des cas on utilise Vss et Vdd comme référence, pour une conversion analogique numérique standard, car nos cher pics sont alimentés derrière un régulateur de tension, propre , bien stable et bien découplé !

certains se diront :
mais a quoi peut bien servir une lecture analogique avec référence interne ? :idea:


Prenons un exemple très concret !

Imaginons un instant, que cette tension d'alimentation du pic ne soit pas stable, mais au contraire qu'elle évolue avec le temps ! Comme par exemple une alimentation en direct sur une batterie, qui se viderait au fil du temps.
Dans ce cas il est devient difficile de pouvoir lire une valeur correcte avec une référence qui bouge aussi ! :mur:

ceci est un exemple parmi tant d'autre, mais plutôt parlant je trouve :wink: !


2/ La configuration

On va configurer notre PIC étape par étape.

==> - Les Ports I/O
==> - Le registre ADCON0
==> - Le registre ADCON1
==> - Le registre ADCON2
==> - Le registre De configuration de FVR

Sur le PIC choisi pour le tutoriel il y a trois registre ADCONx à paramétrer !. Suivant votre PIC cela peut éventuellement être différent.
Je travaillerais avec la broche RA0 pour effectuer ma lecture analogique dans mon exemple.

Voici ce que ça peut donner avec les commentaires sur chaque lignes et les pages de la DS!

Code : Tout sélectionner



  ANSELA 
= 0b00000001;     // RA0 en analogique
  TRISA = 0b00000001;      // RA0 en entrée


  // Configuration de l'ADCON0  page 304 ------------------------------------
                          // bit 7 non utilisé
                          // CHS<4:0> = choix du canal AN0  = 00000
  ADCON0 = 0b00000001;    // Go/~DONE = 0 , stand-by pour la conversion
                          // ADON = 1, activation du module AD

  // Configuration de l'ADCON1  page 305 --------------------------------------
                          // TRIGSEL = 0, non utilisé
                          // bit <6:4>= non utilisé
  ADCON1 = 0b00001000;    // PVCFG <1:0> = 10 , REF+ = FVR BUF2
                          // NVCFG <1:0> = 00 , REF- = GND

  // Configuration de l'ADCON2  page 306--------------------------------------
                          // ADFM = 1, justification à droite
                          // bit 6 non utilisé
  ADCON2 = 0b10101001;    // ACQT<2:0> = 101, temps d'acquisition de 12 Tad
                          // ADCS<2:0> = 001, Fosc/8

  // Configuration de Vref  page 344-----------------------------------------
                          // FVREN_bit = 1;   // Activation du Vref
                          // FVRST = 1;       // Prêt à être utilisé
  VREFCON0 = 0b11100000 ; // FVRS<1:0> = 10 , Vref = 2.048V
                          // bit 3, 2, 1 et 0 non utilisé



Voila pour mon PIC, suivant le votre ce sera forcement différent ! L'important est de bien suivre les étapes :
- Configuration des I/O et ana/num
- Activer le module ADC et choisir le canal de lecture analogique
- Régler la tension de référence(FVR) basse et haute
- Régler la valeur de la FVR haute
- Après tout ces réglages, bien veiller à activer la FVR ! :roll:

Vous voila maintenant avec une notion de la configuration manuelle de votre convertisseur analogique numérique !
Pour toutes questions sur des points particuliers, dirigez-vous sur le Forum, les membres se feront une joie de vous répondre :razz:

3/ La fonction de lancement d'une lecture

Pour démarrer un cycle de conversion, rien de bien compliqué, il faut mettre le bit correspondant au lancement à "1" .
Sur mon PIC il s'agit du bit "GO/DONE" du registre ADCON0, voir explication page 304 . Une fois ce bit à "1" le PIC lance une analyse de conversion. Une fois la conversion terminé ce bit ce met à "0" tout seul .
idea ! Très pratique ça, pour savoir quand on à fini la conversion, vous ne trouvez pas ?

On va juste mettre ce bit à "1" puis attendre qu'il passe à "0" . et le tour est joué !

Cela donne :

Code : Tout sélectionner


     ADCON0
.B1 = 1;     // On démarre la conversion en mettant le bit à "1"
     while (ADCON0.B1==1); // // Tant que le bit est à "1" je reste ici. En gros j'attends qu'il passe à 0
 


C'est bien beau ça , mais elle est où notre valeur de conversion !


Bonne question ! Toujours d’après la DS, la valeur de la conversion est stockée dans les registres ADRESL ( Adresse Low) et ADRESH (Adres High).
Et oui la valeur est sur 10,12 voir 14 bit, il faut donc 2 registres pour la stocker . Une partie haute et une partie basse.
Le bit ADFM du registre ADCON2 sert a formater cette valeur avec une justification à droite ou non .
Prenons par exemple la valeur sur 10 bit de : 0b1101001000 avec une justification à droite les 8 bits de poids faibles seront stocké dans ADRESL et les 2 restantes ( celle de poids fort donc ... :-D ), seront stockées dans ADREH . soit :
ADRESL = 0b01001000
ADRESH = 0b11

Pour retrouver notre valeur une petite formule s'impose:
On multiplie par 256 le registre des bits de poids fort et on l'additionne au bit de poids faible.
Je nomme "temp" la variable de stockage !

Code : Tout sélectionner

Temp = ((ADRESH)*256) + ADRESL


PS: la multiplication est gourmande en ressource, un décalage de 8 sur la gauche fait la même chose

Code : Tout sélectionner

Temp = ((ADRESH<<8) + ADRESL


Et voila normalement vous avez toutes les cartes en main, pour vous configurez et utiliser le convertisseur analogique numérique avec une tension de référence interne !


► Afficher le programme test


La vidéo est légèrement tronquée, car l'alimentation de ma carte Easypic est fixe. Mais le principe reste le même , une référence interne, est utilisée. On voit donc apparaitre une plage morte, quand la tension dépasse la FVR, la valeur reste bloquée à 2.048V.

http://www.dailymotion.com/video/x587zfj


idea ! Conseils :

Il est préférable de faire une suite de mesure pour en tirer une moyenne, rendant le résultat bien plus fiable. En générale une série de 8 ou 16 valeurs est suffisantes et cela permet par simple décalage de bit de trouver sa moyenne ( plutôt qu'une division) :wink:
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Convertisseur Analogique/Numérique avec Vref interne
Gérard
Avatar de l’utilisateur
Confirmé
Confirmé
Messages : 789
Âge : 59
Enregistré en : septembre 2015
Localisation : Alsace

#2 Message par Gérard » jeu. 12 janv. 2017 14:31

C'est du bon boulot. :bravo:
Le 11 / 07 / 2017, j'ai commandé une Ford Mustang.
Le 31 / 08 / 2017, j'ai eu la Mustang, un régal.

Convertisseur Analogique/Numérique avec Vref interne
venom
Avatar de l’utilisateur
Passioné
Passioné
Messages : 368
Âge : 32
Enregistré en : avril 2016
Localisation : . <------ ici
Contact :

#3 Message par venom » jeu. 12 janv. 2017 18:11

Je te re merci pour ce tuto Merci !






@++

Convertisseur Analogique/Numérique avec Vref interne
paulfjujo
Avatar de l’utilisateur
Expert
Expert
Messages : 1019
Âge : 67
Enregistré en : juillet 2015
Localisation : 01120
Contact :

#4 Message par paulfjujo » ven. 26 mai 2017 14:54

bonjour,



ATTENTION , sur le PIC16F1847
usage de la tension de refernce interne +Vref=2,048V

Code : Tout sélectionner

EA0=ADC_READ(0); 

ne donne pas le bon resultat , malgré :

Nouveauté de MIkroC 7.01 :
function specifique pour usage des tensions de references interne pour la gamme de l'ADC

Code : Tout sélectionner


 ADC_Init_Advanced
(_ADC_INTERNAL_FVRH2); // 2,048V   

et la note , dans l'aide de MikroC ADC_Read

:furieux:
Note : This function doesn't work with the external voltage reference source, only with the internal voltage reference.

Ce devrait donc etre bon .. que nenni !

par contre , si j'utilise

Code : Tout sélectionner

EA0= ADC_Get_Sample(0); 

j'obtiens bien le resultat voulu.

le bout de code mettant ceci en evidence:

Code : Tout sélectionner


   txt
=&TEXTE[0];
  CRLF1();
  UART1_Write_CText(" Init ADC EA0 gamme 2,048V + diviseur par 2\r\n");
  ADC_Init_Advanced(_ADC_INTERNAL_FVRH2); // 2,048V
  Delay_ms(100);
  //--- Main loop
  
   UART1_Write_CText
("Test Batterie :\r\n ");
   UART1_Write_CText(" +VCC-------- R=2,7K ----|---- R=2,7K ------------ /  0V \r\n");
   UART1_Write_CText(" 3,86V                   |------> 1,93V on EA0        \r\n");
    CRLF1();
  #define TEST2
  do {
        
  
//  RAZ_UART1();
    Delay_ms(1000);



      UART1_Write_CText("Test Batterie ");
   #ifdef TEST1
     UART1_Write_CText(" (avec ADC_Read(0) = ");
     EA0=ADC_Read(0);
     WordToStr(EA0,CRam1);
     UART1_Write_Text(CRam1);UART1_Write(TAB);
     Battery_Volt=(float)(EA0<<2) / 1000.0;   // 2,048 pleine echelle, mais diviseur de tension 1/2 !
     FloatToStr_FixLen(Battery_Volt,CRam1,6);
     UART1_Write_Text(CRam1); UART1_Write_CText(" v  ");
    #endif
   
   
#ifdef TEST2
     UART1_Write_CText(" (avec ADC_Get_Sample(0) = ");
     EA0=ADC_Get_Sample(0);
     Battery_Volt=(float)(EA0<<2) / 1000.0;   // 2,048 pleine echelle, mais diviseur de tension 1/2 !
     WordToStr(EA0,CRam1);
     UART1_Write_Text(CRam1);UART1_Write(TAB);
     Battery_Volt=(float)(EA0<<2) / 1000.0;   // 2,048 pleine echelle, mais diviseur de tension 1/2 !
     FloatToStr_FixLen(Battery_Volt,CRam1,6);
     UART1_Write_Text(CRam1); UART1_Write_CText(" v");
  #endif
    CRLF1();
  }
    while(1);
}
 


et les resultats obtenus dans les 2 cas:

:eek: BAD !
Init ADC EA0 gamme 2,048V + diviseur par 2
Test Batterie (avec ADC_Read(0) = 519 2.075 v
Test Batterie (avec ADC_Read(0) = 519 2.075 v
Test Batterie (avec ADC_Read(0) = 520 2.079 v
Test Batterie (avec ADC_Read(0) = 519 2.075 v
Test Batterie (avec ADC_Read(0) = 520 2.079 v
Test Batterie (avec ADC_Read(0) = 519 2.075 v


:-D OK!
Init ADC EA0 gamme 2,048V + diviseur par 2
Test Batterie (avec ADC_Get_Sample(0) = 953 3.811 v
Test Batterie (avec ADC_Get_Sample(0) = 954 3.815 v
Test Batterie (avec ADC_Get_Sample(0) = 953 3.811 v
Test Batterie (avec ADC_Get_Sample(0) = 952 3.807 v
Test Batterie (avec ADC_Get_Sample(0) = 954 3.815 v
Test Batterie (avec ADC_Get_Sample(0) = 953 3.811 v


Nota: le #define TEST1 ou #define TEST2 permet de tester chacun des cas de figure
et 1 seul à la fois.

la question est posée à MikroE ..

Si ça continue, on va devoir ecrire NOS propres fonctions en ASM ... c'est le comble

à suivre


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité