Remplacement du réglage analogique par numérique dans l'alimentation du laboratoire HY3005D

     L'article discutera du remplacement des potentiomètres standard par des codeurs mécaniques EC11 (capteurs d'angle d'accumulation) dans une unité d'alimentation Mastech HY3005D utilisant un microcontrôleur PIC16F1829 et un registre à décalage 74HC595 implémentant un DAC sur une matrice de résistances R2R

Préface


     Il y a quelques années, j'ai acheté une alimentation Mastech HY3005D. Il n'y a pas si longtemps, il y avait des problèmes de régulation de la tension - le revêtement en graphite des rhéostats était usé et le réglage de la tension requise est devenu une tâche difficile. Il n'y avait pas de rhéostats appropriés et j'ai décidé de ne pas en acheter de semblables, mais de changer la méthode de réglage.
     Le niveau de tension et de courant de sortie est défini par la tension de référence fournie aux amplificateurs opérationnels. Ainsi, vous pouvez vous débarrasser complètement des potentiomètres en les remplaçant par un DAC capable de délivrer une tension dans la plage souhaitée.
     Dans le catalogue des micropuces, je n'ai pas pu trouver un microcontrôleur approprié qui a deux DAC à bord, et les DAC externes n'ont pas un petit prix et trop de fonctionnalités supplémentaires. J'ai donc acquis les registres à décalage 74HC595 et les résistances pour la matrice R2R. Le microcontrôleur PIC16F1829 était déjà en stock.
     Afin de pouvoir revenir au circuit d'origine, tous les changements sont minimisés - en remplaçant l'unité de réglage effectuée sur une carte séparée.

Description du poste


     Le circuit est basé sur le microcontrôleur PIC16F1829 fonctionnant à une fréquence de 32 MHz. La fréquence d'horloge est réglée par le générateur d'horloge intégré, selon la fiche technique, elle n'est pas trop précise, mais pour ce circuit, elle n'est pas critique. L'avantage de ce MK est la présence de résistances de rappel sur toutes les entrées numériques et de deux modules MSSP qui implémentent SPI. Les 18 broches logiques du microcontrôleur sont utilisées.
     Sur quatre registres à décalage 74HC595et les matrices R2R ont implémenté deux DAC 16 bits. Les avantages de ce registre incluent la présence d'un registre à décalage et d'un registre de stockage séparés. Cela vous permet d'écrire des données dans le registre sans casser les valeurs de sortie actuelles. La matrice R2R est montée sur des résistances avec une erreur de 1%. Il convient de noter que les mesures sélectives ont montré une erreur ne dépassant pas 10 ohms. Initialement, il était prévu d'utiliser 3 registres, mais lors du câblage de la carte, cela ne me semblait pas une bonne solution, en plus, il fallait ajouter des grignotages.
     Les résistances de rappel intégrées au MC sont activées à toutes les entrées et simplifient le circuit. Toutes les sorties des encodeurs sont connectées directement aux bornes MK, un total de 4 encodeurs ont chacun deux sorties pour le capteur de rotation lui-même et une pour le bouton intégré. Un total de 12 conclusions MK est utilisé pour traiter les données d'entrée. Le rebond de contact est lissé avec une capacité de 100nF. Après avoir modifié les valeurs des tampons de courant et de tension à 16 bits conformément aux données d'entrée des codeurs, les valeurs sont transférées vers les registres à décalage 74HC595 via SPI. Pour réduire le temps de transfert des données, deux modules SPI sont utilisés, ce qui permet aux données d'être transmises simultanément pour le courant et la tension. Une fois les données transférées dans le registre, une commande est envoyée pour transférer les données du tampon de décalage vers le tampon de stockage. Les sorties du registre sont connectées à la matrice R2R faisant office de diviseur pour le DAC.La tension de sortie de la matrice est transmise aux entrées des amplificateurs opérationnels.
     Les boutons intégrés aux encodeurs définissent respectivement le minimum (bouton de l'encodeur pour un réglage en douceur) ou le maximum (bouton de l'encodeur pour un réglage grossier) pour le courant ou la tension.

Schéma


     Sur Internet, je n'ai pas trouvé de schéma qui coïncide complètement avec le mien, j'ai donc pris le premier lien. Correction des incohérences révélées, puis ajout des modifications. J'ai dessiné un schéma du bloc de réglage dans TinyCAD - téléchargez le fichier HY3005D-regulator.dsn .

L'original


Après avoir trouvé des inexactitudes


Le schéma final après raffinement L'

unité portable avec réglage (surlignée en rouge) a été placée dans un schéma séparé.

Un voltmètre numérique avec un affichage sur le panneau avant (il ne figure pas sur les schémas) est connecté au connecteur J3.

Composants utilisés


     Voici une liste des composants utilisés (le cas est indiqué entre parenthèses). Tous ont été achetés à différents moments en Chine. Il est important d'utiliser des LED ayant les mêmes caractéristiques que les LED natives, comme ils se tiennent en série dans le circuit de sortie des amplificateurs opérationnels (j'ai pris les mêmes que ceux qui se trouvaient sur ma carte mère).
  • U1: microcontrôleur PIC16F1829I / ML (QFN)
  • U2 - U5: registre à décalage 74HC595BQ (DHVQFN16 ou SOT-763)
  • U6: Régulateur de tension linéaire AMS1117 5V (SOT-223)
  • RE1 - RE4: capteur d'angle d'accumulation mécanique EC11
  • Matrices R1, R2 et R2R: résistances 1 et 2 kΩ (SMD 0402)
  • C1 - C12, C14-C17: Condensateurs céramiques GRM21BR71E104KA01L 100nF (SMD 0805)
  • C13: condensateur au tantale 22mkF 16V (tiv B)
  • D1, D2: LED tension / courant du panneau avant


Frais


     J'ai élevé la carte dans Sprint Layout 6 - téléchargez le fichier HY3005D-regulator.lay6 . Malheureusement, l'original sur lequel j'ai réalisé ma version n'a pas été conservé, au format lay6 déjà avec des corrections identifiées lors du montage:

  1. J'ai ajouté des cavaliers à côté de l'interface du micrologiciel à la connexion d'interruption de l'encodeur de contrôle de courant lisse, car capacités filtrage rebond de contact empêché de faire clignoter le contrôleur
  2. Ajout de cavaliers manquants pour le sol entre les côtés
  3. Déplacement de l'assemblage de stabilisation 5 V de l'autre côté pour réduire les cavaliers
  4. Ajout de condensateurs de lissage sur la ligne électrique ( discussion )

Photo après gravure et perçage (première version)



     Fabriqué en utilisant une pellicule photosensible. J'ai souffert longtemps avec un petit câblage de registres. Dans cette dernière version, il y avait de petits défauts qui devaient être nettoyés après la gravure. Mais en général, le conseil a échoué. Il n'y a toujours pas assez de deux cavaliers pour relier le sol à l'avant et à l'arrière.

Après avoir saisi les problèmes identifiés (deuxième version)


0 SMD 0805.

Photo après dessoudage et installation en place


      . — . — 12.

     Comme vous pouvez le voir, les changements sont minimes, tous les anciens connecteurs sont restés inchangés. J'ai dû ajouter de la nourriture séparément, car la seule tension provenant de la carte de réglage 2,5 V ne convient pas au diviseur natif. Si vous retirez la diode Zener à 2,5 V (V5A) sur la carte principale du bloc d'alimentation et placez un cavalier à la place de la résistance (R1A), vous pouvez vous passer de l'alimentation supplémentaire de 12 V.

Firmware


Code C pour le compilateur XC8. Cousu le PICkit original 3.

config.h
// PIC16F1829 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)


main.c
#include "config.h"

#define _XTAL_FREQ 32000000
#pragma intrinsic(_delay)
extern void _delay(unsigned long);
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#define TransferNotDone          !(SSP2STAT&0b00000001)

#define StoreAll                 LATA4
#define ResetAll                 LATC6

#define VoltageSharpCHA          RC1
#define VoltageSharpCHB          RC0
#define VoltageSharpBTN          RA2

#define VoltageSmoothCHA         RB5
#define VoltageSmoothCHB         RB4
#define VoltageSmoothBTN         RC2

#define CurrentSharpCHA          RC5
#define CurrentSharpCHB          RC4
#define CurrentSharpBTN          RC3

#define CurrentSmoothCHA         RA1
#define CurrentSmoothCHB         RA0
#define CurrentSmoothBTN         RA3

#define VoltageRateSharp         0x0100
#define VoltageRateSmooth        0x0010
#define CurrentRateSharp         0x0040
#define CurrentRateSmooth        0x0004

#define VoltageMax               0xC000
#define CurrentMax               0x5000
#define VoltageMin               0x0000
#define CurrentMin               0x0000

#define VoltageStart             0x1E00
#define CurrentStart             CurrentMax

unsigned short VoltageBuff;
unsigned short CurrentBuff;

void interrupt tc_int() {
};

void SendData() {
    SSP1BUF = VoltageBuff>>8;
    SSP2BUF = CurrentBuff>>8;
    while ( TransferNotDone );
    SSP1BUF = VoltageBuff;
    SSP2BUF = CurrentBuff;
    while ( TransferNotDone );
    StoreAll = 1;
    StoreAll = 0;
};

void main() {
    // Configure oscillator for 32MHz
    //             76543210
    OSCCON     = 0b11110000; //B1

    // Enable individual pull-ups
    //             76543210
    OPTION_REG = 0b01111111; //B1

    // Configure analog port (1 - enable, 0 - disable)
    //             76543210
    ANSELA     = 0b00000000; //B3
    ANSELB     = 0b00000000; //B3
    ANSELC     = 0b00000000; //B3

    // Reset latch
    //             76543210
    LATA       = 0b00000000; //B2
    LATB       = 0b00000000; //B2
    LATC       = 0b00000000; //B2

    // Alternate pin function (set SDO2 on RA5)
    //             76543210
    APFCON0    = 0b00000000; //B2
    APFCON1    = 0b00100000; //B2

    // Configure digital port (1 - input, 0 - output)
    //             76543210
    TRISA      = 0b00001111; //B1
    TRISB      = 0b00110000; //B1
    TRISC      = 0b00111111; //B1

    // Configure input level (1 - CMOS, 0 - TTL)
    INLVLA     = 0b11000000; //B7
    INLVLB     = 0b00001111; //B7
    INLVLC     = 0b00000000; //B7

    // Configure individual pull-ups (1 - enable, 0 - disable)
    //             76543210
    WPUA       = 0b00111111; //B4
    WPUB       = 0b11110000; //B4
    WPUC       = 0b11111111; //B4

    ResetAll = 0;
    ResetAll = 1;

    // Configure SPI in master mode
    //             76543210
  //SSP1ADD    = 0b00000000; //B4
    SSP1STAT   = 0b01000000; //B4
    SSP1CON3   = 0b00000000; //B4
    SSP1CON1   = 0b00100000; //B4
  //SSP1ADD    = 0b00000000; //B4
    SSP2STAT   = 0b01000000; //B4
    SSP2CON3   = 0b00000000; //B4
    SSP2CON1   = 0b00100000; //B4

    VoltageBuff = VoltageStart;
    CurrentBuff = CurrentStart;
    __delay_ms(50);
    SendData();

    while ( 1 ) {
        if ( !VoltageSharpCHA ) {
            if ( VoltageSharpCHB ) { VoltageBuff-=VoltageRateSharp; if ( VoltageBuff > VoltageMax ) VoltageBuff = VoltageMin; }
                              else { VoltageBuff+=VoltageRateSharp; if ( VoltageBuff > VoltageMax ) VoltageBuff = VoltageMax; }
            while ( !VoltageSharpCHA );
            SendData();
        }

        if ( !VoltageSmoothCHA ) {
            if ( VoltageSmoothCHB ) { VoltageBuff-=VoltageRateSmooth; if ( VoltageBuff > VoltageMax ) VoltageBuff = VoltageMin; }
                               else { VoltageBuff+=VoltageRateSmooth; if ( VoltageBuff > VoltageMax ) VoltageBuff = VoltageMax; }
            while ( !VoltageSmoothCHA ); 
            SendData();
        }

        if ( !CurrentSharpCHA ) {
            if ( CurrentSharpCHB ) { CurrentBuff-=CurrentRateSharp; if ( CurrentBuff > CurrentMax ) CurrentBuff = CurrentMin; }
                              else { CurrentBuff+=CurrentRateSharp; if ( CurrentBuff > CurrentMax ) CurrentBuff = CurrentMax; }
            while ( !CurrentSharpCHA );
            SendData();
        }

        if ( !CurrentSmoothCHA ) {
            if ( CurrentSmoothCHB ) { CurrentBuff-=CurrentRateSmooth; if ( CurrentBuff > CurrentMax ) CurrentBuff = CurrentMin; }
                               else { CurrentBuff+=CurrentRateSmooth; if ( CurrentBuff > CurrentMax ) CurrentBuff = CurrentMax; }
            while ( !CurrentSmoothCHA );
            SendData();
        }

        if ( !VoltageSharpBTN  ) { VoltageBuff = VoltageMax; while ( !VoltageSharpBTN  ); SendData(); }
        if ( !VoltageSmoothBTN ) { VoltageBuff = VoltageMin; while ( !VoltageSmoothBTN ); SendData(); }
        if ( !CurrentSharpBTN  ) { CurrentBuff = CurrentMax; while ( !CurrentSharpBTN  ); SendData(); }
        if ( !CurrentSmoothBTN ) { CurrentBuff = CurrentMin; while ( !CurrentSmoothBTN ); SendData(); }
    };
}


     Pour les valeurs minimales, VoltageMin et CurrentMin sont définis sur 1, car à 0 dans le tampon, l'ajustement cesse de fonctionner jusqu'à ce que je comprenne où est le problème. Tarifs * Tarif * sélectionné multiple et le plus pratique à mon avis. Pour la méthode SendData, je n'ai pas passé de variables en tant que paramètres pour enregistrer les instructions de la machine et la mémoire. Le mode LVP (Low Voltage Firmware) doit être désactivé, sinon RA3 ne fonctionnera pas comme entrée numérique. Les interruptions ne sont pas utilisées, la méthode tc_int est présente dans le code afin que le compilateur place le bloc principal au début de la ROM.
     Pour le firmware, il suffit de retirer les cavaliers, de connecter le PICkit 3 (ou un autre programmeur) et de réaliser le firmware. Dans la première version, il n'y avait pas de cavaliers sur le CLK et le DAT, j'ai donc dû dessouder les condensateurs de lissage, les flasher puis les souder.
UPD:Après avoir installé des capacités supplémentaires sur la ligne électrique, le problème de sortie du compteur de la position zéro a disparu. J'ai également dû changer le sens de rotation. Apparemment, le bruit du redresseur AMS1117 a empêché la reconnaissance correcte de l'état des codeurs. De plus, j'ai ajouté un réglage des valeurs de départ, maintenant la tension par défaut est réglée à 5 volts (le courant est toujours au maximum). Avant le premier envoi de données, un retard de 50 ms a été inséré dans les registres (la valeur du retard a été prise avec une grande marge) pour attendre l'initialisation des modules SPI.

Caractéristiques de la tension de sortie


     Après l'assemblage final de l'appareil, une mesure de tension a été effectuée entre les contacts J4.1 - J4.2 (régulation de tension) et J4.1 - J4.7 (régulation de courant). Selon les données obtenues, des graphiques sont construits (ci-dessous sous le spoiler) des dépendances valeur / tension pour le DAC.
Graphiques



Les valeurs calculées des tensions sont obtenues par la formule (U * D) / (2 ^ K), où
U est la tension à la sortie du registre, en tenant compte des diviseurs du circuit principal (pour les DAC de courant - 4950mV, pour les DAC de tension - 3550mV);
D est la valeur décimale du compteur DAC;
K - Profondeur de bits DAC (16 bits)

Ce qui peut être amélioré


  • ajouter des valeurs de minuterie enregistrement
  • lier les valeurs standard aux boutons du codeur, par exemple, pour la tension: 3,3; 5,0; 7,5; 12V
  • pour se protéger contre une valeur inconnue au démarrage, il est préférable de connecter MR à 1, de tirer l'OE à travers la résistance à 1 et de le réinitialiser à 0 après avoir initialisé le MK.
  • remplacer le DAC par un PWM avec une chaîne de lissage ( LampTester suggéré ici )

Source: https://habr.com/ru/post/fr391617/


All Articles