📜 ⬆️ ⬇️

Replacement of analog adjustment with digital one in laboratory power supply HY3005D

The article will discuss the replacement of standard potentiometers with EC11 mechanical encoders (accumulating angle sensors) in the Mastech HY3005D power supply using a PIC16F1829 microcontroller and a 74HC595 shift register with a real-time DAC on a R2R resistor matrix

Foreword


A few years ago, I purchased the Mastech HY3005D power supply. Not so long ago, there were problems with voltage regulation - the graphite coating of the rheostats was worn out and setting the required voltage became a difficult task. There were no suitable rheostats, and I decided not to buy similar ones, but to change the method of adjustment.
The level of output voltage and current is set by the reference voltage supplied to the operational amplifiers. Thus, you can completely get rid of the potentiometers by replacing them with a DAC capable of delivering a voltage in the desired range.
In the microchip catalog, I could not find a suitable microcontroller with two DACs on board, and the external DACs have not a small price tag and too much extra functionality. Therefore, acquired the shift registers 74HC595 and resistors for the matrix R2R. The PIC16F1829 microcontroller was already in stock.
To be able to return to the original scheme, all changes are minimized - replacing the adjustment unit performed on a separate board.

Description of work


The scheme is based on the PIC16F1829 microcontroller operating at 32 MHz. The clock frequency is set by the built-in clock generator, according to the data sheet it is not too accurate, but for this scheme it is not critical. The advantage of this MC is the presence of pull-up resistors on all digital inputs and two MSSP modules implementing SPI. All 18 logical outputs of the microcontroller are used.
On four shift registers 74HC595 and R2R matrices, two 16-bit DACs are implemented. The advantages of this register include the presence of a separate shift register and storage register. This allows you to write data to the register without disturbing the current output values. The R2R matrix is ​​assembled on resistors with an accuracy of 1%. It is worth noting that sample measurements showed an error of no more than 10 ohms. It was originally planned to use 3 registers, but when setting up the board it seemed to me that this was not a good solution, besides it was necessary to add nibbles.
The pull-up resistors built into the MC are activated at all inputs and simplify the circuit. All outputs from the encoders are connected directly to the MK pins, only 4 encoders each with two pins for the rotation sensor itself and one for the integrated button. A total of 12 pins MK is used to process input data. The contact bounce is smoothed with a capacity of 100 nF. After changing the values ​​of 16-bit current and voltage buffers in accordance with the input data from the encoders, the values ​​are transferred to the 74HC595 shift registers via SPI. To reduce data transfer time, two SPI modules are used, which allows data to be transmitted simultaneously for current and voltage. After the data is transferred to the register, the command to transfer data from the shift buffer to the storage buffer is sent. Register outputs are connected to the R2R matrix acting as a divider for the DAC. The output voltage from the matrix is ​​transmitted to the inputs of the operational amplifiers.
Buttons embedded in the encoders set the values ​​to minimum (soft adjustment encoder button) or maximum (coarse adjustment encoder button), respectively, for current or voltage.

Scheme


On the Internet, I did not find a scheme that completely coincides with mine, so I took the first link. Made corrections for identified inconsistencies and then added its own changes. TinyCAD drew adjustment block scheme - download the file HY3005D-regulator.dsn .
')
Original


After the found inaccuracies


Final scheme after revision

Remote unit with adjustment (highlighted in red) made a separate scheme.

A digital voltmeter with a display on the front panel is connected to the J3 connector (it is not in the diagrams).

Used components


Below is a list of used components (the case is shown in brackets). All purchased at different times in China. It is important to use LEDs with the same characteristics as the native ones, since they stand consistently in the output circuit of operational amplifiers (I took the same ones that were on my motherboard).


Pay


Plate wired to Sprint Layout 6 - download the file HY3005D-regulator.lay6 . Unfortunately, the original, on which I made my version, was not preserved, in lay6 format already with the corrections revealed during the assembly:

  1. A jumper near the interface for flashing was added to the disconnection of the smooth current control encoder; containers that bounce contacts did not allow the controller to be flashed
  2. Added missing jumpers for ground between sides
  3. Moved the stabilizing assembly to 5V on the other side to reduce the through jumpers
  4. Added smoothing capacitors on the power line ( discussion )

Photo after etching and drilling (first version)



Made using film photoresist. For a long time I suffered with a fine register setting. In the last version there were small flaws that had to be cleaned after etching. But in general, the fee was a success. There are still not enough two jumpers to connect the earth on the front and back sides.

After entering the identified problems (second version)


Three 0 Ω resistors in the SMD 0805 package were used as jumpers.

Photo after soldering and installing in place


On the left side is the power supply itself. In the right - the front panel face down. The green wire from the upper left corner to the lower right is an additional 12V power supply.

As you can see, the changes are minimal, all the old connectors remain unchanged. I had to add a separate food, because the only voltage coming to the 2.5V adjustment board for the native divider is not suitable. If on the main board of the power supply you remove the 2.5V Zener diode (V5A) and put the jumper in place of the resistor (R1A), you can do without an additional summing up of 12V power supply.

Firmware


C code for the XC8 compiler. Stitched 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(); } }; } 


For minimum values ​​of VoltageMin and CurrentMin, 1 is set, since at 0 in the buffer, the adjustment stops working until I understand where the problem is. Rates * Rate * selected multiples and most convenient in my opinion. For the SendData method, I did not pass variables as parameters to save machine instructions and memory. The low voltage (LVP) firmware mode must be turned off, otherwise the RA3 will not work as a digital input. Interrupts are not used, the tc_int method is present in the code so that the compiler places the main unit at the beginning of the EPROM.
For the firmware, it is enough to remove the jumpers, connect the PICkit 3 (or another programmer) and execute the firmware. In the first version there were no jumpers on CLK and DAT, so I had to pull out the smoothing capacitors, flash and then solder them back.
UPD: After installing additional capacitors on the supply line, the problem with exit from the zero position of the counter disappeared. Just had to change the direction of rotation. Apparently, the noise from the AMS1117 rectifier made it difficult to correctly recognize the status of the encoders. Additionally added setting of starting values, now the default voltage is set to 5 volts (the current is still at maximum). Before the first data transfer to the registers, a delay of 50ms was inserted (the delay value was taken with a large margin) to wait for the SPI modules to initialize.

Output Voltage Characteristics


After the final assembly of the device, voltages were measured between pins J4.1 - J4.2 (voltage regulation) and J4.1 - J4.7 (current regulation). According to the data obtained, graphs (below under the spoiler) of the value / voltage dependencies for the DAC are plotted.
Charts



The calculated stress values ​​are obtained by the formula (U * D) / (2 ^ K), where
U is the voltage at the output of the register, taking into account the dividers in the main circuit (for the current DAC - 4950 mV, for the DAC voltage - 3550 mV);
D is the decimal value of the DAC counter;
K - bit width of the DAC (16 bit)

What can be improved


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


All Articles