Пример #1
0
        /// <summary>
        /// Configures submatrices so that <paramref name="opAmp"/> is considered to work in saturation, however output remains at 0 - op-amps have
        /// to be manually activated, for example using <see cref="ActivateSaturatedOpAmp(AdmittanceMatrix, IOpAmpDescription)"/>.
        /// </summary>
        /// <param name="matrix"></param>
        /// <param name="opAmp"></param>
        private void ConfigureOpAmpForSaturation(AdmittanceMatrix matrix, IOpAmpDescription opAmp)
        {
            // Indices of op-amps nodes
            var nodes = _OpAmpsNodes[opAmp];

            // And its index
            var index = _IndexedComponentsIndices[opAmp];

            // If the non-inverting input is not grounded, reset its entry in the _C matrix
            if (nodes.NonInvertingInput != ReferenceNode)
            {
                matrix._C[index, nodes.NonInvertingInput] = 0;
            }

            // If the inverting input is not grounded, reset its entry in the _C matrix
            if (nodes.InvertingInput != ReferenceNode)
            {
                matrix._C[index, nodes.InvertingInput] = 0;
            }

            // And the entry in _C corresponding to the output node to 1
            // It is important that, when non-inverting input is connected directly to the output, the entry in _B
            // corresponding to that node is 1 (and not 0 like the if above would set it). Because this assigning is done after
            // the one for non-inverting input no special conditions are necessary however it's very important to remeber about
            // it if (when) this method is modified
            matrix._C[index, nodes.Output] = 1;
        }
Пример #2
0
        /// <summary>
        /// Configures submatrices so that <paramref name="opAmp"/> is considered to work in active operation (output is between
        /// supply voltages)
        /// </summary>
        /// <param name="matrix"></param>
        /// <param name="opAmp"></param>
        private void ConfigureOpAmpForActiveOperation(AdmittanceMatrix matrix, IOpAmpDescription opAmp)
        {
            // Get nodes of the op-amp
            var nodes = _OpAmpsNodes[opAmp];

            // As well as its index
            var index = _IndexedComponentsIndices[opAmp];

            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            //																													 //
            // Very important: in case the non-inverting input and output are short-circuited (they are the same node) then		 //
            // the value of 1 should be entered into the corresponding cell in _C array. This comes from the fact that having	 //
            // -OpenLoopGain and OpenLoogGain in the _C in the same row enforces potentials at both inputs to be equal. However  //
            // if the non-inverting input is shorted then the OpenLoopGain value has no place in _C and 1 from the output should //
            // be put there.																									 //
            // If the inverting input is shorted with the output then the OpenLoopGain should be put int the corresponding cell  //
            // instead of 1. That's because the initial assumption that V+ = V- is made and if Vout = V- (the same node) then	 //
            // The OpenLoopGain has to be used to guarantee both voltages will be equal											 //
            // (so matrix looks like : ... -k ... k ... | 0 which boils down to kV- = kV+ which means V- = V+)					 //
            // That's why it is very important that if (when) this method is modified the rules presented above are obeyed.		 //
            //																													 //
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // If there exists a node to which TerminalA (non-inverting input) is connected
            // (it's possible it may not exist due to removed ground node)
            if (nodes.NonInvertingInput != ReferenceNode)
            {
                // Fill the entry in the row corresponding to the op-amp (plus starting row)
                // and column corresponding to the node (positive terminal) with -OpenLoopGain
                matrix._C[index, nodes.NonInvertingInput] = -opAmp.OpenLoopGain;
            }

            // If there exists a node to which TerminalB (inverting input) is connected
            // (it's possible it may not exist due to removed ground node)
            if (nodes.InvertingInput != ReferenceNode)
            {
                // Fill the entry in the row corresponding to the op-amp (plus starting row)
                // and column corresponding to the node (positive terminal) with OpenLoopGain
                matrix._C[index, nodes.InvertingInput] = opAmp.OpenLoopGain;
            }

            // If the output is not shorted with the inverting input
            if (nodes.Output != nodes.InvertingInput)
            {
                matrix._C[index, nodes.Output] = 1;
            }

            // Fill the entry in the row corresponding to the op-amp (plus starting row)
            // and column corresponding to the node (positive terminal) with 1
            matrix._E[index] = 0;
        }
Пример #3
0
        /// <summary>
        /// Configures <see cref="IOpAmp"/> for operation in <paramref name="operationMode"/> in <paramref name="matrix"/>. Saturated op-amps remain
        /// inactive after this call - they will appear to be saturated but saturation voltage will be equal to 0. Op-amps have to be manually
        /// activated, for example using <see cref="ActivateSaturatedOpAmps(AdmittanceMatrix)"/>
        /// </summary>
        /// <param name="matrix"></param>
        /// <param name="opAmpIndex"></param>
        /// <param name="operationMode"></param>
        private void ConfigureOpAmpOperation(AdmittanceMatrix matrix, IOpAmpDescription opAmp, OpAmpOperationMode operationMode)
        {
            // Call appropriate method based on operation mode
            switch (_OpAmpOperation[opAmp])
            {
            case OpAmpOperationMode.Active:
            {
                ConfigureOpAmpForActiveOperation(matrix, opAmp);
            }
            break;

            case OpAmpOperationMode.PositiveSaturation:
            case OpAmpOperationMode.NegativeSaturation:
            {
                ConfigureOpAmpForSaturation(matrix, opAmp);
            }
            break;

            default:
            {
                throw new Exception("Unhandled case");
            }
            }
        }
Пример #4
0
 /// <summary>
 /// Activates saturated op-amp - modifies matrix E with saturation voltage in entry corresponding to that op-amp. Does not check if
 /// the op-amp is in fact saturated - assumes that caller checked that.
 /// </summary>
 /// <param name="matrix"></param>
 /// <param name="opAmp"></param>
 private void ActivateSaturatedOpAmp(AdmittanceMatrix matrix, IOpAmpDescription opAmp) =>
 // Depending on which supply was exceeded, set the value of the op-amp output to either positive or negative
 // supply voltage, depending on saturaiton (if determined that it is in either saturation).
 // Modify entry in E matrix corresponding to index of the op-amp.
 matrix._E[_IndexedComponentsIndices[opAmp]] = _OpAmpOperation[opAmp] == OpAmpOperationMode.PositiveSaturation ?
                                               opAmp.PositiveSupplyVoltage : opAmp.NegativeSupplyVoltage;