Ersetzen der analogen Einstellung durch die digitale im Labornetzteil HY3005D

     In diesem Artikel wird der Austausch von Standardpotentiometern durch mechanische EC11-Encoder (Akkumulationswinkelsensoren) in einem Mastech HY3005D-Netzteil unter Verwendung eines PIC16F1829-Mikrocontrollers und eines Schieberegisters 74HC595 erläutert, das einen DAC auf einer R2R-Widerstandsmatrix implementiert

Vorwort


     Vor einigen Jahren habe ich ein Mastech HY3005D-Netzteil gekauft. Vor nicht allzu langer Zeit gab es Probleme mit der Spannungsregelung - die Graphitbeschichtung der Rheostate war abgenutzt und das Einstellen der erforderlichen Spannung wurde zu einer schwierigen Aufgabe. Es gab keine geeigneten Rheostate, und ich beschloss, keine ähnlichen zu kaufen, sondern die Anpassungsmethode zu ändern.
     Der Pegel der Ausgangsspannung und des Ausgangsstroms wird durch die Referenzspannung eingestellt, die den Operationsverstärkern zugeführt wird. Auf diese Weise können Sie die Potentiometer vollständig entfernen, indem Sie sie durch einen DAC ersetzen, der Spannung im gewünschten Bereich liefern kann.
     Im Mikrochip-Katalog konnte ich keinen geeigneten Mikrocontroller finden, der zwei DACs an Bord hat, und externe DACs haben keinen kleinen Preis und zu viel zusätzliche Funktionalität. Daher habe ich die Schieberegister 74HC595 und Widerstände für die R2R-Matrix erworben. Der Mikrocontroller PIC16F1829 war bereits auf Lager.
     Um zur ursprünglichen Schaltung zurückkehren zu können, werden alle Änderungen minimiert und die auf einer separaten Platine vorgenommene Einstelleinheit ersetzt.

Stellenbeschreibung


     Die Schaltung basiert auf dem Mikrocontroller PIC16F1829 , der mit einer Frequenz von 32 MHz arbeitet. Die Taktfrequenz wird vom eingebauten Taktgenerator eingestellt, laut Datenblatt ist sie nicht zu genau, aber für diese Schaltung nicht kritisch. Der Vorteil dieses MK ist das Vorhandensein von Pull-up-Widerständen an allen digitalen Eingängen und zwei MSSP-Modulen, die SPI implementieren. Alle 18 Logikpins des Mikrocontrollers werden verwendet.
     Auf vier Schieberegistern 74HC595und R2R-Matrizen implementierten zwei 16-Bit-DACs. Die Vorteile dieses Registers umfassen das Vorhandensein eines separaten Schieberegisters und Speicherregisters. Auf diese Weise können Sie Daten in das Register schreiben, ohne die aktuellen Ausgabewerte zu unterbrechen. Die R2R-Matrix wird auf Widerständen mit einem Fehler von 1% zusammengesetzt. Es ist anzumerken, dass selektive Messungen einen Fehler von nicht mehr als 10 Ohm zeigten. Ursprünglich war geplant, 3 Register zu verwenden, aber bei der Verkabelung der Platine schien es mir keine gute Lösung zu sein, außerdem war es notwendig, Knabbereien hinzuzufügen.
     Die im MC eingebauten Pull-up-Widerstände werden an allen Eingängen aktiviert und vereinfachen die Schaltung. Alle Ausgänge der Encoder sind direkt mit den MK-Klemmen verbunden. Insgesamt 4 Encoder haben jeweils zwei Ausgänge für den Rotationssensor selbst und einen für die eingebaute Taste. Insgesamt 12 Schlussfolgerungen MK werden zur Verarbeitung von Eingabedaten verwendet. Der Kontaktsprung wird mit einer Kapazität von 100 nF geglättet. Nach dem Ändern der Werte der 16-Bit-Strom- und Spannungspuffer gemäß den Eingangsdaten von den Codierern werden die Werte über SPI an die Schieberegister 74HC595 übertragen. Um die Datenübertragungszeit zu verkürzen, werden zwei SPI-Module verwendet, mit denen Daten gleichzeitig für Strom und Spannung übertragen werden können. Nachdem die Daten in das Register übertragen wurden, wird ein Befehl zum Übertragen von Daten vom Verschiebungspuffer in den Speicherpuffer gesendet. Die Ausgänge des Registers sind mit der Matrix R2R verbunden, die als Teiler für den DAC fungiert.Die Ausgangsspannung von der Matrix wird an die Eingänge der Operationsverstärker übertragen.
     Die in die Encoder eingebauten Tasten stellen das Minimum (Encodertaste für eine reibungslose Einstellung) bzw. das Maximum (Encodertaste für die Grobeinstellung) für Strom oder Spannung ein.

Schema


     Im Internet habe ich kein Schema gefunden, das vollständig mit meinem übereinstimmt, also habe ich den ersten Link genommen. Korrekturen an den aufgedeckten Inkonsistenzen vorgenommen und dann die Änderungen hinzugefügt. Ich habe ein Diagramm des Einstellblocks in TinyCAD gezeichnet - laden Sie die Datei HY3005D-regulator.dsn herunter .

Das Original


Nach gefundenen Ungenauigkeiten


Das endgültige Schema nach der Verfeinerung Die

tragbare Einheit mit Anpassung (rot hervorgehoben) wurde in ein separates Schema gestellt.

Ein digitales Voltmeter mit einer Anzeige auf der Vorderseite (nicht in den Diagrammen angegeben) wird an den J3-Anschluss angeschlossen.

Verwendete Komponenten


     Unten finden Sie eine Liste der verwendeten Komponenten (der Fall ist in Klammern angegeben). Alle wurden zu unterschiedlichen Zeiten in China gekauft. Es ist wichtig, LEDs mit den gleichen Eigenschaften wie native zu verwenden Sie stehen in Reihe im Ausgangsstromkreis von Operationsverstärkern (ich habe die gleichen genommen, die auf meinem Motherboard standen).
  • U1: PIC16F1829I / ML-Mikrocontroller (QFN)
  • U2 - U5: Schieberegister 74HC595BQ (DHVQFN16 oder SOT-763)
  • U6: AMS1117 5V linearer Spannungsregler (SOT-223)
  • RE1 - RE4: mechanischer Akkumulationswinkelsensor EC11
  • R1-, R2- und R2R-Matrizen: 1 und 2 kΩ-Widerstände (SMD 0402)
  • C1 - C12, C14-C17: Keramikkondensatoren GRM21BR71E104KA01L 100nF (SMD 0805)
  • C13: Tantalkondensator 22 mkF 16 V (tiv B)
  • D1, D2: Spannungs- / Strom-LEDs auf der Vorderseite


Gebühr


     Ich habe das Board in Sprint Layout 6 gezüchtet - laden Sie die Datei HY3005D-regulator.lay6 herunter . Leider wurde das Original, auf dem ich meine Version erstellt habe, nicht erhalten, und zwar im Lay6-Format, wobei bereits während der Montage Korrekturen festgestellt wurden:

  1. Ich habe Jumper neben der Firmware-Schnittstelle zur Interrupt-Verbindung des Encoders für die reibungslose Stromregelung hinzugefügt, weil Kapazitäten, die den Kontaktsprung filtern, verhinderten das Blinken des Controllers
  2. Fehlende Jumper für Boden zwischen den Seiten hinzugefügt
  3. Verschob die 5-V-Stabilisierungsbaugruppe auf die andere Seite, um sie durch Jumper zu reduzieren
  4. Glättungskondensatoren auf der Stromleitung hinzugefügt ( Diskussion )

Foto nach dem Ätzen und Bohren (erste Version)



     Hergestellt mit Filmfotolack. Ich habe lange unter einer kleinen Verkabelung von Registern gelitten. In der letzteren Version gab es kleine Fehler, die nach dem Ätzen gereinigt werden mussten. Aber im Allgemeinen ist das Board gescheitert. Es gibt immer noch nicht genug zwei Jumper, um den Boden auf der Vorder- und Rückseite zu verbinden.

Nach Eingabe der identifizierten Probleme (zweite Version)


0 SMD 0805.

Foto nach dem Entlöten und Einbau


      . — . — 12.

     Wie Sie sehen können, sind die Änderungen minimal, alle alten Anschlüsse blieben unverändert. Ich musste Essen separat hinzufügen, weil Die einzige Spannung, die an die 2,5-V-Einstellkarte ankommt, ist nicht für den nativen Teiler geeignet. Wenn Sie die Zenerdiode auf 2,5 V (V5A) auf der Hauptplatine des Netzteils entfernen und anstelle des Widerstands (R1A) einen Jumper einsetzen, können Sie auf eine zusätzliche Versorgung mit 12 V verzichten.

Firmware


C-Code für den XC8-Compiler. Genäht das Original PICkit 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(); }
    };
}


     Für die Mindestwerte werden VoltageMin und CurrentMin auf 1 gesetzt, weil Bei 0 im Puffer funktioniert die Anpassung nicht mehr, bis ich verstehe, wo das Problem liegt. Preise * Rate * ausgewählt mehrfach und meiner Meinung nach am bequemsten. Für die SendData-Methode habe ich keine Variablen als Parameter übergeben, um Maschinenanweisungen und Speicher zu speichern. Der LVP-Modus (Low Voltage Firmware) muss ausgeschaltet sein, sonst funktioniert RA3 nicht als digitaler Eingang. Interrupts werden nicht verwendet, die Methode tc_int ist im Code vorhanden, sodass der Compiler den Hauptblock am Anfang des ROM platziert.
     Für die Firmware reicht es aus, die Jumper zu entfernen, das PICkit 3 (oder einen anderen Programmierer) anzuschließen und die Firmware auszuführen. In der ersten Version gab es keine Jumper an CLK und DAT, daher musste ich die Glättungskondensatoren ablöten, flashen und dann zurücklöten.
UPD:Nach der Installation zusätzlicher Kapazitäten in der Stromleitung verschwand das Problem, den Zähler aus der Nullposition zu verlassen. Ich musste auch die Drehrichtung ändern. Anscheinend verhinderte das Rauschen des Gleichrichters AMS1117 die korrekte Erkennung des Zustands der Encoder. Zusätzlich habe ich eine Einstellung der Startwerte hinzugefügt, jetzt ist die Standardspannung auf 5 Volt eingestellt (der Strom ist immer noch maximal). Vor dem ersten Senden der Daten wurde eine Verzögerung von 50 ms in die Register eingefügt (der Verzögerungswert wurde mit großem Abstand angenommen), um auf die Initialisierung der SPI-Module zu warten.

Ausgangsspannungseigenschaften


     Nach der Endmontage des Gerätes wurde eine Spannungsmessung zwischen den Kontakten J4.1 - J4.2 (Spannungsregelung) und J4.1 - J4.7 (Stromregelung) durchgeführt. Entsprechend den erhaltenen Daten werden Diagramme (unten unter dem Spoiler) der Wert- / Spannungsabhängigkeiten für den DAC aufgezeichnet.
Grafiken



Die berechneten Werte der Spannungen werden durch die Formel (U * D) / (2 ^ K) erhalten, wobei
U die Spannung am Ausgang des Registers unter Berücksichtigung der Teiler im Hauptstromkreis ist (für den DAC-Strom - 4950 mV, für die DAC-Spannung - 3550 mV);
D ist der Dezimalwert des DAC-Zählers;
K - DAC-Bittiefe (16 Bit)

Was kann verbessert werden


  • Timer-Werte speichern
  • Binden Sie die Standardwerte an die Encoder-Tasten, z. B. für die Spannung: 3.3; 5,0; 7,5; 12V
  • Zum Schutz vor einem unbekannten Wert beim Start ist es besser, MR an 1 anzuschließen und die OE durch den Widerstand auf 1 zu ziehen und nach dem Initialisieren des MK auf 0 zurückzusetzen.
  • Ersetzen Sie den DAC durch ein PWM mit einer Glättungskette ( LampTester hier vorgeschlagen ).

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


All Articles