# Trying to simulate pulse width modulation

I am trying to simulate a pulse width modulated signal in a NDSolve, but i have a hard time passing the signal function in. This is my code:

(* Arbitrary test circuit *)
components = {r iR[t] == vR[t], l iL'[t] == vL[t], iC[t] == c vC'[t]};
connections = {vR[t] + vL[t] + vC[t] - v1[t] == 0,
iL[t] == iR[t], iR[t] == iC[t]};
ic = {iR == 0, iL == 0, iC == 0, vR == 0,
vL == 0, vC == 0, iR' == 0, iL' == 0,
iC' == 0, vR' == 0, vL' == 0, vC' == 0};
params = {r -> 5, l -> 10^-2, c -> 10^-4};

signal = {1, 0.1, 0.1, 0.2, 0, 1, 0, 1, 0, 0.4, 0.4, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

(* Problem in this definition*)
v1[t_] := If[
Mod[t, 1/100]*100 > signal[[ IntegerPart[100.0*t + 1] ]]
, 1, 0
];
(* solve does thus not work*)
sol = NDSolve[
{components, connections, ic} /. params,
vC, {t, 0.0, 0.2}
];


I feel like i'm close but still so far away. The error seems to indicate that ...0,0,0,0,0,0,0,0,0}[[1/2]]] the error is in the Part lookup. How can this be im asking for the IntegerPart? Should i be using some other function for this. Tried wrapping a N in the expression.

Also any ideas how i could make the signal function smooth step would be great.

h[t_?NumericQ] := signal[[Floor[100*t + 1]]];
sol = NDSolveValue[{components, connections, ic,
WhenEvent[Mod[t, 1/100]*100 - h[t] == 0, v1[t] -> Unitize[v1[t] - 1]]} /.
params, {vC, v1}, {t, 0.0, 0.2}, DiscreteVariables -> {v1}];
Plot[Through[sol[t]], {t, 0, .2}, Evaluated -> True] The above solution seems correct,but it isn't.

It is losing the last components of signal because of this behavior:

Plot[Mod[t, 1/100]*100 - h[t], {t, 0, .2}] The events lying on the red ellipse are not detected because the sign of the function and its derivative don't change. One simple (but not precise) way to get those too is:

h[t_?NumericQ] := signal[[Floor[100*t + 1]]];
sol = NDSolveValue[{components, connections, ic,
WhenEvent[Mod[t, 1/100]*100 - h[t] - .05 == 0, v1[t] -> Unitize[v1[t] - 1]]} /.
params, {vC, v1}, {t, 0.0, 0.2}, DiscreteVariables -> {v1}];
Plot[Through[sol[t]], {t, 0, .2}, Evaluated -> True,  PlotPoints -> 1000] • Actually there probably should not be a dip after a 0 pulse so consecutive zeroes should behave like in the first example. – joojaa Jan 26 '16 at 15:38
• @joojaa Well ... you decide ... – Dr. belisarius Jan 26 '16 at 16:03

There are two problems in your code :

• v1[t_] should be replaced by v1[t_?NumericQ] . The idea is to prevent NDSolve[..v1[t]...]to ask what is v1[t] with t purely symbolic. See for example this link.

• Your system of equation contains equalities between variables without derivatives and thus is interpreted as a Differential-Algebric system. Mathematica uses also the DAE solver which is not adapted to this simple classical ODE system.

The hereafter solution is no more that a rewriting of the system with the minimum necessary 2 variables. It has the advantage of being compatible with your definition of v1 : v1[t] = If[Mod[t, 1/100]* ...))

ClearAll[v1];

(*Arbitrary test circuit*)
components = {r iR[t] == vR[t], l iL'[t] == vL[t], iC[t] == c vC'[t]};
connections = {vR[t] + vL[t] + vC[t] - v1[t] == 0, iL[t] == iR[t],
iR[t] == iC[t]};
ic = {iR == 0, iL == 0, iC == 0, vR == 0, vL == 0,
vC == 0, iR' == 0, iL' == 0, iC' == 0, vR' == 0,
vL' == 0, vC' == 0};
params = {r -> 5, l -> 10^-2, c -> 10^-4};

signal = {1, 0.1, 0.1, 0.2, 0, 1, 0, 1, 0, 0.4, 0.4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};

(* no more problems in this definition*)
v1[t_?NumericQ] :=
If[Mod[t, 1/100]*100 > signal[[IntegerPart[100.0*t + 1]]], 1, 0];

(* rewriting of the problem with a minimal set of variables *)
newEqus =
Join[components, connections] //
Eliminate[#, {vL[t], vR[t], iR[t], iC[t]}] & ;

(* only two variables are remaining. Initial condition for these two
variables : *)
newIc = {iL == 0, vC == 0};

(*solution *)
sol = NDSolveValue[{newEqus, newIc} /. params, {vC, v1}, {t, 0.0,
0.2}];

Plot[Through[sol[t]], {t, 0, .2}, Evaluated -> True] • Thanks, I've accepted Dr. belisarius answer, after some testing because it alerted me if event driving which is a good idea in general. Your answer is also very useful. Though you get slightly different results. – joojaa Jan 26 '16 at 11:29