Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Frequency Response for series and parallel RLC circuits to electricpy.visu #104

Open
Lakshmikanth2001 opened this issue Dec 31, 2022 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@Lakshmikanth2001
Copy link
Contributor

Describe the solution you'd like

  • A clear and concise description of what you want to happen.
  • Computing various parameters like bandwidth, quality factor, resonating frequency, and characteristic equation
  • Plotting the frequency response using matlplotlob

Link to Formulas and Example References

@Lakshmikanth2001 Lakshmikanth2001 added the enhancement New feature or request label Dec 31, 2022
@engineerjoe440
Copy link
Owner

This sounds like a marvelous idea!

Do you have some content or ideas that you'd like to contribute, or is there something I can help with?

@engineerjoe440 engineerjoe440 added this to the Next Version: v0.3.0 milestone Jan 2, 2023
@Lakshmikanth2001
Copy link
Contributor Author

Yes I am having a very abstract idea for Frequency Response as a class in visu.py

Which includes

  • RLC Series Frequency Response
  • Operation Amplifier Frequency Response
  • Any Second order system with a given characteristic equation
class FrequencyResponse:
    def __init__(self) -> None:
        pass

    def band_width(self):
        pass

    def quality_factor():
        pass

    def lower_cut_off_frequency():
        pass

    def upper_cut_off_frequency():
        pass

    def peak_gain():
        pass


class RLC(FrequencyResponse):
    def __init__(self) -> None:
        pass

class OpAmp(FrequencyResponse):
    def __init__(self) -> None:
        pass

@engineerjoe440
Copy link
Owner

I think this would be awesome!

Let me know how I can help!

@Lakshmikanth2001
Copy link
Contributor Author

class RLC(FrequencyResponse):
    def __init__(self, resistance: float, inductance: float, capacitance: float, frequency: float) -> None:
        self.resistance = resistance
        self.inductance = inductance
        self.capacitance = capacitance
        self.frequency = frequency

    def resonance_frequency(self):
        return 1/(_np.sqrt(self.inductance*self.capacitance)*2*_np.pi)

    def band_width(self):
        return self.resistance/(2*_np.pi*self.inductance)

    def quality_factor(self):
        return 2*_np.pi*self.frequency/self.resistance

    def lower_cut_off_frequency(self):
        x = (-self.resistance)/(2*self.inductance)
        resonance_angular_frequency = 2*_np.pi*self.resonance_frequency()

        return (x + _np.sqrt(x**2 + resonance_angular_frequency**2))/(2*_np.pi)

    def upper_cut_off_frequency(self):
        x = (self.resistance)/(2*self.inductance)
        resonance_angular_frequency = 2*_np.pi*self.resonance_frequency()

        return (x + _np.sqrt(x**2 + resonance_angular_frequency**2))/(2*_np.pi)

    def graph(self, lower_frequency_cut: float, upper_frequency_cut: float, samples = 10000):
        x = _np.linspace(lower_frequency_cut, upper_frequency_cut, samples)

        def output_gain(frequency):
            ang_frq = 2*_np.pi*frequency
            current_impedence = self.resistance**2 + (ang_frq*self.inductance - 1/(ang_frq*self.capacitance))**2
            return (self.resistance)/(_np.sqrt(current_impedence))

        y = output_gain(x)

        _plt.title("Frequency response of series RLC circuit")
        _plt.grid(visible=True)

        _plt.plot(x, y)
        _plt.ylabel("Gain")
        _plt.xlabel("Frequency (Hz)")
        f1, f2 = self.lower_cut_off_frequency(), self.upper_cut_off_frequency()
        f = self.resonance_frequency()
        _plt.scatter([f1, f2], [_np.sqrt(0.5), _np.sqrt(0.5)], marker="*", c="black", label='_nolegend_')


        half_power_gain = _np.sqrt(0.5)

        _plt.plot([f, f], [0, 1], ls='-.')
        _plt.plot([f1, f1], [half_power_gain, 0], ls='-.')
        _plt.plot([f2, f2], [half_power_gain, 0], ls='-.')
        _plt.plot([f1, f2], [half_power_gain, half_power_gain], ls='-.')

        _plt.plot([0, f], [half_power_gain, half_power_gain], label="_nolegend_", ls ="--")
        _plt.plot([0, f], [1, 1], label="_nolegend_", ls ="--")
        _plt.plot([0, 0], [half_power_gain, 1], label="Quality factor", c="black")
        _plt.scatter([0], [half_power_gain], label="_nolegend_", c="black", marker='v')
        _plt.scatter([0], [1], label="_nolegend_", c="black", marker='^')
        _plt.legend([
            'Gain',
            f'Resonance frequency ({f}Hz)',
            f'Lower cutoff frequency ({f1}Hz)',
            f'Upper cutoff frequency ({f2}Hz)',
            f'Bandwidth ({f2 - f1}Hz)',
            f'Quality factor {self.quality_factor()}'
        ])
        return _plt

Greeting,

  • can you help me with documenting each and every function of above and this methods and classes
  • should we take input in (uF, KHz) insted of (Farad and Hz)

@engineerjoe440
Copy link
Owner

engineerjoe440 commented May 15, 2023

Hi @Lakshmikanth2001! 👋

Regarding:

  • should we take input in (uF, KHz) insted of (Farad and Hz)

I think that we should probably only accept units in Farads and Hz, since those seem to be the most prolific throughout the package, and consistency is key! Converting to those units is relatively easy, so it shouldn't be too troublesome.


Regarding:

  • can you help me with documenting each and every function of above and this methods and classes

You bet! 😄 Happy to lend a hand, here!

Sample Python
class RLC(FrequencyResponse):
    """Frequency Response for a Traditional RLC (Resistive, Inductive, Capacitive) Load."""

    def __init__(self, resistance: float, inductance: float, capacitance: float, frequency: float) -> None:
        """Form the Frequency Response Analysis System."""
        self.resistance = resistance
        self.inductance = inductance
        self.capacitance = capacitance
        self.frequency = frequency

    @property
    def resonance_frequency(self):
        """Resonance Frequency (in Hz) of the Described RLC Circuit."""
        return 1/(_np.sqrt(self.inductance*self.capacitance)*2*_np.pi)

    @property
    def bandwidth(self):
        """Bandwidth of the Described RLC Circuit."""
        return self.resistance/(2*_np.pi*self.inductance)

    @property
    def quality_factor(self):
        """Quality Factor of the Described RLC Circuit."""
        return 2*_np.pi*self.frequency/self.resistance

    @property
    def lower_cutoff_frequency(self):
        """Lower Cutoff Frequency (in Hz) of the Described RLC Circuit."""
        x = (-self.resistance)/(2*self.inductance)
        resonance_angular_frequency = 2*_np.pi*self.resonance_frequency()

        return (x + _np.sqrt(x**2 + resonance_angular_frequency**2))/(2*_np.pi)

    @property
    def upper_cut_off_frequency(self):
        x = (self.resistance)/(2*self.inductance)
        resonance_angular_frequency = 2*_np.pi*self.resonance_frequency()

        return (x + _np.sqrt(x**2 + resonance_angular_frequency**2))/(2*_np.pi)

    def output_gain(self, frequency: float):
        """
        Evaluated Output Gain of the Described RLC Circuit at a Particular Frequency.
        
        Parameters
        -----------
        frequency:  float
                          Frequency (in Hz) at which the output gain should be evaluated.
        """
        ang_frq = 2*_np.pi*frequency
        current_impedence = self.resistance**2 + (ang_frq*self.inductance - 1/(ang_frq*self.capacitance))**2
        return (self.resistance)/(_np.sqrt(current_impedence))

    def graph(self, lower_frequency_cut: float, upper_frequency_cut: float, samples = 10000):
        """
        Generate a Plot to Represent all Data Respective of the RLC Circuit.
        
        Parameters
        ----------
        lower_frequency_cut:  float
                                   Minimum frequency to demonstrate as a boundary of the X-axis of the plot.
        upper_frequency_cut: float
                                   Maximum frequency to demonstrate as a boundary of the X-axis of the plot.
        samples:                   float
                                   Number of samples over which the plot should be formed.
        """
        x = _np.linspace(lower_frequency_cut, upper_frequency_cut, samples)

        y = self.output_gain(x)

        _plt.title("Frequency response of series RLC circuit")
        _plt.grid(visible=True)

        _plt.plot(x, y)
        _plt.ylabel("Gain")
        _plt.xlabel("Frequency (Hz)")
        f1, f2 = self.lower_cut_off_frequency, self.upper_cut_off_frequency
        f = self.resonance_frequency
        _plt.scatter([f1, f2], [_np.sqrt(0.5), _np.sqrt(0.5)], marker="*", c="black", label='_nolegend_')


        half_power_gain = _np.sqrt(0.5)

        _plt.plot([f, f], [0, 1], ls='-.')
        _plt.plot([f1, f1], [half_power_gain, 0], ls='-.')
        _plt.plot([f2, f2], [half_power_gain, 0], ls='-.')
        _plt.plot([f1, f2], [half_power_gain, half_power_gain], ls='-.')

        _plt.plot([0, f], [half_power_gain, half_power_gain], label="_nolegend_", ls ="--")
        _plt.plot([0, f], [1, 1], label="_nolegend_", ls ="--")
        _plt.plot([0, 0], [half_power_gain, 1], label="Quality factor", c="black")
        _plt.scatter([0], [half_power_gain], label="_nolegend_", c="black", marker='v')
        _plt.scatter([0], [1], label="_nolegend_", c="black", marker='^')
        _plt.legend([
            'Gain',
            f'Resonance frequency ({f}Hz)',
            f'Lower cutoff frequency ({f1}Hz)',
            f'Upper cutoff frequency ({f2}Hz)',
            f'Bandwidth ({f2 - f1}Hz)',
            f'Quality factor {self.quality_factor}'
        ])
        return _plt

Please note that I've also added a few general suggestions in the layout of the class (mainly, I think that some of those methods could easily be properties, and that inner-function in the graph method could be valuable by itself.

@engineerjoe440
Copy link
Owner

Thanks, @Lakshmikanth2001! 🎉

Let me know if you feel this issue is ready to close, or if you had other items you wish to add before we consider this work "done."

@Lakshmikanth2001
Copy link
Contributor Author

please test this changes from an end user perspective and give your valuable feedback we need to add Frequency Responses for

parallerl RLC ,OpAmp and First and second order control systems etc which can complete the Frequency Response issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants