206 lines
4.5 KiB
C
206 lines
4.5 KiB
C
/*
|
|
* b_cccv_algo.c
|
|
*
|
|
* Created on: 16.06.2023
|
|
* Author: max
|
|
*/
|
|
|
|
#include "b_cccv_algo.h"
|
|
#include "charger_control.h"
|
|
#include "main.h"
|
|
|
|
static uint32_t dt;
|
|
static uint32_t lasttick;
|
|
static float errorintegration = 0;
|
|
static float finalvoltage = 4.15;
|
|
static float chargevoltage = 430;
|
|
static float chargecurrentlimit = CHARGE_CURRENT_LIMIT;
|
|
|
|
static float resistancelut[1024];
|
|
static float voltageresistancelut[1024];
|
|
|
|
#define CURRENT_R 2.2
|
|
#define VOLTAGE_R 18
|
|
|
|
CCCV_CONTROL_STATE chargerstate = NO_CHARGING;
|
|
|
|
#ifdef SIMULINKTEST
|
|
CCCV_CONTROL_STATE cccvloop(float maxcellvoltage, float voltagesetpoint, float maxcurrent, float*ccurrent)
|
|
#else
|
|
CCCV_CONTROL_STATE cccvloop(float maxcellvoltage, float voltagesetpoint, float maxcurrent)
|
|
#endif
|
|
|
|
{
|
|
#ifdef SIMULINKTEST
|
|
dt = 1000;
|
|
#else
|
|
dt = HAL_GetTick() - lasttick;
|
|
lasttick = HAL_GetTick();
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
float chargecurrent = 0;
|
|
|
|
//Calculate Voltage Error and I and P Factors
|
|
float voltageerror = voltagesetpoint-maxcellvoltage;
|
|
|
|
float errorproportional = P_GAIN * voltageerror;
|
|
errorintegration += I_GAIN*voltageerror * ((float)dt)/1000;
|
|
|
|
|
|
//Limit I and P Factors to maximum charge current
|
|
|
|
if(errorintegration > maxcurrent)
|
|
errorintegration = maxcurrent;
|
|
|
|
if(errorproportional > maxcurrent)
|
|
errorproportional = maxcurrent;
|
|
|
|
if(errorproportional <= -maxcurrent)
|
|
errorproportional = -maxcurrent;
|
|
|
|
if(errorintegration <= -maxcurrent)
|
|
errorintegration = -maxcurrent;
|
|
|
|
float errorintegrationout = errorintegration;
|
|
chargecurrent = (errorproportional + errorintegrationout);
|
|
|
|
if(chargecurrent > maxcurrent)
|
|
chargecurrent = maxcurrent;
|
|
|
|
if(chargecurrent <= 0)
|
|
chargecurrent = 0;
|
|
|
|
if(chargecurrent < 0.01) //If Charge Current ist below minimum threshold, stop charging
|
|
return CHARGING_COMPLETED;
|
|
#ifdef SIMULINKTEST
|
|
*ccurrent = chargecurrent;
|
|
#else
|
|
setchargevoltage(103,finalvoltage+0.05);
|
|
setchargecurrent(chargecurrent);
|
|
#endif
|
|
|
|
|
|
return CHARGING_IN_PROGRESS;
|
|
}
|
|
|
|
#ifndef SIMULINKTEST
|
|
|
|
void initChargerAlgo(uint8_t numberofcells, float maximumcellvoltage)
|
|
{
|
|
chargerstate = NO_CHARGING;
|
|
chargevoltage = numberofcells * maximumcellvoltage;
|
|
|
|
for(uint32_t i = 0; i < 1024; i++)
|
|
{
|
|
resistancelut[i] = 10*CURRENT_R/(CURRENT_R+(20*((float)i)/1024));
|
|
}
|
|
|
|
for(uint32_t i = 0; i < 1024; i++)
|
|
{
|
|
voltageresistancelut[i] = (600*VOLTAGE_R)/(VOLTAGE_R+(20*((float)i)/1024));
|
|
}
|
|
}
|
|
|
|
void setchargecurrent(float chargecurrent)
|
|
{
|
|
float targetresistance;
|
|
if(chargecurrent != 0)
|
|
{
|
|
for(uint32_t setpoint = 0; setpoint < 1024; setpoint++)
|
|
{
|
|
if(resistancelut[setpoint] <= chargecurrent)
|
|
{
|
|
targetresistance = (20000*((float)setpoint)/1024);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
targetresistance = 20000;
|
|
}
|
|
|
|
float wiperpos = targetresistance/20000 * (1023);
|
|
charger_control_set_current((uint32_t) wiperpos);
|
|
}
|
|
|
|
void setchargevoltage(uint8_t numberofcells,float maximumcellvoltage)
|
|
{
|
|
|
|
float chargevoltage = numberofcells * maximumcellvoltage;
|
|
float targetresistance;
|
|
|
|
if(chargevoltage != 0)
|
|
{
|
|
for(uint32_t setpoint = 0; setpoint < 1024; setpoint++)
|
|
{
|
|
if(voltageresistancelut[setpoint] <= chargevoltage)
|
|
{
|
|
targetresistance = (20000*((float)setpoint)/1024);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
targetresistance = 20000;
|
|
}
|
|
|
|
float wiperpos = targetresistance/20000 * (1023);
|
|
charger_control_set_voltage((uint32_t) wiperpos);
|
|
//@TODO Call Function to set Resistance for Voltage
|
|
}
|
|
|
|
void chargingloop(float maximumcellvoltage)
|
|
{
|
|
switch(chargerstate)
|
|
{
|
|
case NO_CHARGING: //Do Nothing IDLE Loop
|
|
chargerstate = NO_CHARGING;
|
|
charger_control_disable_remote();
|
|
errorintegration = 0;
|
|
break;
|
|
case CHARGING_IN_PROGRESS: //Run charging algo periodically
|
|
charger_control_enable_remote();
|
|
chargerstate = cccvloop(maximumcellvoltage, finalvoltage, chargecurrentlimit);
|
|
break;
|
|
case CHARGING_COMPLETED: //Signal Completion of Charging here
|
|
chargerstate = NO_CHARGING;
|
|
charger_control_disable_remote();
|
|
errorintegration = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void startcharging(float endvoltage)
|
|
{
|
|
chargerstate = CHARGING_IN_PROGRESS;
|
|
finalvoltage = endvoltage;
|
|
}
|
|
|
|
void stopcharging()
|
|
{
|
|
chargerstate = NO_CHARGING;
|
|
charger_control_disable_remote();
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef SIMULINKTEST
|
|
|
|
float matlabvalidationwrapper(float maxcellvoltage, float voltagesetpoint, float maxcurrent)
|
|
{
|
|
float chargecurrent = 0;
|
|
(void*) cccvloop(maxcellvoltage,voltagesetpoint,maxcurrent, &chargecurrent);
|
|
return chargecurrent;
|
|
|
|
}
|
|
|
|
#endif
|
|
|