Sustitución del ajuste analógico por digital en la fuente de alimentación del laboratorio HY3005D

     El artículo discutirá el reemplazo de potenciómetros estándar con codificadores mecánicos EC11 (sensores de ángulo de acumulación) en una unidad de fuente de alimentación Mastech HY3005D usando un microcontrolador PIC16F1829 y un registro de desplazamiento 74HC595 que implementa un DAC en una matriz de resistencia R2R

Prólogo


     Hace unos años, compré una fuente de alimentación Mastech HY3005D. No hace mucho tiempo había problemas con la regulación de voltaje: el revestimiento de grafito de los reóstatos estaba desgastado y establecer el voltaje requerido se convirtió en una tarea difícil. No había reóstatos adecuados, y decidí no comprar otros similares, sino cambiar el método de ajuste.
     El nivel de voltaje y corriente de salida se establece mediante el voltaje de referencia suministrado a los amplificadores operacionales. Por lo tanto, puede deshacerse por completo de los potenciómetros reemplazándolos con un DAC capaz de entregar voltaje en el rango deseado.
     En el catálogo de microchip, no pude encontrar un microcontrolador adecuado que tenga dos DAC a bordo, y los DAC externos no tienen un precio pequeño y demasiada funcionalidad adicional. Por lo tanto, adquirí los registros de desplazamiento 74HC595 y las resistencias para la matriz R2R. El microcontrolador PIC16F1829 ya estaba en stock.
     Para poder volver al circuito original, se minimizan todos los cambios, reemplazando la unidad de ajuste realizada en una placa separada.

Descripción del puesto


     El circuito se basa en el microcontrolador PIC16F1829 que funciona a una frecuencia de 32 MHz. La frecuencia del reloj la establece el generador de reloj incorporado, de acuerdo con la hoja de datos no es demasiado precisa, pero para este circuito no es crítica. La ventaja de este MK es la presencia de resistencias pull-up en todas las entradas digitales y dos módulos MSSP que implementan SPI. Se utilizan los 18 pines lógicos del microcontrolador.
     En cuatro registros de desplazamiento 74HC595y las matrices R2R implementaron dos DAC de 16 bits. Las ventajas de este registro incluyen la presencia de un registro de desplazamiento y un registro de almacenamiento separados. Esto le permite escribir datos en el registro sin romper los valores de salida actuales. La matriz R2R se ensambla en resistencias con un error del 1%. Vale la pena señalar que las mediciones selectivas mostraron un error de no más de 10 ohmios. Inicialmente, se planeó usar 3 registros, pero al conectar el tablero no me pareció una buena solución, además, era necesario agregar mordiscos.
     Las resistencias pull-up integradas en el MC se activan en todas las entradas y simplifican el circuito. Todas las salidas de los codificadores están conectadas directamente a los terminales MK, un total de 4 codificadores tienen dos salidas cada una para el sensor de rotación y una para el botón incorporado. Un total de 12 conclusiones MK se utiliza para procesar datos de entrada. El rebote de contacto se suaviza con una capacidad de 100nF. Después de cambiar los valores de las memorias intermedias de voltaje y corriente de 16 bits de acuerdo con los datos de entrada de los codificadores, los valores se transfieren a los registros de desplazamiento 74HC595 a través de SPI. Para reducir el tiempo de transferencia de datos, se utilizan dos módulos SPI, lo que permite que los datos se transmitan simultáneamente para corriente y voltaje. Después de que los datos se transfieren al registro, se envía un comando para transferir datos desde el búfer de cambio al búfer de almacenamiento. Las salidas del registro están conectadas a la matriz R2R que actúa como un divisor para el DAC.El voltaje de salida de la matriz se transmite a las entradas de los amplificadores operacionales.
     Los botones integrados en los codificadores establecen el mínimo (botón del codificador para un ajuste suave) o el máximo (botón del codificador para el ajuste aproximado), respectivamente, para corriente o voltaje.

Esquema


     En Internet, no encontré un esquema que coincidiera completamente con el mío, así que tomé el primer enlace. Se realizaron correcciones en las inconsistencias reveladas y luego se agregaron los cambios. Dibujé un diagrama del bloque de ajuste en TinyCAD: descargue el archivo HY3005D-regulator.dsn .

El original


Después de encontrar imprecisiones


El esquema final después del refinamiento La

unidad portátil con ajuste (resaltada en rojo) se colocó en un esquema separado.

Se conecta un voltímetro digital con una pantalla en el panel frontal (no está en los diagramas) al conector J3.

Componentes utilizados


     A continuación se muestra una lista de los componentes utilizados (el caso se indica entre paréntesis). Todos fueron comprados en diferentes momentos en China. Es importante utilizar LED con las mismas características que los nativos, como se colocan en serie en el circuito de salida de los amplificadores operacionales (tomé los mismos que estaban en mi placa base).
  • U1: PIC16F1829I / ML microcontrolador (QFN)
  • U2 - U5: registro de desplazamiento 74HC595BQ (DHVQFN16 o SOT-763)
  • U6: regulador de voltaje lineal AMS1117 5V (SOT-223)
  • RE1 - RE4: sensor de ángulo de acumulación mecánico EC11
  • Matrices R1, R2 y R2R: resistencias de 1 y 2 kΩ (SMD 0402)
  • C1 - C12, C14-C17: Condensadores de cerámica GRM21BR71E104KA01L 100nF (SMD 0805)
  • C13: condensador de tantalio 22mkF 16V (tiv B)
  • D1, D2: LED de voltaje / corriente del panel frontal


Tarifa


     Creé la placa en Sprint Layout 6: descargue el archivo HY3005D-regulator.lay6 . Desafortunadamente, el original en el que hice mi versión no se conservó, ya en formato lay6 con correcciones identificadas durante el ensamblaje:

  1. Agregué puentes al lado de la interfaz de firmware a la conexión de interrupción del codificador de control de corriente suave, porque las capacidades de filtrado de rebote de contacto impidieron el parpadeo del controlador
  2. Se agregaron puentes faltantes para el suelo entre los lados
  3. Se movió el conjunto estabilizador de 5 V al otro lado para reducir a través de puentes
  4. Condensadores de suavizado agregados en la línea de alimentación ( discusión )

Foto después del grabado y la perforación (primera versión)



     Hecho con película fotorresistente. Sufrí durante mucho tiempo con un pequeño cableado de registros. En la última versión, hubo pequeños defectos que tuvieron que limpiarse después del grabado. Pero en general, la junta falló. Todavía no hay suficientes dos puentes para conectar el suelo en los lados frontal y posterior.

Después de ingresar los problemas identificados (segunda versión)


0 SMD 0805.

Foto después de soldar e instalar en su lugar


      . — . — 12.

     Como puede ver, los cambios son mínimos, todos los conectores antiguos permanecieron sin cambios. Tuve que agregar comida por separado, porque El único voltaje que llega a la placa de ajuste de 2.5V no es adecuado para el divisor nativo. Si quita el diodo zener a 2.5V (V5A) en la placa principal de la unidad de fuente de alimentación y coloca un puente en el lugar de la resistencia (R1A), puede prescindir de una fuente de alimentación adicional de 12V.

Firmware


Código C para el compilador XC8. Cosido el 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(); }
    };
}


     Para los valores mínimos, VoltageMin y CurrentMin se establecen en 1, porque a 0 en el búfer, el ajuste deja de funcionar hasta que entiendo dónde está el problema. Tarifas * Tarifa * seleccionado múltiple y más conveniente en mi opinión. Para el método SendData, no pasé variables como parámetros para guardar las instrucciones de la máquina y la memoria. El modo Firmware de bajo voltaje (LVP) debe estar apagado; de lo contrario, RA3 no funcionará como entrada digital. Las interrupciones no se usan, el método tc_int está presente en el código para que el compilador coloque el bloque principal al comienzo de la ROM.
     Para el firmware, es suficiente eliminar los puentes, conectar el PICkit 3 (u otro programador) y ejecutar el firmware. En la primera versión no había puentes en el CLK y DAT, así que tuve que soldar los condensadores de suavizado, flashearlos y luego soldarlos.
UPD:Después de instalar capacidades adicionales en la línea de alimentación, desapareció el problema de salir del contador desde la posición cero. También tuve que cambiar la dirección de rotación. Aparentemente, el ruido del rectificador AMS1117 impidió el reconocimiento correcto del estado de los codificadores. Además, agregué una configuración de valores iniciales, ahora el voltaje predeterminado está configurado en 5 voltios (la corriente todavía está al máximo). Antes del primer envío de datos, se insertó un retraso de 50 ms en los registros (el valor del retraso se tomó con un gran margen) para esperar a que se inicialicen los módulos SPI.

Características de voltaje de salida


     Después del ensamblaje final del dispositivo, se realizó una medición de voltaje entre los contactos J4.1 - J4.2 (regulación de voltaje) y J4.1 - J4.7 (regulación de corriente). De acuerdo con los datos obtenidos, se trazan gráficos (debajo del spoiler) de las dependencias de valor / voltaje para el DAC.
Gráficos



Los valores calculados de los voltajes se obtienen mediante la fórmula (U * D) / (2 ^ K), donde
U es el voltaje en la salida del registro, teniendo en cuenta los divisores en el circuito principal (para la corriente DAC - 4950mV, para el voltaje DAC - 3550mV);
D es el valor decimal del contador DAC;
K - Profundidad de bits DAC (16 bits)

¿Qué se puede mejorar?


  • agregar valores de temporizador de ahorro
  • ate los valores estándar a los botones del codificador, por ejemplo, para voltaje: 3.3; 5.0; 7.5; 12V
  • Para protegerse contra un valor desconocido en el inicio, es mejor conectar MR a 1 y tirar del OE a través de la resistencia a 1 y restablecer a 0 después de inicializar el MK.
  • reemplace el DAC con un PWM con una cadena de suavizado ( aquí se sugiere LampTester )

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


All Articles