Digital Adjustable Power Supply
This project was developed using an Arduino Nano, providing precise output voltage control from 0 to 25V, with adjustment in both volts and millivolts through a rotary encoder.
This project was developed using an Arduino Nano, providing precise output voltage control from 0 to 25V, with adjustment in both volts and millivolts through a rotary encoder.
Project Features
- Adjustable output voltage from 0 to 25V
- Fine adjustment in volts and millivolts
- I2C LCD display for real-time information
- Rotary encoder control
- Temperature monitoring using an NTC sensor
- Automatic cooling fan control for transistor temperature management
- Short-circuit protection using transistor switching at the LM358 input
- Audible buzzer alarm for warnings and protection
- Real-time voltage and current monitoring
Tests Performed
A continuous test was conducted for approximately 30 minutes using an automotive lamp as the load, drawing about 1.7A. During the test, the system operated reliably and maintained stable voltage regulation while continuously monitoring the temperature of the power components.Applications
Ideal for electronics workbenches, equipment maintenance, circuit testing, and electronic project development.
B4R:
Sub Process_Globals
Serial Público1 Como Serial
Serial Público1 Como Serial
Timer_ADC Público Como Temporizador
Controle Público do Temporizador Como Temporizador
' -------- PINOS --------
Volt_Leitura público como Pin A0 (pino 14) - tensão
Ampe_Leitura público como pino A1 (pino 15) - corrente ACS712 30A
Public Pwm1 As Pin ' D11 - saída PWM
Buzzer Público Como Pin ' D8
Public Modo As Pin ' D9 - botão confirmar
Pwm_Mais público como Pin ' A2 (pino 16) - ajuste fino +1
Pwm_Menos público como Pin ' A3 (pino 17) - ajuste fino -1
Public EncoderPinA Como Pin ' D12
Codificador Público PinB Como Pin ' D10
Public Ventilador Como Pin ' D4
Protetor Público Como Pin ' D3
' -------- VALORES MEDIDOS --------
BatVolt Público Como Carro Alegórico
Amper Público Como Carro Alegórico
PWM_Value Pública Como Int
' -------- CALIBRAÇÃO CORRENTE --------
OffsetAmp Público Como Flutuador
Public OffsetAmpCalibrado As Boolean = False
Público ÚltimoEstadoTempo Enquanto Tempo
Público ÚltimoMaisTempo Enquanto Tempo
Público ÚltimoMenos Tempo Enquanto Tempo
' -------- LCD --------
LCD público como LiquidCrystal_I2C
Pub bc Como ByteConverter
' ----- Leitura ntc -----
R_NTC Pública Como Carro Alegórico
Comunidade Pública de Direitos Aglomerados
InvT Público Como Carro Alegórico
TempK público como carro alegórico
TempC Público Como Carro Alegórico
Public Vref As Double = 4.8 ' Referência de tensão do ADC (3.3V se for NodeMCU/Wemos)
VentLigado Público como Booleano
Ntc_Leitura Pública Como Pin
Beta pública Como Flutuador
Leitura pública As Int
Tensão pública Como carro alegórico
R0 Público Como Carro Alegórico
T0 Público Como Carro Alegórico
O Modo_Volte Público Como Int
Fim de Substituição
Sub-Início de Apps Privado
Serial1.Inicialize(115200)
Log("AppStart")
Modo.Inicialize(9, Modo.MODE_INPUT_PULLUP)'D9
Buzzer.Inicialize(8, Buzzer.MODE_OUTPUT) 'D8
pwm1.Inicialize(11, Pwm1.MODE_OUTPUT) 'D11
Pwm1.AnalogWrite(0)
Volt_Leitura.Initialize(14, Volt_Leitura.MODE_INPUT) ' A0
Ampe_Leitura.Initialize(15, Ampe_Leitura.MODE_INPUT) ' A1
Ntc_Leitura.Initialize(21, Ntc_Leitura.MODE_INPUT) ' D7
Pwm_Mais.Initialize(16, Pwm_Mais.MODE_INPUT_PULLUP) ' A2
Pwm_Menos.Initialize(17, Pwm_Menos.MODE_INPUT_PULLUP) ' A3
EncoderPinA.Initialize(12, EncoderPinA.MODE_INPUT_PULLUP)' D12
EncoderPinB.Initialize(10, EncoderPinB.MODE_INPUT_PULLUP)' D10
EncoderPinA.AddListener("EncoderPinA_Changed")
Prot.Initialize(3, Prot.MODE_OUTPUT) ' D3
Prot.DigitalWrite(Falso)
Ventilador.Inicialize(4, Ventilador.MODE_OUTPUT) ' D4
Ventilador.DigitalWrite(False)
Timer_ADC. Inicializar("Read_ADC", 500)
Timer_ADC. Ativado = Verdadeiro
TimerControle.Initialize("Controle", 200)
TimerControle.Enabled = True
lcd.Inicialize(0x27, 16, 2)
lcd.Backlight = True
LCD. Limpo
lcd.SetCursor(0, 0)
LCD.Write ("FONTE DE BANCADA")
lcd.SetCursor(0, 1)
lcd.Write(" Iniciando... ")
Atraso (1500)
LCD. Limpo
Fim de Substituição
' =============================================================
' ENCODER
' =============================================================
Sub EncoderPinA_Changed (Declara como booleano)
Dim t As Long = Millis
Se t - LastStateTime < 150 Então Retorne
ÚltimoEstadoTempo = t
Se EncoderPinB.DigitalRead então
Modo_Volte = Modo_Volte + 1
Bipe2
Else
Bipe2
Modo_Volte = Modo_Volte - 1
Fim Se
Selecione Modo_Volte
Caso 1
PWM_Value = 15
Caso 2
PWM_Value = 24
Caso 3
PWM_Value = 34
Caso 4
PWM_Value = 44
Caso 5
PWM_Value = 53
Caso 6
PWM_Value = 62
Caso 7
PWM_Value = 72
Caso 8
PWM_Value = 81
Caso 9
PWM_Value = 90
Caso 10
PWM_Value = 99
Caso 11
PWM_Value = 109
Caso 12
PWM_Value = 118
Caso 13
PWM_Value = 128
Caso 14
PWM_Value = 137
Caso 15
PWM_Value = 146
Caso 16
PWM_Value = 156
Caso 17
PWM_Value = 167
Fim Seleção
Se Modo_Volte > 17 Então Modo_Volte = 1
Se Modo_Volte < 1 Então Modo_Volte = 17
Fim de Substituição
' =============================================================
' LEITURA ADC (temporizador 500ms)
' =============================================================
Sub Read_ADC
'-------------Leitura da Voltagem 0 25v ---------------
' --- TENSÃO — R1=22k, R2=2k2, fator=10,57 ---
Dim rawBat As UInt = Volt_Leitura.AnalogRead
Dim vA0 As Float = rawBat * (5.0 / 1023.0)
BatVolt = vA0 * 10,50
'-------------Leitura da Amperagem ate 5 Amper ---------
' --- CORRENTE — ACS712 30A (66mV/A) ---
Se OffsetAmpCalibrado = False então
Dim SomaOffset como flutuante = 0
Para i = 1 a 100
SomaOffset = SomaOffset + Ampe_Leitura.AnalogRead
Próximo
OffsetAmp = (SomaOffset / 100) * (5.0 / 1023.0)
OffsetAmpCalibrado = True
Amper = 0
Retorno
Fim Se
Dim Soma Como Flutuante = 0
Para i = 1 a 20
Soma = Soma + Ampe_Leitura.AnalogRead
Próximo
Dim rawAmp As Float = Soma / 20
Dim vAmp As Float = rawAmp * (5.0 / 1023.0)
Amper = Abs((vAmp - OffsetAmp) / 0,066)
Se Amper < 0,10, então Amper = 0
'-------------Leitura do ntc---------------
' ----- Parâmetros -----
beta = 3950 ' Constante Beta do NTC (ajuste fino depois)
R0 = 10000' Fixo do resistor (10k)
T0 = 298,15 ' 25 °C em Kelvin
Vref = 3.3 ' ATENÇÃO: use 1.0 se seu A0 for de módulo "puro" (TOUT = 1.0V máx)
' ----- Leitura -----
leitura = Ntc_Leitura.AnalogRead ' 0..1023
tensão = leitura * Vref / 1023.0
' ----- Resistência do NTC (resistor sem GND, NTC no +V) -----
' Fórmula correta para este esquema:
' R_NTC = R0 * (Vref - tensao) / tensao
Se tensao <= 0 então tensao = 0,001' evita divisão por zero
Se tensao >= Vref, então tensao = Vref - 0,001
R_NTC = R0 * (Vref - tensão) / tensão
' ----- Temperatura (Lei Beta) -----
lnR = Logaritmo(R_NTC / R0, 2,718281828)
invT = (1 / T0) + (1 / beta) * lnR
tempK = 1 / invT
tempC = tempK - 273,15
' ----- Calibração opcional -----
' correção = 4,8
' tempC = tempC + correção
' ----- Controle do ventilador -----
Se tempC > 40 E VentLigado = False Então
Ventilador.DigitalWrite(True)
VentLigado = Verdadeiro
Caso contrário, se a temperatura C < 35 e VentLigado = verdadeiro, então
Ventilador.DigitalWrite(False)
VentLigado = False
Fim Se
Dim grau() como byte = array como byte(223)
Log("Temperatura: ", NumberFormat(tempC, 1, 2), " °C")
' Linha 0: atualiza tensão
lcd.SetCursor(0, 0)
lcd.Write(NumberFormat(tempC, 2, 1))
LCD.Write (Grau)
lcd.Write("C")
Texto escuro Como Corda
Se Amper < 1 então
texto = NumberFormat(Amper * 1000, 1, 0)
Else
texto = NumberFormat(Amper, 1, 2)
Fim Se
Dim textoBytes() As Byte = texto. GetBytes
Dim Pos As Int = bc. IndexOf(textoBytes, ".". GetBytes)
Se Pos <> -1 então
textoBytes(Pos) = ",". GetBytes(0)
Fim Se
lcd.SetCursor(11, 1)
LCD. Escrever(a.C. StringFromBytes(textoBytes))
Se Amper < 1 então
lcd.Write("mA")
Else
lcd.Write("A")
Fim Se
' Linha 0: atualiza tensão
lcd.SetCursor(10, 0)
LCD.Write(">")
lcd.SetCursor(10, 1)
LCD.Write(">")
Texto dim As String = NumberFormat(BatVolt, 2, 1)
Dim textoBytes() As Byte = texto. GetBytes
Dim Pos As Int = bc. IndexOf(textoBytes, ".". GetBytes)
Se Pos <> -1 então
textoBytes(Pos) = ",". GetBytes(0)
Fim Se
lcd.SetCursor(11, 0)
LCD. Escrever(a.C. StringFromBytes(textoBytes))
lcd.Write("V")
Fim de Substituição
' =============================================================
' CONTROLE (temporizador 200ms)
' =============================================================
Sub Controle
' --- Botão ajuste fino + ---
Se Pwm_Mais.DigitalRead = False então
Se Millis - LastMaisTime > 200, então
LastMaisTime = Millis
PWM_Value = PWM_Value + 1
Bipe2
Se PWM_Value > 255 Então PWM_Value = 255
Fim Se
Fim Se
' --- Botão ajuste fino - ---
Se Pwm_Menos.DigitalRead = False então
Se Millis - LastMenosTime > 200, então
LastMenosTime = Millis
PWM_Value = PWM_Value - 1
Bipe2
Se PWM_Value < 0 Então PWM_Value = 0
Fim Se
Fim Se
Pwm1.AnalogWrite(PWM_Value)
Log("VALOR PWM: ", PWM_Value)
Fim de Substituição
Sub Bipe2
Buzzer.DigitalWrite(True)
Atraso(20)
Buzzer.DigitalWrite(False)
Fim Sub