mardi 3 décembre 2019

Alimentation 3.7V Numérique



Alimentation 3.7V Numérique


Dans la vie d'un concepteur de montages alimentés par batterie LITHIUM-ION ou LIPO il n'est pas rare d'avoir besoin de faire des tests en faisant varier la tension de la batterie.

Généralement on se débrouille avec une alimentation de laboratoire. Le danger de dépasser la tension maximale supportée par le montage n'est pas négligeable, surtout avec mon alimentation qui ne possède pas de bouton de réglage fin. De plus elle est très imprécise dans la plage des tensions faibles < 5V.

Il serait préférable d'utiliser une alimentation limitée à 4.2V, la tension maximale d'une batterie chargée à 100%.
Descendre en dessous de 3V n'est pas très utile, car il est déconseillé de laisser une batterie LITHIUM se décharger en dessous de cette tension.

L'alimentation étudiée dans cet article est numérique. la tension de sortie est réglable grâce à un encodeur rotatif, par pas de 50mV, et d'un écran OLED :


Elle est également pilotable par la ligne série depuis un terminal, ou un logiciel maison.

Ce projet requiert une expérience assez moyenne en développement électronique, et le logiciel n'est pas difficile à comprendre.
Différents sujets matériels et logiciels sont abordées :
  • utilisation d'un régulateur ajustable
  • utilisation d'un DAC (Digital to Analog Converter)
  • mesure de tensions continues
  • utilisation d'une référence de tension externe (TL431)
  • utilisation d'un encodeur rotatif
  • utilisation d'un écran OLED
  • réception de commandes simples par la ligne série (shell)
Dans la première partie, le sujet régulation est traité. Ceux qui seraient seulement intéressés par une alimentation réglable toute simple peuvent éviter la suite.

1. La régulation

Lorsque l'on conçoit une alimentation réglable le schéma le plus couramment utilisé est de ce type :
Ce schéma utilise un LM317, régulateur ajustable pouvant délivrer 1.5A.

Avec une résistance R2 de 330Ω la tension de sortie sera de :

VMIN = VREF x (1 + R2 / R1) + (IADJ× R2)
VMIN = 1.25 × (1 + 330 ÷ 240) + (0.000050 × 330) = 2.98V

Si l'on adopte une résistance R2 de 580Ω (notre résistance de 330Ω + un potentiomètre de 250Ω) la tension de sortie maximale sera de :

VMAX = 1.25 × (1 + 580 ÷ 240) + (0.000050 × 580) = 4.29V

Un potentiomètre de 250Ω ne se trouve pas facilement. On pourra utiliser un modèle 470Ω + une résistance de 470Ω ou 510Ω en parallèle :

Le LD1085, pouvant délivrer 3A, pourra être utilisé en lieu et place du LM317. Il faudra remplacer les condensateur C1 et C3 par des condensateurs de 10µF / 10V.

Voilà pour la partie analogique. Comme on le voit, avec quelques calculs basiques, il est assez simple de concevoir une alimentation réglable.
Un autre article traite du sujet "alimentations à transformateur" pour ceux qui désireraient ajouter les composants nécessaires pour obtenir une alimentation à brancher directement sur le secteur :
https://riton-duino.blogspot.com/2019/01/alimentation-transformateur.html

2. La version numérique

Il est possible de remplacer le potentiomètre par un composant numérique : soit un potentiomètre numérique, soit un DAC (Digital to Analog Converter).

Il semble plus logique d'utiliser un potentiomètre numérique puisqu'il vient directement remplacer notre potentiomètre RV1 du schéma précédent.
Mais un potentiomètre ne fait que convertir le courant qui le traverse en tension, tension qu'un DAC sera capable de produire aussi facilement.

Les potentiomètre numériques les plus précis ont 256 pas, mais malheureusement leur résistance est souvent de 10KΩ, très loin des 250Ω requis.
On trouve des modèles 8 bits (256 pas) de 1KΩ (AD8400), pour un peu plus de 3€, mais un DAC MCP4725 12 bits aura une résolution supérieure. De plus on le trouve sous forme de module pour moins d'1€ :
Cette différence de prix est compréhensible. Un potentiomètre numérique est censé laisser passer des signaux alternatifs. Il est adapté à l'audio (l'AD8400 a une distorsion de 0.015%). La complexité de  ce composant est sans commune mesure avec celle d'un DAC 12 bits, qui est un simple convertisseur numérique / analogique.

Il nous faudra bien entendu piloter le DAC à l'aide d'un microcontrôleur.

Quel est le but ? il n'est pas simplement de se compliquer la vie. Les avantages sont multiples :
  • on peut utiliser un encodeur rotatif à la place du potentiomètre
  • un ordinateur peut également piloter l'alimentation à distance
  • comme on dispose d'un processeur, on peut ajouter :
    • un afficheur
    • des entrées de mesure analogique
    • des entrées / sorties digitales
Les possibilités sont nombreuses, en particulier en matière de test automatisé.

Avec un tel outil il devient possible de tester un dispositif d'alimentation en pilotant l'alimentation depuis un PC avec un logiciel adapté, écrit en PYTHON par exemple (voir unittest).
Les entrées analogiques peuvent être utilisées pour vérifier des tensions.
Les sorties digitales peuvent être utilisées pour piloter des relais ou des MOSFET ou lire l'état d'une sortie (une LED par exemple).

Si nous avons à tester une carte alimentée par batterie on peut imaginer plusieurs cas de test :
  • fixer la tension batterie à 3.0V, 3.7V ou 4.2V
  • activer une alimentation secteur (relais)
  • vérifier la tension de sortie d'un régulateur
  • vérifier qu'une LED est allumée ou qu'elle clignote
  • etc.
Voici le schéma :
Le schéma est réalisé à l'aide de KICAD.

Pour récupérer le projet voir plus bas :  11. Téléchargements.

La tension d'entrée est fournie par une alimentation 7.5V, 9V ou 12V.

Il est possible d'utiliser un LM317 (1.5A) ou un LD1085 (3A). Dans le cas où le LM317 est choisi, les condensateurs C1 (100nF) et C4 (1µF) sont nécessaires, sinon le LD1085 devra être accompagné de C9 et C10 (10µF).
Le brochage des deux régulateurs est identique.

Le LM317 a une tension de drop-out de 3V. La tension d'entrée sera de préférence supérieure à 7.5V.
Le LD1085 a une tension de drop-out de 1.3V. La tension d'entrée pourra être inférieure : 6V suffiront.
Le dissipateur est un ML97/1.5 de 4.3°C/W. Il devrait suffire pour dissiper une douzaine de watts.
Dans le cas du LD1085, la tension d'entrée ne devra pas dépasser 7V, car si l'alimentation est réglée sur 3V et débite 3A la puissance sera élevée :

P = (7V - 3V) * 3A = 12W

Dans le cas du LM317 la tension maximale sera de 11V :

P = (11V - 3V) * 1.5A = 12W

Bien entendu si le courant débité est faible, on pourra utiliser une tension d'entrée supérieure :
  • LD1085 : maximum 30V
  • sinon : maximum 35V (limite du LM78L05)
Un petit afficheur OLED I2C 128x32 permet d'afficher la tension de sortie.

La carte ARDUINO NANO et le DAC peuvent être alimentés soit par un cordon USB soit par le régulateur U6 LM78L05.

Le DAC utilisé est un MCP4725 12 bits.

Un encodeur rotatif permet de faire varier la tension manuellement par pas de 50mV.

Enfin, la liaison USB de l'ARDUINO peut être utilisée pour piloter l'alimentation :
  • sélection de la tension de sortie
  • lecture de la tension de sortie
  • lecture d'une entrée analogique
  • sélection du mode (entrée ou sortie) des entrées / sorties digitales
  • lecture d'une entrée digitale
  • écriture d'une entrée digitale
Les 5 entrées analogiques sont atténuées par les résistances R6 à R15 (ponts diviseurs 10KΩ + 2KΩ). La tension d'entrée ne devra pas excéder 15V.

Une référence de tension 2.5V TL431 est utilisée. La référence 5V serait trop dépendante de la tension USB ou de celle du régulateur LM78L05.
Quant à la référence interne 1.1V et sa précision de 10%, je l'ai écartée.
Si l'on a pas l'intention d'utiliser un TL431, on peut malgré tout utiliser la référence 5V ou 1.1V, mais il faudra adapter le code et les ponts diviseurs.

3. Le matériel

Les composants suivants sont utilisés :
  • 1 carte ARDUINO NANO
  • 1 module MCP4725
  • 1 TL431 en boîtier TO92
  • 1 afficheur OLED I2C SSD1306 128x32
  • 1 encodeur rotatif  du type ALPS EC11E
  • 1 LM78L05
  • régulation :
    • un LM317
    • un condensateur polyester de 100nF
    • un condensateur MLCC de 1µF
  • ou
    • un LD1085
    • deux condensateurs de 10µF 10V ou 16V
  • 1 résistance de 240Ω 1%
  • 1 résistance de 270Ω 1%
  • 7 résistances de 10KΩ 1%
  • 5 résistances de 2KΩ 1%
  • 1 résistance de 1KΩ
  • 4 condensateurs polyester de 100nF
  • 1 condensateur polyester de 470nF
  • 2 connecteurs 2 broches au pas de 2.54 NS25 ou KF2510
  • un condensateur de 10µF 10V ou 16V
  • 1 connecteur DUPONT femelle 6 broches au pas de 2.54
  • 1 connecteur DUPONT femelle 10 broches au pas de 2.54
  • 1 dissipateur TO220 du type ML97/1.5 (L42xl25xH38)
L'encodeur est un modèle made in china très courant : AliExpress

On peut également utiliser des connecteurs DUPONT 2 broches en lieu et place des connecteurs NS25. Attention au sens de branchement, car le détrompeur des NS25 sera absent.

4. La réalisation

Comme il s'agit d'une réalisation sans trop de complexité, en exemplaire unique, j'ai réalisé la carte à l'aide d'une plaquette à pastilles 120mm x 80mm (voir photo plus bas).
Dans le dossier kicad un routage est disponible dans le cas où un PCB est souhaité.
Le routage est également utile si l'on utilise une plaquette à pastilles, pour réaliser le câblage à partir d'une image à l'écran, ou d'une impression.

5. IDE ARDUINO

Il faudra installer les bibliothèques ARDUINO suivantes :
Librairie SSD1306 : https://github.com/greiman/SSD1306Ascii.git
Librairie MCP4725 : https://github.com/adafruit/Adafruit_MCP4725.git 

Dans l'IDE, dans le menu "Outils/Type de Carte" choisir "Arduino Nano". Dans le menu "Outils/Processeur" choisir "ATmega328p" ou "ATmega328p (old bootloader)".

6. Le code

Pour récupérer le projet voir plus bas : 11. Téléchargements.

L'encodeur est géré à l'aide d'un code source personnel, inspiré de ce celui-ci :

https://www.instructables.com/Improved-Arduino-Rotary-Encoder-Reading/ 

Je n'ai fait que le transformer en classe C++.

Je n'ai pas réussi à faire fonctionner l'encodeur made in china avec les librairies Encoder ou Rotary. Un click générait plusieurs incrémentations / décrémentations.

7. Utilisation

7.1. Réglages

Il faut avant tout mesurer la tension de référence sur la broche AREF de la NANO, et reporter la valeur de VREF dans le code (ligne 32).

Ensuite il faut régler les tensions basse et haute :
  • tourner l'encodeur jusqu'à ce qu'il affiche 3.00V
  • appuyer sur le bouton
  • l'afficheur affiche la tension réelle
  • ajuster la valeur OUTPUT_MIN (ligne 15). Un point vaut environ 1.2mV.
  • recommencer jusqu'à obtenir une tension réelle de 3.00V

  • tourner l'encodeur jusqu'à ce qu'il affiche 4.20V
  • appuyer sur le bouton
  • l'afficheur affiche la tension réelle
  • ajuster la valeur OUTPUT_MAX (ligne 16)
  • recommencer jusqu'à obtenir une tension réelle de 4.20V
Bien entendu, si l'on modifie les valeurs de VREF, OUTPUT_MIN ou OUTPUT_MAX, il faut recompiler et recharger de code pour essayer les nouvelles valeurs.
Normalement si l'on utilise des résistances à 1% les valeurs devraient être très proches de celles que j'ai utilisé.

7.2. Réglage manuel

Il suffit de tourner l'encodeur jusqu'à ce qu'il affiche la tension voulue et d'appuyer sur le bouton. L'afficheur affiche ensuite la tension réelle mesurée.

Au démarrage la tension de sortie vaut 3.7V.

7.3. Pilotage par le PC

Le commandes sont entrées à l'aide d'un terminal 115200 baud (le moniteur série ARDUINO par exemple) :
  • VOUT=XX.XX : permet de modifier la tension de sortie (XX.XX = 3V à 4.2V)
  • READ N : permet de lire une entrée analogique (N = 1 à 6). L'entrée N°1 est la sortie de l'alimentation
  • IN N : permet de basculer une GPIO en entrée (N = 1 à 9)
  • OUT N : permet de basculer une GPIO en sortie (N = 1 à 9)
  • GET N : permet de lire une GPIO (N = 1 à 9)
  • SET N : permet de basculer une GPIO à un niveau UN (N = 1 à 9)
  • RESET N : permet de basculer une GPIO à un niveau ZERO (N = 1 à 9)

8. Photos

Voici quelques images de la carte :


De haut en bas et de gauche à droite :
  • les connecteurs d'entrée et de sortie
  • le LM317 et son dissipateur
  • l'ARDUINO NANO
  • le LM78L05
  • le connecteur des GPIOS
  • le connecteur des entrées analogiques
  • le module MCP4725
  • le TL431
  • l'afficheur OLED
  • l'encodeur
la carte est surélevée à l'aide de colonnettes M2.5.

Remarque :
Sur la plaquette à pastilles il est facile de placer l'encodeur à gauche pour les gauchers.

Vue côté connecteurs ANALOG et DIGITAL
Vue côté entrée et sortie

Vue de dessous
Il est facile d'intégrer la carte dans un boîtier en plaçant l'afficheur et l'encodeur en façade et en les reliant à l'aide de quelques fils à la carte.
Avec deux bornes + et - en façade elle ressemblera à une vraie alimentation.

Personnellement j'envisage plutôt une utilisation sur table, avec la carte telle quelle.

10. Essais

Le réglage de la tension est assez précis, de l'ordre +/- 10mV.

Les entrées analogiques 2 à 6 sont moins précises, du fait des ponts diviseurs employés : 10KΩ + 2KΩ au lieu de 10KΩ + 10KΩ pour l'entrée 1, mais la mesure reste tout de même dans une fourchette de +/- 50mV.

On pourrait faire mieux en adoptant des ponts diviseurs 10KΩ + 10KΩ sur les entrées analogiques (résistances R6 à R15), mais cela limiterait la tension à 5V en entrée.
Il suffit ensuite de modifier la constante ANALOG_DIVIDER dans le code (0.5 au lieu de 0.165).

Mais pour mon utilisation je tiens à conserver la possibilité de mesurer des tensions de 12V ou un peu plus.

Passons à la partie communication série entre le PC et l'alimentation.
Voici un script PYTHON permettant de tester la carte :

import unittest
import time
import serial

class Test(unittest.TestCase):

    def sendReply(self, request):
        global ser
        ser.write(request+'\r\n')
        answer = ser.read_until('\n')
        print answer,
        return answer.strip('\r\n')

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_power(self):
        print 'setting voltage to 3V'
        answer = self.sendReply('VOUT=3')
        voltage = float(answer)
        self.assertTrue(voltage > 2.97 and voltage < 3.03)
        print 'setting voltage to 3.7V'
        answer = self.sendReply('VOUT=3.7')
        voltage = float(answer)
        self.assertTrue(voltage > 3.67 and voltage < 3.73)
        print 'setting voltage to 4.2V'
        answer = self.sendReply('VOUT=4.2')
        voltage = float(answer)
        self.assertTrue(voltage > 4.17 and voltage < 4.23)

    def test_GPIO(self):
        print 'setting GPIO9 to OUTPUT'
        answer = self.sendReply('OUT 9')
        self.assertEqual(answer, 'OK')
        print 'setting GPIO9 to 1'
        answer = self.sendReply('SET 9')
        self.assertEqual(answer, 'OK')
        print 'getting GPIO9'
        answer = self.sendReply('GET 9')
        self.assertEqual(answer, '1')
        print 'setting GPIO9 to 0'
        answer = self.sendReply('RESET 9')
        self.assertEqual(answer, 'OK')
        print 'getting GPIO9'
        answer = self.sendReply('GET 9')
        self.assertEqual(answer, '0')

    def test_ANALOG(self):
        print 'setting voltage to 3.7V'
        answer = self.sendReply('VOUT=3.7')
        voltage = float(answer)
        self.assertTrue(voltage > 3.67 and voltage < 3.73)
        print 'reading ANALOG1'
        answer = self.sendReply('READ 1')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)
        print 'reading ANALOG2'
        answer = self.sendReply('READ 2')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)
        print 'reading ANALOG3'
        answer = self.sendReply('READ 4')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)
        print 'reading ANALOG4'
        answer = self.sendReply('READ 5')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)
        print 'reading ANALOG5'
        answer = self.sendReply('READ 5')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)
        print 'reading ANALOG6'
        answer = self.sendReply('READ 6')
        voltage = float(answer)
        self.assertTrue(voltage > 3.6 and voltage < 3.8)

if __name__ == "__main__":
    global ser
    ser = serial.Serial('/dev/ttyUSB1', baudrate=115200)
    ser.timeout = 3
    time.sleep(1)
    ser.read_until('\n') # read boot message
    unittest.main()


Les modules unittest et pyserial sont nécessaires.

'/dev/ttyUSB1' peut être remplacé par 'COMX' sur une machine Windows.

Pour le test les entrées analogique 2 à 6 sont reliées à la sortie de l'alimentation.

Le résultat :

riton@alpha:/mnt/sdc1/riton/projects/3.7v-power-supply/test$ python test.py
setting voltage to 3.7V
3.70
reading ANALOG1
3.69
reading ANALOG2
3.64
reading ANALOG3
3.67
reading ANALOG4
3.67
reading ANALOG5
3.67
reading ANALOG
3.71
.setting GPIO9 to OUTPUT
OK
setting GPIO9 to 1
OK
getting GPIO9
1
setting GPIO9 to 0
OK
getting GPIO9
0
.setting voltage to 3V
3.01
setting voltage to 3.7V
3.69
setting voltage to 4.2V
4.21
.
----------------------------------------------------------------------
Ran 3 tests in 2.130s

OK
riton@alpha:/mnt/sdc1/riton/projects/3.7v-power-supply/test$


PYTHON est un langage extraordinaire si l'on veut bien se donner la peine d'une petite formation.

11. Téléchargements

Pour télécharger le projet :
https://bitbucket.org/henri_bachetti/3.7v-power-supply.git

Cette page vous donne toutes les informations nécessaires :
https://riton-duino.blogspot.com/p/migration-sous-bitbucket.html

12. Conclusion

Voilà un petit outil qui va me permettre d'éliminer pas mal de risques liés à l'utilisation d'une alimentation de laboratoire non limitée, et de réaliser des tests poussés sur mes montages alimentés par batterie.


Cordialement
Henri

10 commentaires:

  1. Bonjour Henri, merci pour votre blog et vos articles !
    Cette question n'a pas de rapport direct avec ce montage, mais j'aurai voulu savoir quelle section de fil (ou AWG) vous utilisez pour connecter les composants entre eux SOUS votre plaque à trou. Merci et bonnes fêtes de fin d'année !

    RépondreSupprimer
    Réponses
    1. C'est du fil à wrapper 30AWG.
      https://fr.aliexpress.com/item/32902141717.html?spm=a2g0s.9042311.0.0.27426c37vGwW1O
      Les fils de puissance (nus) sont rigides : 0.3mm2

      Bonnes fêtes également !

      Supprimer
    2. Merci pour votre réponse ! Au plaisir de vous lire !

      Supprimer
  2. Bsr Henri,article tres instructif,je cherche par moi meme a
    faire une alim reglable de ce style mais jusqu'a 30v,et le
    potar numerique aurait un probleme,si tu as une solution...
    Mon alim serait symetrique et j'ai en plus un veritable
    casse tete pour afficher les valeurs positives et negatives
    a l'aide d'un ads1115 monté en differentiel,c'est tres lent
    et ca affiche une difference de 1v sur 2secondes.
    Bonne année a ton blog!
    p.s:tu t'appelles vraiment Duino?

    RépondreSupprimer
    Réponses
    1. Un LM317 supporte jusqu'à 37V, par contre il faudrait amplifier la sortie du MCP4725 afin d'élever la tension de référence (multiplier par 6 ou 7). Certains AOP supportent jusqu'à +/- 18V.
      Une alimentation symétrique peut être fabriquée avec deux alimentations simples, le + de la deuxième étant reliée au - de la première, comme celle-ci :
      https://riton-duino.blogspot.com/2018/02/une-alimentation-symetrique-6-18v.html
      Je ne suis pas très satisfait non plus de l'ADS1115 en différentiel. Mais si tu construis deux alimentations positives, tu peux utiliser deux ADS1115 en mode simple mesure.
      Duino : non, Bachetti

      Supprimer
    2. Un NTE975 par exemple peut être alimenté en +/- 20V.
      Il pourrait être inséré (montage multiplicateur) entre le MCP4725 et le LM317.
      Il devra être alimenté par la tension d'entrée du LM317.
      Avec une tension d'entrée de 35V cela pourrait coller.
      Par contre la dissipation sera très importante si la tension de sortie du LM317 est faible.
      Le LM78L05 supporte au maxi 35V en entrée. Il faudrait insérer un LM7824 (40V) en amont.

      Supprimer
  3. Merci d'avoir pris le temps de repôndre,c'est un probleme
    ardu,je n'ai pas vu de solutions sur le net,ou peut etre jalousement gardées.Je vais essayer avec ton DAC et un
    multiplicateur de tension.

    Il y a aussi la solution avec une resistance commandée en
    tension,j'avais testé avec un coupleur opto,mais la plage
    de reglage n'etait pas suffisante.
    Et avec les mosfets?ca marche?
    Je n'aime pas le LM78L05 et ses copains,ils chauffent trop
    pour ce qu'ils font;le LM317 est plutot discret a ce niveau la.
    Effectivement,2 LM317 en dephasage feraient l'affaire,mais
    n'y a t'il pas de danger avec une reference entre les deux?

    RépondreSupprimer
    Réponses
    1. Avec un MOSFET pour amplifier ? Cela m'étonnerait que ce soit très linéaire.
      Le 78L05 ne chauffe pas plus que les autres. La dissipation est directement liée à la différence de tension entrée / sortie et au courant : P = (Vin - Vout) * I
      De plus un LM7805 est moins bruyant qu'un LM317 ou LD1085.
      A propos de bruit je suppose qu'une alimentation symétrique devra alimenter des AOP, audio peut-être ? Si c'est le cas il faudra choisir des composants peu bruyants. Par exemple le LT3081 est assez exceptionnel (voir le lien précédent).
      Mettre plusieurs régulateurs en parallèle : en général une résistance de faible valeur est placée en série avec la sortie (voir les datasheets).

      Supprimer
  4. Pour le MOSFET,ce serait l'utiliser dans sa region que l'on dit
    ohmique,j'ai vu ca plusieurs fois comme application,souvent on
    les utilisent comme "potars" commandés en tension,mais je crois
    que ca se produit en commandant la gate en valeur negative de
    tension,faut bien regarder la doc.
    Pour moi,un 78L05 chauffe meme sans charge,alors qu'un LM317
    ne monte en temp qu'avec un courant dissipé par la charge.

    RépondreSupprimer
    Réponses
    1. Un MOSFET canal N avec la source au GND se commande en tension positive. Le problème est d'établir la relation entre tension grille et valeur de résistance Drain/source, et vérifier la linéarité. A essayer.

      Un 78L05 consomme 3mA. Avec une tension d'entrée de 20V cela donne 60mW. C'est largement supportable.
      Le LM317 supporte 1.5A, le 78L05 100mA. Difficilement comparable. Les applications sont de toutes façons différentes.
      Le 78L05 peut se comparer à un HT7550-1, qui lui ne dissipera que 50µW dans les mêmes conditions.

      https://riton-duino.blogspot.com/2018/11/les-regulateurs-ldo.html

      Supprimer