Jump to content

Supercapacitor modelling with ELN


Recommended Posts

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:

  1. the provided Voltage
  2. the current Energy
  3. 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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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;
}

 

Link to comment
Share on other sites

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?
Link to comment
Share on other sites

  • 2 weeks later...

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...