Skip to content
Snippets Groups Projects
Select Git revision
  • main
  • dev_yhe_citymodel
  • detached
  • dev_jbr_mkr_updating_pandas
  • dev_V2X_jfu
  • dev_jbr_pareto
  • dev_jgn_debug
  • dev_jou_cme
  • dev_jfu_V2X
  • dev_msc_rolinghorizon_prediction
  • dev_dph_jkr
  • dev_jou_fsa_extract_data_quarter
  • dev_yni_network
  • dev_jou_cma_arbitrage
  • dev_jbr_readme
  • dev_jou_fsa
  • dev_demand_yni
17 results

shlp.csv

Blame
  • expirament.cpp 11.69 KiB
    #include "expirament.h"
    
    #include "coincell.h"
    #include "expiramentimpl.h"
    #include "vcpps.h"
    #include "panic.h"
    #include "randomgen.h"
    #include "watchdog.h"
    
    #include <chrono>
    #include <filesystem>
    #include <sstream>
    #include <thread>
    #include <fstream>
    
    
    /* Cell distrobution:
     * 0  1  2  3   |  4  5  6
     * 7  8  9  10  |  11 12 13
     * 14 15 16 17  |  18 19 20
     */
    
    Expirament::Expirament(std::vector<std::unique_ptr<CoinCell>>* coinCellsIn, Vcpps* psuIn, float voltageIn, float currentIn,
    					   Heaters* heatersIn, Multiplexers* multiplexersIn, BioControl* biocontrolIn,
    					   const std::filesystem::path& outdirIn, const std::filesystem::path& stepfileIn):
    					   coinCells(coinCellsIn), psu(psuIn), heaters(heatersIn),
    					   multiplexers(multiplexersIn), biocontrol(biocontrolIn),
    					   voltage(voltageIn), current(currentIn), outdir(outdirIn),
    					   stepfile(stepfileIn)
    {
    }
    
    bool Expirament::preparePsu()
    {
    	Vcpps::Status status;
    	Log(Log::INFO)<<"Setting psu voltage to "<<voltage;
    	bool ret = psu->setVoltage(voltage);
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to set psu voltage";
    		return false;
    	}
    	Log(Log::INFO)<<"Setting psu current to "<<current;
    	ret = psu->setCurrent(current);
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to set psu current";
    		return false;
    	}
    	ret = psu->setEnabled(true);
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to enable psu output";
    		return false;
    	}
    
    	Log(Log::INFO)<<"Waiting for psu to stablize";
    	std::this_thread::sleep_for(std::chrono::seconds(2));
    
    	ret = psu->getStatus(status);
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to read psu state, abort";
    		psu->setEnabled(false);
    		return false;
    	}
    	else if(status.curent_limited)
    	{
    		Log(Log::ERROR)<<"Psu is overcurrent at "<<status.current<<" abort";
    		psu->setEnabled(false);
    		return false;
    	}
    
    	Log(Log::INFO)<<"PSU voltage: "<<status.voltage<<" current: "<<status.current
    		<<" is currently "<<(status.curent_limited ? "" : "not")<<" current limited";
    	return true;
    }
    
    bool Expirament::run(size_t startstep, size_t substep)
    {
    	for(globalstep = startstep; globalstep < MAX_LOOP*STEP_COUNT && !stop; ++globalstep)
    	{
    		Log(Log::INFO)<<"System starting globalstep "<<globalstep;
    		watchdog::reset();
    		bool ret = step(substep);
    		substep = 0;
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"System failed at globalstep "<<globalstep;
    			return false;
    		}
    		heaters->reconnectDevices();
    	}
    	Log(Log::WARN)<<"Run compleated";
    	return true;
    }
    
    bool Expirament::takeMesurements(bool onlyTVariing)
    {
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		if(onlyTVariing)
    		{
    			switch(i)
    			{
    				case 0 ... 10:
    					break;
    				default:
    					Log(Log::INFO)<<"Skipping EIS for cell "<<i<<" as we are only mesureing cells with varieng temperature";
    					continue;
    			}
    		}
    		std::stringstream userstrss;
    		std::stringstream filenamess;
    
    		float temp;
    		bool ret = coinCells->at(i)->getTemperature(temp);
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"Could not mesure temperature from coin cell "<<i;
    			return false;
    		}
    		float ocv;
    		ret = coinCells->at(i)->measureOcv(ocv);
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"Could not mesure ocv from coin cell "<<i;
    			return false;
    		}
    
    		userstrss<<'"'<<globalstep<<','<<i<<','<<temp<<','<<ocv<<'"';
    		filenamess<<globalstep<<'-'<<i;
    		std::filesystem::path path = createCsvPath(filenamess.str());
    
    		Log(Log::INFO)<<"Takeing GEIS mesurement for cell "<<i<<" will be saved to "<<path;
    		ret = coinCells->at(i)->measureEis(path, userstrss.str());
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"Could not mesure eis spectra from coin cell "<<i;
    			return false;
    		}
    	}
    	return true;
    }
    
    bool Expirament::heatMeasureSeq(float fraction)
    {
    	Log(Log::INFO)<<"Doing heat and mesure sequence to "<<fraction;
    	setTemperatures(fraction);
    	bool ret = heaters->allReady();
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Not all heaters moved to ready state in globalstep "<<globalstep;
    		return false;
    	}
    
    	Log(Log::INFO)<<"Waiting 2 minutes for temperature soak";
    	std::this_thread::sleep_for(std::chrono::seconds(120));
    
    	Log(Log::INFO)<<"Takeing mesurements";
    	ret = takeMesurements(fraction != 0.0f);
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Takeing mesurements failed in globalsetp "<<globalstep;
    		return false;
    	}
    	return true;
    }
    
    std::vector<double> Expirament::createStepSequence(size_t upSteps, size_t downSteps, double low, double high)
    {
    	std::vector<double> out;
    
    	double closeToLow = low+(high-low)*0.05;
    	double closeToHigh = low+(high-low)*0.95;
    
    	double last = low;
    	for(size_t i = 0; i < upSteps - 1; ++i)
    	{
    		double step = rd::rand(closeToHigh, last);
    		out.push_back(step);
    		last = step;
    	}
    
    	out.push_back(high);
    
    	last = high;
    	for(size_t i = 0; i < downSteps - 1; ++i)
    	{
    		double step = rd::rand(last, closeToLow);
    		out.push_back(step);
    		last = step;
    	}
    
    	out.push_back(low);
    
    	assert(out.size() == upSteps+downSteps);
    
    	return out;
    }
    
    bool Expirament::thermalCycle(size_t count, size_t start)
    {
    	bool ret = true;
    
    	for(size_t i = start; i < count; ++i)
    	{
    		Log(Log::INFO)<<"Cycle "<<i<<" for globalsetp "<<globalstep;
    		saveStep(i);
    		if(i == 0)
    		{
    			std::vector<double> steps = createStepSequence(2, 3, 0, 1);
    			ret = heatMeasureSeq(steps[0]);
    			if(!ret)
    				return false;
    			ret = heatMeasureSeq(steps[1]);
    			if(!ret)
    				return false;
    			ret = heatMeasureSeq(steps[2]);
    			if(!ret)
    				return false;
    			ret = heatMeasureSeq(steps[3]);
    			if(!ret)
    				return false;
    			ret = heatMeasureSeq(steps[4]);
    			if(!ret)
    				return false;
    		}
    		else
    		{
    			Log(Log::INFO)<<"Heating to 1.0";
    			setTemperatures(1);
    			ret = heaters->allReady();
    			if(!ret)
    			{
    				Log(Log::ERROR)<<"Not all heaters moved to ready state in globalstep"<<globalstep<<" subcycle "<<i;
    				return false;
    			}
    			Log(Log::INFO)<<"Heating to 0.0";
    			setTemperatures(0);
    			ret = heaters->allReady();
    			if(!ret)
    			{
    				Log(Log::ERROR)<<"Not all heaters moved to ready state in globalstep"<<globalstep<<" subcycle "<<i;
    				return false;
    			}
    		}
    	}
    	return true;
    }
    
    void Expirament::setTemperatures(float fraction)
    {
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		switch(i)
    		{
    			case 0 ... 3:
    				coinCells->at(i)->setTemperature(35+20*fraction);
    				break;
    			case 4 ... 6:
    				coinCells->at(i)->setTemperature(35+20*fraction);
    				break;
    			case 7 ... 10:
    				coinCells->at(i)->setTemperature(35+10*fraction);
    				break;
    			case 11 ... 13:
    				coinCells->at(i)->setTemperature(35);
    				break;
    			case 14 ... 17:
    				coinCells->at(i)->setTemperature(45);
    				break;
    			case 18 ... 20:
    				coinCells->at(i)->setTemperature(55);
    				break;
    			default:
    				break;
    		}
    	}
    }
    
    bool Expirament::charge(float fraction, bool all)
    {
    	float current = coinCells->size()*0.04;
    	if(current > 0.9)
    		current = 0.9;
    	Log(Log::INFO)<<"Doing charge sequence to "<<fraction<<" at "<<current<<'A';
    	watchdog::reset();
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		if(all)
    		{
    			bool ret = coinCells->at(i)->setConnected(true);
    			if(!ret)
    			{
    				Log(Log::ERROR)<<"Unable to read connect cell holder "<<i;
    				return false;
    			}
    		}
    		else
    		{
    			switch(i)
    			{
    				case 0 ... 3:
    				case 7 ... 20:
    				{
    					bool ret = coinCells->at(i)->setConnected(true);
    					if(!ret)
    					{
    						Log(Log::ERROR)<<"Unable to read connect cell holder "<<i;
    						return false;
    					}
    				}
    					break;
    				default:
    					break;
    			}
    		}
    	}
    
    	Log(Log::INFO)<<"Wating for cells to stablize";
    	std::this_thread::sleep_for(std::chrono::seconds(20));
    
    	std::string filename = "charge_for_"+std::to_string(globalstep)+".csv";
    	std::filesystem::path path = outdir/filename;
    
    	Log(Log::INFO)<<"Charge curve will be saved to "<<outdir/filename;
    	bool ret = biocontrol->charge(fraction, current, path, "charge for "+std::to_string(globalstep));
    	if(!ret)
    		Log(Log::ERROR)<<"Unable to charge";
    
    	ret &= multiplexers->disconnectAll();
    	return ret;
    }
    
    bool Expirament::chargeCellToVoltage(int id, float voltage, const std::string& prefix)
    {
    	bool ret;
    
    	std::string filename = prefix+std::to_string(id)+".csv";
    	std::filesystem::path path = outdir/filename;
    	ret = coinCells->at(id)->connectExclusive();
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to read connect cell holder "<<id;
    		coinCells->at(id)->dissconnect();
    		return false;
    	}
    	ret = biocontrol->chargeToVoltage(voltage, 0.04, path, "cell"+std::to_string(id));
    	if(!ret)
    	{
    		Log(Log::ERROR)<<"Unable to charge cell holder "<<id;
    		return false;
    	}
    	ret = coinCells->at(id)->dissconnect();
    	if(!ret)
    		Log(Log::ERROR)<<"Unable to dissconnect cell holder "<<id;
    	return ret;
    }
    
    bool Expirament::capacityMesureCycle()
    {
    	bool ret = true;
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		switch(i)
    		{
    			case 0 ... 3:
    			case 7 ... 20:
    				ret = chargeCellToVoltage(i, coinCells->at(i)->getFullVoltage(),
    				                    "single_cell_charge_"+std::to_string(getGlobalstep())+"_");
    				if(!ret)
    					return ret;
    				ret = chargeCellToVoltage(i, coinCells->at(i)->getEmptyVoltage(),
    				                    "single_cell_discharge_"+std::to_string(getGlobalstep())+"_");
    				if(!ret)
    					return ret;
    				break;
    			default:
    				break;
    		}
    	}
    	return ret;
    }
    
    bool Expirament::startup()
    {
    	Log(Log::INFO)<<"Runnin startup sequence";
    	Log(Log::INFO)<<"Checking coincells";
    
    	float leadOcv;
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		Log(Log::INFO)<<"Reading cell "<<i;
    		bool shorted;
    		bool ret = (*coinCells)[i]->isShorted(shorted);
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"Unable to read shorted state from cell holder "<<i;
    			return false;
    		}
    		else if(shorted)
    		{
    			Log(Log::ERROR)<<"Coin cell holder "<<i<<" is shorted!";
    			return false;
    		}
    
    		float ocv;
    		ret = (*coinCells)[i]->measureOcv(ocv);
    		if(!ret)
    		{
    			Log(Log::ERROR)<<"Unable read ocv from cell holder "<<i;
    			return false;
    		}
    		else if(ocv < (*coinCells)[i]->getEmptyVoltage()-0.1 || ocv > (*coinCells)[i]->getFullVoltage()+0.1)
    		{
    			Log(Log::ERROR)<<"Cell "<<i<<" has a voltage that is out of range";
    			return false;
    		}
    		else if(i == 0)
    		{
    			leadOcv = ocv;
    		}
    		else if(std::abs(leadOcv - ocv) > 0.2)
    		{
    			Log(Log::WARN)<<"Cell "<<i<<" has a voltage delta of "<<std::abs(leadOcv - ocv)<<" compeared to Cell 0, cell equalization needed";
    			ret = chargeCellToVoltage(i, leadOcv, "voltage_equlaization_");
    			if(!ret)
    			{
    				Log(Log::ERROR)<<"Unable to equalize cell "<<i;
    				return false;
    			}
    		}
    
    		Log(Log::INFO)<<"Cell "<<i<<" has a voltage of "<<ocv;
    
    		ret = coinCells->at(i)->setEnabled(true);
    		if(!ret)
    		{
    			Log(Log::INFO)<<"Heater for cell "<<i<<" has failed to enable";
    			return false;
    		}
    	}
    
    	Log(Log::INFO)<<"Activateing PSU";
    	if(!preparePsu())
    		return false;
    
    	Log(Log::INFO)<<"Setting all temperatures";
    	setTemperatures(0);
    
    	Log(Log::INFO)<<"Waiting for heaters to reatch temperature";
    	bool ret = heaters->allReady();
    	if(!ret)
    		return false;
    
    	Log(Log::INFO)<<"Charging all cells to 50% soc";
    	if(!charge(0.5, true))
    		return false;
    
    	Log(Log::INFO)<<"Initilization finished";
    	return true;
    }
    
    std::filesystem::path Expirament::createCsvPath(const std::filesystem::path& filename)
    {
    	int i = 0;
    	std::filesystem::path candidate = outdir/(filename.string() + "-" + std::to_string(i) + ".csv");
    	while(std::filesystem::exists(candidate))
    	{
    		++i;
    		candidate = outdir/(filename.string() + "-" + std::to_string(i) + ".csv");
    	}
    	return candidate;
    }
    
    bool Expirament::shutdown()
    {
    	Log(Log::INFO)<<"Shutting down";
    
    	multiplexers->disconnectAll();
    
    	for(size_t i = 0; i < coinCells->size(); ++i)
    	{
    		int ret = coinCells->at(i)->setEnabled(false);
    		if(!ret)
    		{
    			Log(Log::INFO)<<"Heater for cell "<<i<<" has failed disable";
    			return false;
    		}
    	}
    
    	return psu->setEnabled(false);
    }
    
    void Expirament::saveStep(size_t substep)
    {
    	std::fstream file(stepfile, std::ios_base::out | std::ios_base::trunc);
    	if(!file.is_open())
    	{
    		Log(Log::WARN)<<"Coult not open "<<stepfile<<" in order to save current step";
    		return;
    	}
    	file<<globalstep<<','<<substep<<std::endl;
    	file.close();
    }
    
    size_t Expirament::getGlobalstep()
    {
    	return globalstep;
    }