Hello everyone, how are you?
I want to share with you my newest 12V lead-acid battery charger with three functions: Fast Charge, Slow Charge, Floating Charge, and Stand-by.
Here is the code.
Best regards to all, see you later
I want to share with you my newest 12V lead-acid battery charger with three functions: Fast Charge, Slow Charge, Floating Charge, and Stand-by.
Here is the code.
Best regards to all, see you later
B4R:
Sub Process_Globals
Public Serial1 As Serial
Public I2C_Erro As Byte
Public Voltagem, Corrente, Shunt, Vdd, LoadVoltage As Float
Public Pwm1 As Pin
Public BtnUp As Pin
Public BtnDown As Pin
Public Pwm1 As Pin
Public Led_Standby As Pin
Public Led_Carregamento_Rapido As Pin
Public Led_Crregamendo_Lento As Pin
Public Led_Frutua As Pin
Public Buzze As Pin
' Controle
Public PWM_Value As Int = 0
Public Timer1 As Timer
Public Overflow As Boolean
Public MODO As Byte
Dim Limite_Voltage_BulkHigh As Float = 14.2
Dim Limite_Voltage_FloatLow As Float = 13.8
Dim PWM_Rapido As Int = 175 ' ajuste para carga rápida
Dim PWM_Lento As Int = 157 ' ajuste para flutuação (~13.6-13.8V)
Public Pisca As Boolean
Private Stop As Timer
End Sub
Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")
'Led de endicação
Led_Carregamento_Rapido.Initialize(5,Led_Carregamento_Rapido.MODE_OUTPUT)
Led_Crregamendo_Lento.Initialize(10,Led_Crregamendo_Lento.MODE_OUTPUT)
Led_Standby.Initialize(12,Led_Standby.MODE_OUTPUT)
Led_Frutua.Initialize(13,Led_Frutua.MODE_OUTPUT)
Buzze.Initialize(9,Buzze.MODE_OUTPUT)
' Botões
BtnUp.Initialize(14, BtnUp.MODE_INPUT_PULLUP)
BtnUp.AddListener("PWM_MA")
BtnDown.Initialize(15, BtnDown.MODE_INPUT_PULLUP)
BtnDown.AddListener("PWM_ME")
' Saída PWM
Pwm1.Initialize(11,Pwm1.MODE_OUTPUT)
' Configura PWM inicial
Pwm1.AnalogWrite(PWM_Value)
Timer1.Initialize("Controle", 500)
Timer1.Enabled = True
Stop.Initialize("Buzzer",100)
Stop.Enabled = True
MODO = 0
RunNative("Init", Null)
End Sub
Sub Buzzer
Buzze.DigitalWrite(True)
Delay(200)
Buzze.DigitalWrite(False)
Stop.Enabled = False ' Desativa o timer após 3 apitos
End Sub
Sub PWM_MA(State As Boolean)
If State = False And BtnDown.DigitalRead = True Then
MODO = (MODO + 1) Mod 4 ' roda de 0 até 4 e volta para 0
Stop.Enabled = True ' Desativa o timer após 3 apitos
End If
End Sub
Sub PWM_ME(State As Boolean)
If BtnDown.DigitalRead = False Then
PWM_Value = PWM_Value + 1
End If
End Sub
Sub Controle
RunNative("Read", Null) ' atualiza Voltagem, Corrente etc. preenchidos na parte C
If I2C_Erro <> 0 Then
Log("Erro I2C: ", I2C_Erro)
Timer1.Enabled = False
Return
End If
Select MODO
Case 0 '
Log("⏹️ Estado: Standby")
Pwm1.AnalogWrite(PWM_Value) ' Força 0 no Standby
Led_Carregamento_Rapido.DigitalWrite(False)
Led_Crregamendo_Lento.DigitalWrite(False)
Led_Standby.DigitalWrite(True)
Led_Frutua.DigitalWrite(False)
Case 1
Log("⚡ Carga Rabida")
Pwm1.AnalogWrite(PWM_Rapido)
Pisca = Not(Pisca)
Led_Carregamento_Rapido.DigitalWrite(Pisca)
Led_Crregamendo_Lento.DigitalWrite(False)
Led_Standby.DigitalWrite(False)
Led_Frutua.DigitalWrite(False)
If Corrente > 15 Then
If Voltagem >= Limite_Voltage_BulkHigh Then
Log("⚡ Atingiu 14.2V - Limitando Corrente")
PWM_Value = PWM_Rapido
End If
Else
Log("⚠️ Nenhuma bateria conectada")
End If
Case 2
Log("️⚡ Carga Lenta")
Pwm1.AnalogWrite(PWM_Lento)
Pisca = Not(Pisca)
Led_Crregamendo_Lento.DigitalWrite(Pisca)
Led_Carregamento_Rapido.DigitalWrite(False)
Led_Standby.DigitalWrite(False)
Led_Frutua.DigitalWrite(False)
If Corrente > 15 Then
If Voltagem >= Limite_Voltage_BulkHigh Then
Log("🔄 Atingiu 14.2V - Limitando Corrente")
PWM_Value = PWM_Lento
End If
Else
Log("⚠️ Nenhuma bateria conectada")
End If
Case 3
Log("⏹️ Carga Lenta + Flutuação")
Pwm1.AnalogWrite(PWM_Lento)
Pisca = Not(Pisca)
Led_Carregamento_Rapido.DigitalWrite(False)
Led_Crregamendo_Lento.DigitalWrite(False)
Led_Standby.DigitalWrite(False)
Led_Frutua.DigitalWrite(Pisca)
If Corrente > 15 Then
If Voltagem <= Limite_Voltage_FloatLow Then
Log("⬇️ Bateria Caiu Abaixo de 12.5V - voltando para Carga Rápida")
MODO = 1
End If
Else
Log("⚠️ Nenhuma bateria conectada")
End If
End Select
Log("| Vbat = ", NumberFormat(Voltagem,1,1), " V | I = ", NumberFormat(Corrente,1,0), " mA = | A = ",NumberFormat(Corrente/1000.0,1,2)," | PWM = ",NumberFormat(PWM_Value,1,1))
If Overflow Then
Log("⚠️ Overflow detectado!")
Else
Log("✓ Leitura OK")
End If
End Sub
#If C
#include <Wire.h>
#include <INA226_WE.h>
INA226_WE ina226 = INA226_WE(0x40);
void Init(B4R::Object* o) {
Wire.begin(); // SDA = D2 (GPIO4), SCL = D1 (GPIO5)
// Wire.begin(18, 19); // SDA = D2 (GPIO4), SCL = D1 (GPIO5)
bool status = ina226.init();
if (!status) {
b4r_main::_i2c_erro = 99; // erro de inicialização
return;
}
ina226.setAverage(AVERAGE_64);
ina226.setConversionTime(CONV_TIME_1100, CONV_TIME_1100);
// Calibração para resistor shunt R01F = 0.01 Ω
//ina226.setResistorRange(0.1, 2.0);
ina226.setResistorRange(0.01, 10.0);
ina226.waitUntilConversionCompleted(); // evitar leitura zero na 1ª medição
b4r_main::_i2c_erro = 0;
}
void Read(B4R::Object* o) {
byte errorCode = ina226.getI2cErrorCode();
b4r_main::_i2c_erro = errorCode;
if (errorCode != 0) return;
float bus = ina226.getBusVoltage_V();
float shunt_mV = ina226.getShuntVoltage_mV();
//float current_mA = ina226.getCurrent_mA();
float current_mA = ina226.getCurrent_mA() * 0.897; // fator de calibração ajustado
float power_mW = ina226.getBusPower();
b4r_main::_voltagem = bus;
b4r_main::_shunt = shunt_mV;
b4r_main::_corrente = current_mA;
b4r_main::_vdd = power_mW;
b4r_main::_loadvoltage = bus + (shunt_mV / 1000.0);
b4r_main::_overflow = ina226.overflow;
}
#End If