Final Project
Final Project
RC-Circuit Calculator
Introduction
A simple RC electric circuit consists of an EMF source (battery), a Resistor,
and a Capacitor. When the resistor and capacitor are connected in series with
the EMF source, the capacitor is being charged. When the EMF source is
bypassed, the capacitor discharges. Both of these actions produce a current.
There is a mathematical relationship between EMF, resistance, capacitance,
time, and current, and that is what this application calculates and displays.
Index
Quantity
Voltage
Current
Resistance
Capacitan
ce
Charge
Time
Formulas
Symbol
V or E
I
R
C
Q
t
Unit
Abbreviati
Volt
Ampere
Ohm
Farad
on
V
A
Coulomb
Seconds
t
)
RC
1e
q=Qf
(Charging)
I0 =
Qf =VC
C
s
q=Q0 e
t
)
RC
(Discharging)
V
R
i=I 0 e
t
)
RC
Methods
1. Assigned member variables for time, capacitance, current, resistance,
charge, and voltage.
2. Calculated the initial current (I0) and max charge Q0 outside of loop.
3. Set time to 0.
4. Created a multiplier variable based on the users time input to scale the
x cooredinates of the graph to the window. The size of the graph is 500
so multiplier = 500/time.
5. Created a multiplier variable based on the largest quantity to be
graphed (initial current or max charge) and used an if-else statement
to choose between the two. Since the Y graph is + - 100, multiplier 2 is
100 / (I0 or Q0).
6. Created a for-loop with a counter from 1-1000 with a sleep of 10 ms, so
the animation will last 10 seconds.
7. Used time to calculate current and charge and then display the results
in a text box.
8. Used CClient DC to alternate between drawing the current graph and
charge graph for each cycle in the loop.
Results
Charging
Discharging
The program works as intended and all results are accurate. The current
through the circuit and the charge on the capacitor displays correctly over a
specified time period. The final results are displayed in the text boxes on the
right.
Appendix A
Instructions:
1.
2.
3.
4.
5.
6.
7.
Appendix B
C++ Code:
Dlg.h file
// ChargingandDischargingCapacitorDlg.h : header file
//
#pragma once
// CChargingandDischargingCapacitorDlg dialog
class CChargingandDischargingCapacitorDlg : public CDialogEx
{
// Construction
public:
CChargingandDischargingCapacitorDlg(CWnd* pParent = NULL);
constructor
// standard
// Dialog Data
enum { IDD = IDD_CHARGINGANDDISCHARGINGCAPACITOR_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
// Implementation
protected:
HICON m_hIcon;
public:
// DDX/DDV support
CString m_current;
CString m_charge;
CString m_time;
afx_msg void OnBnClickedBtnReset();
double m_boundx;
double m_boundypos;
double m_boundyneg;
afx_msg void OnEnChangeEdtTime();
};
Dld.cpp file
"stdafx.h"
"ChargingandDischargingCapacitor.h"
"ChargingandDischargingCapacitorDlg.h"
"afxdialogex.h"
"math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
// DDX/DDV support
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CChargingandDischargingCapacitorDlg dialog
CChargingandDischargingCapacitorDlg::CChargingandDischargingCapacitorDlg(CWnd* pParent
/*=NULL*/)
: CDialogEx(CChargingandDischargingCapacitorDlg::IDD, pParent)
, m_V(0)
, m_R(0)
, m_C(0)
, m_i(0)
, m_q(0)
, m_t(0)
, m_current(_T(""))
, m_charge(_T(""))
, m_time(_T(""))
, m_boundx(0)
, m_boundypos(0)
, m_boundyneg(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChargingandDischargingCapacitorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDT_EMF, m_V);
DDX_Text(pDX, IDC_EDT_RESISTANCE, m_R);
DDX_Text(pDX, IDC_EDT_CAPACITANCE, m_C);
DDX_Text(pDX, IDC_STA_CURRENT, m_current);
DDX_Text(pDX, IDC_STA_CHARGE, m_charge);
DDX_Text(pDX, IDC_EDT_TIME, m_time);
DDX_Text(pDX, IDC_STA_BOUNDX, m_boundx);
DDX_Text(pDX, IDC_STA_BOUNDYPOS, m_boundypos);
DDX_Text(pDX, IDC_STA_BOUNDYNEG, m_boundyneg);
}
BEGIN_MESSAGE_MAP(CChargingandDischargingCapacitorDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_CHARGE,
&CChargingandDischargingCapacitorDlg::OnBnClickedBtnCharge)
ON_BN_CLICKED(IDC_BTN_DISCHARGE,
&CChargingandDischargingCapacitorDlg::OnBnClickedBtnDischarge)
ON_BN_CLICKED(IDC_BTN_RESET,
&CChargingandDischargingCapacitorDlg::OnBnClickedBtnReset)
ON_EN_CHANGE(IDC_EDT_TIME,
&CChargingandDischargingCapacitorDlg::OnEnChangeEdtTime)
END_MESSAGE_MAP()
SendMessage(WM_ICONERASEBKGND,
reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChargingandDischargingCapacitorDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CChargingandDischargingCapacitorDlg::OnBnClickedBtnCharge()
{
// TODO: Add your control notification handler code here
UpdateData(true);
m_t = _tstof(m_time);
double mult = 500/m_t;
double mult2;
double I0 = m_V/m_R;
double j = m_t/100;
double Q0 = m_V * m_C;
double cur,curp,t,tp,q,qp;
curp = 200;
tp = 50;
qp = 200;
m_t = 0;
if(I0 > Q0)
{
mult2 = 100/I0;
m_boundypos = I0;
m_boundyneg = -I0;
}
else
{
mult2 = 100/Q0;
m_boundypos = Q0;
m_boundyneg = -Q0;
CClientDC dc(this);
CPen greenPen(0,1,RGB(0,255,0));
CPen bluePen(0,1,RGB(0,0,255));
CPen yellowPen(0,1,RGB(255,255,0));
CPen redPen(0,1,RGB(255,0,0));
CPen* pPen;
dc.Rectangle(49,99,551,301);
dc.MoveTo(50,200);
dc.LineTo(550,200);
//Diagram
//
//
dc.MoveTo(625,100);
dc.LineTo(575,100);
dc.LineTo(575,195);
//EMF source
dc.MoveTo(560,195);
dc.LineTo(590,195);
dc.MoveTo(570,205);
dc.LineTo(580,205);
dc.MoveTo(575,205);
dc.LineTo(575,300);
dc.LineTo(725,300);
dc.LineTo(725,100);
dc.LineTo(675,100);
//Resistor
dc.MoveTo(650,300);
dc.LineTo(650,273);
dc.LineTo(655,270);
dc.LineTo(645,265);
dc.LineTo(655,260);
dc.LineTo(645,255);
dc.LineTo(655,250);
dc.LineTo(645,245);
dc.LineTo(650,242);
dc.LineTo(650,180);
//Capacitor
dc.MoveTo(640,180);
dc.LineTo(660,180);
dc.MoveTo(640,170);
dc.LineTo(660,170);
dc.MoveTo(650,170);
dc.LineTo(650,140);
//Switch
pPen = dc.SelectObject(&redPen);
dc.LineTo(625,100);
dc.MoveTo(650,140);
pPen = dc.SelectObject(&yellowPen);
dc.LineTo(675,100);
for(int i = 1; i <= 100; i++)
{
m_t += j;
m_time.Format(_T("%1.3e"),m_t);
m_i = I0 * exp(-m_t/(m_R * m_C));
m_current.Format(_T("%1.3e"),m_i);
m_q = m_C * m_V * (1 - exp(-m_t / (m_R * m_C)));
m_charge.Format(_T("%1.3e"),m_q);
t = 50 + mult * m_t;
cur = 200 - mult2 * m_i;
q = 200 - mult2 * m_q;
dc.MoveTo(tp,qp);
pPen = dc.SelectObject(&bluePen);
dc.LineTo(t, q);
qp = q;
dc.MoveTo(tp,curp);
pPen = dc.SelectObject(&greenPen);
dc.LineTo(t,cur);
curp = cur;
tp = t;
Sleep(100);
UpdateData(false);
}
void CChargingandDischargingCapacitorDlg::OnBnClickedBtnDischarge()
{
// TODO: Add your control notification handler code here
UpdateData(true);
m_t = _tstof(m_time);
double mult = 500/m_t;
double mult2;
double q2 = m_q;
m_q = 0;
double j = m_t/100;
double Q0 = m_V * m_C;
double I0 = Q0/(m_R * m_C);
double cur,curp,t,tp,q,qp;
curp = 200;
tp = 50;
qp = 200;
m_t = 0;
if(fabs(I0) > Q0)
{
}
else
{
mult2 = 100/I0;
m_boundypos = I0;
m_boundyneg = -I0;
mult2 = 100/Q0;
m_boundypos = Q0;
m_boundyneg = -Q0;
CClientDC dc(this);
dc.Rectangle(49,99,551,301);
dc.MoveTo(50,200);
dc.LineTo(550,200);
CPen greenPen(0,1,RGB(0,255,0));
CPen bluePen(0,1,RGB(0,0,255));
CPen yellowPen(0,1,RGB(255,255,0));
CPen redPen(0,1,RGB(255,0,0));
CPen* pPen;
//Diagram
//
//
dc.MoveTo(625,100);
dc.LineTo(575,100);
dc.LineTo(575,195);
//EMF source
dc.MoveTo(560,195);
dc.LineTo(590,195);
dc.MoveTo(570,205);
dc.LineTo(580,205);
dc.MoveTo(575,205);
dc.LineTo(575,300);
dc.LineTo(725,300);
dc.LineTo(725,100);
dc.LineTo(675,100);
//Resistor
dc.MoveTo(650,300);
dc.LineTo(650,273);
dc.LineTo(655,270);
dc.LineTo(645,265);
dc.LineTo(655,260);
dc.LineTo(645,255);
dc.LineTo(655,250);
dc.LineTo(645,245);
dc.LineTo(650,242);
dc.LineTo(650,180);
//Capacitor
dc.MoveTo(640,180);
dc.LineTo(660,180);
dc.MoveTo(640,170);
dc.LineTo(660,170);
dc.MoveTo(650,170);
dc.LineTo(650,140);
//Switch
pPen = dc.SelectObject(&redPen);
dc.LineTo(625,100);
dc.MoveTo(650,140);
pPen = dc.SelectObject(&yellowPen);
dc.LineTo(675,100);
for(int i = 1; i <= 100; i++)
{
m_t += j;
m_time.Format(_T("%1.3e"),m_t);
m_i = -m_q/(m_R * m_C);
m_current.Format(_T("%1.3e"),m_i);
m_q = q2 * exp(-m_t/(m_R * m_C));
m_charge.Format(_T("%1.3e"),m_q);
t = 50 + mult * m_t;
cur = 200 - mult2 * m_i;
q = 200 - mult2 * m_q;
dc.MoveTo(tp,qp);
pPen = dc.SelectObject(&bluePen);
dc.LineTo(t, q);
qp = q;
dc.MoveTo(tp,curp);
pPen = dc.SelectObject(&greenPen);
dc.LineTo(t,cur);
curp = cur;
tp = t;
Sleep(100);
UpdateData(false);
}
}
void CChargingandDischargingCapacitorDlg::OnBnClickedBtnReset()
{
// TODO: Add your control notification handler code here
UpdateData(true);
m_V = 0;
m_R = 0;
m_C = 0;
m_time = _T("0");
m_current = _T("0");
m_charge = _T("0");
m_boundx = 1;
m_boundypos = 1;
m_boundyneg = -1;
CClientDC dc(this);
dc.Rectangle(49,99,551,301);
dc.MoveTo(50,200);
dc.LineTo(550,200);
UpdateData(false);
}
void CChargingandDischargingCapacitorDlg::OnEnChangeEdtTime()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialogEx::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.