Balint Bujtor Posted July 29 Report Posted July 29 Hello, I want to model a supercapacitor with ELN. As input, I have the requested current and as outputs, I would like to provide 3 signals in total: the provided Voltage the current Energy and the current SOC I created the following header and cpp files for the supercapacitor: supercapacitor.h: SC_MODULE(supercapacitor_eln) { // Interface and internal components declaration sca_tdf::sca_in<double> I; // Requested supercapacitor current sca_tdf::sca_out<double> V; // Provided supercapacitor voltage // transformers bw ELN and TDF sca_eln::sca_tdf::sca_isource iin; sca_eln::sca_tdf::sca_vsink vout; sca_eln::sca_c C_sc; // Capacitance (for supercap) sca_eln::sca_r R_l; // Leakage resistance sca_eln::sca_r R_s; // Series resistance // Constructor supercapacitor_eln( double C_val = 3, double Rl_val = 500000, double Rs_val = 0.08 ); // internal node and ref node private: sca_eln::sca_node node_top, node_mid; sca_eln::sca_node_ref gnd; }; supercapacitor.cpp: supercapacitor_eln::supercapacitor_eln( double C_val, double Rl_val, double Rs_val ): I("I"), V("V"), iin("iin"), vout("vout"), C_sc("C_sc", C_val), R_l("R_l", Rl_val), R_s("R_s", Rs_val), node_top("node_top"), node_mid("node_mid"), gnd("gnd") { // Connect the in and out interfaces iin.inp(I); iin.p(node_top); iin.n(gnd); vout.p(node_top); vout.n(gnd); vout.outp(V); // Connect the components C_sc.p(node_top); C_sc.n(node_mid); R_l.p(node_top); R_l.n(node_mid); R_s.p(node_mid); R_s.n(gnd); } However, I am struggling how to calculate the current Energy and the SOC. I have tried to read the value of 'V' but I cannot access it, hence I am unable to compute the energy of the supercapacitor (which would be: E = 1/2*C*V*V). Any suggestions on how to do this? I was wondering how to create a wrapper TDF class around this class, but I am unsure if that would be beneficial. I appreciate your help in advance. BR Quote
Martin Barnasconi Posted July 31 Report Posted July 31 What you've shown here is only the implementation of the supercapacitor circuit itself. The next step is to instantiate this element in another (top-level) SystemC module, along with another module (e.g. TDF module) in which you do the actual energy calculations based on the measured voltage and parameter values. Since you have an input for the circuit, you also need to instantiate a TDF module acting as source (i.e. set the current level input). After this, you need again to instantiate the top-level module into the sc_main function, where you can define the overall simulation time, and also add the trace functions to explore signals and waveforms. I propose to take a look at the SystemC AMS users guide how to build this topology. Quote
Balint Bujtor Posted August 2 Author Report Posted August 2 Thank you for your answer, @Martin Barnasconi. I followed your suggestions and implemented the structure you sketched up. Right now I have 3 files, the top-level module 'supercapacitor', and 2 other modules 'sc_eln' and 'sc_tdf'. However, when I try to simulate the circuit I get the following error, for every signal related to the supercapacitor declared in the main: Quote Warning: SystemC-AMS: Initialization for tracing of: v_sc failed set wave to 0 In file: .. / .. / .. / .. / .. / .. /src/scams/impl/util/tracing/sca_trace_object_data.cpp:174 In process: sca_implementation_0.cluster_process_0 @ 0 s There are no compile-time errors. Ideally I would like to start with a charged-up supercapacitor and use it as the battery of my system. I am a beginner with SystemC so I don't know how to achieve this. Thank you for your support, I appreciate it. Here are my files: sc_eln.h (sc_eln.cpp is empty): #include <systemc-ams.h> SC_MODULE(sc_eln) { public: // Interface and internal components declaration sca_tdf::sca_in<double> pI_in; // Requested supercapacitor current sca_tdf::sca_out<double> pV_out; // Provided supercapacitor voltage // transformers bw ELN and TDF sca_eln::sca_tdf::sca_isource iin; sca_eln::sca_tdf::sca_vsink vout; // ELN components sca_eln::sca_c C_sc; // Capacitance (for supercap) sca_eln::sca_r R_l; // Leakage resistance sca_eln::sca_r R_s; // Series resistance // Constructor sc_eln( sc_core::sc_module_name nm, double c_par, double r_l_par, double r_s_par): pI_in("pI_in"), pV_out("pV_out"), iin("iin"), vout("vout"), C_sc("C_sc", c_par), R_l("R_l", r_l_par), R_s("R_s", r_s_par), node_top("node_top"), node_mid("node_mid"), gnd("gnd") { iin.inp(pI_in); iin.p(node_top); iin.n(gnd); vout.p(node_top); vout.n(gnd); vout.outp(pV_out); C_sc.p(node_top); C_sc.n(node_mid); R_l.p(node_top); R_l.n(node_mid); R_s.p(node_mid); R_s.n(gnd); } private: // internal node and ref node sca_eln::sca_node node_top, node_mid; sca_eln::sca_node_ref gnd; }; sc_tdf.h: #ifndef SUPERCAPACITOR_H #define SUPERCAPACITOR_H #include <systemc-ams.h> #include "config.h" SC_MODULE(sc_tdf) { public: // Ports sca_tdf::sca_in<double> pV_in; //incoming voltage sca_tdf::sca_out<double> pV_out; //forwarded voltage sca_tdf::sca_out<double> pE_out; //current energy sca_tdf::sca_out<double> pSoC_out; //state of charge sc_tdf( sc_core::sc_module_name nm, double c_par): pV_in("pV_in"), pV_out("pV_out"), pE_out("pE_out"), pSoC_out("pSoC_out"), C(c_par), MAX_E(0.5 * C * VREF_BUS * VREF_BUS), SoC_val(SOC_INIT), E_val(SoC_val * MAX_E) { } void set_attributes(); void initialize(); void processing(); private: const double C; const double MAX_E; double SoC_val; double E_val; }; #endif // SUPERCAPACITOR_H sc_tdf.cpp #include "sc_tdf.h" void sc_tdf::set_attributes() { pV_in.set_timestep(SIM_STEP, sc_core::SC_SEC); pE_out.set_timestep(SIM_STEP, sc_core::SC_SEC); pSoC_out.set_timestep(SIM_STEP, sc_core::SC_SEC); pV_out.set_timestep(SIM_STEP, sc_core::SC_SEC); //pE_out.set_delay(1); //pSoC_out.set_delay(1); //pV_out.set_delay(1); } void sc_tdf::initialize(){} void sc_tdf::processing() { double tmp_v; tmp_v = pV_in.read(); if(tmp_v <= 0) { cout << "ERROR: 0 or less voltage value" << " @" << sc_time_stamp() << "Value V=" << tmp_v << endl; sc_stop(); } if(tmp_v > VREF_BUS) { cout << "Voltage is greatar than VREF_BUS" << " @" << sc_time_stamp() << "Value V=" << tmp_v << endl; tmp_v = VREF_BUS; } pV_out.write(tmp_v); E_val = 0.5 * C * tmp_v * tmp_v; pE_out.write(E_val); SoC_val = E_val / MAX_E; if(SoC_val <= 0.01) { cout << "SC SOC is less than or equal to 1%:" << " @" << sc_time_stamp() << endl; sc_stop(); } pSoC_out.write(SoC_val); } top-level sc.h: #include <systemc-ams.h> #include "sc_eln.h" #include "sc_tdf.h" #include "config.h" SC_MODULE(supercapacitor) { public: sca_tdf::sca_in<double> pI_in; // Battery current sca_tdf::sca_out<double> pV_out; // Voltage sca_tdf::sca_out<double> pE_out; // Energy sca_tdf::sca_out<double> pSoC_out; // State of Charge // connecting signals sca_tdf::sca_signal<double> sVoltage; sc_eln eln_module; sc_tdf tdf_module; supercapacitor( sc_core::sc_module_name nm, double c_par = 3.0, double r_l_par = 500000.0, double r_s_par = 0.08): pI_in("pI_in"), pV_out("pV_out"), pE_out("pE_out"), pSoC_out("pSoC_out"), eln_module("eln_module", c_par, r_l_par, r_s_par), tdf_module("tdf_module", c_par) { //eln_module = new sc_eln('eln_module', c_val, r_l_val, r_s_val); //tdf_module = new sc_tdf('tdf_module', c_val); eln_module.pI_in(pI_in); eln_module.pV_out(sVoltage); tdf_module.pV_in(sVoltage); tdf_module.pV_out(pV_out); tdf_module.pE_out(pE_out); tdf_module.pSoC_out(pSoC_out); } }; and finally the main.cpp (there are other classes used here, but they work correctly): #include <systemc-ams.h> #include "battery.h" #include "bus.h" #include "converter_battery.h" #include "mcu.h" #include "air_quality_sensor.h" #include "sc.h" int sc_main(int argc, char* argv[]) { // Instantiate signals sca_tdf::sca_signal<double> i_batt, v_batt, soc; sca_tdf::sca_signal<double> i_air_quality_sensor; sca_tdf::sca_signal<double> i_mcu; sca_tdf::sca_signal<double> i_tot_batt, i_tot_sc; sca_tdf::sca_signal<double> i_sc, v_sc, e_sc, soc_sc; // Instantiate modules bus bus("bus"); battery battery("battery"); converter_battery converter_battery("converter_battery"); mcu mcu("mcu"); air_quality_sensor air_quality_sensor("air_quality_sensor"); supercapacitor sc_module("supercapacitor"); sc_module.pI_in(i_tot_sc); sc_module.pV_out(v_sc); sc_module.pE_out(e_sc); sc_module.pSoC_out(soc_sc); // Connect signals to modules battery.i_batt(i_batt); battery.v_batt(v_batt); battery.soc(soc); converter_battery.i_bus(i_tot_batt); converter_battery.v_batt(v_batt); converter_battery.i_batt(i_batt); air_quality_sensor.i(i_air_quality_sensor); mcu.i(i_mcu); bus.i_mcu(i_mcu); bus.i_tot_batt(i_tot_batt); bus.i_tot_sc(i_tot_sc); bus.i_air_quality_sensor(i_air_quality_sensor); // define simulation file sca_util::sca_trace_file* atf = sca_util::sca_create_tabular_trace_file("sim_trace.txt"); // the following signals will be traced. Comment any signal you don't want to trace sca_util::sca_trace(atf, i_tot_sc, "i_tot_sc" ); sca_util::sca_trace(atf, i_sc, "i_sc" ); sca_util::sca_trace(atf, v_sc, "v_sc" ); sca_util::sca_trace(atf, e_sc, "e_sc" ); sca_util::sca_trace(atf, soc_sc, "soc_sc" ); cout<<"The simulation starts!"<<endl; sc_start(SIM_LEN, sc_core::SC_SEC); // Set the simulation length cout<<"The simulation ends @ "<<sc_time_stamp()<<endl; sca_util::sca_close_tabular_trace_file(atf); return 0; } Quote
Martin Barnasconi Posted August 6 Report Posted August 6 There are still some issues with your code: avoid the use of `sc_` and `sca_` prefix in your own code. These prefixes are reserved by SystemC and SystemC-AMS and could lead to conflicts with existing library functions and methods, and might confuse for other readers Your instance names in `sc_main` are not correct. E.g., when instantiating a bus of type `bus`, you need to give the instance a specific and different name like `i_bus`. Also the instance name `sc_module` should be avoided at all times!! You miss the header guards in your ELN module. Note that the name of the header guards should be close to the file name Where is SIM_LEN defined? Quote
Balint Bujtor Posted August 19 Author Report Posted August 19 Thank you for your comments, @Martin Barnasconi. Although I appreciate your aim to make my code stylistically flawless, the points that you wrote down do not cause the error that I mention above nor any other errors in the code. Regardless of this I performed the improvements you outlined and tested the simulation again that still yields the same errors as before. For this reason, I would appreciate it more if you could help me with the problem that I highlight in my previous post in this thread. SIM_LEN is defined in another file that I did not include not to clutter the thread to much; it's value is 7736400. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.