:py:mod:`aeroshield` ==================== .. py:module:: aeroshield Subpackages ----------- .. toctree:: :titlesonly: :maxdepth: 3 aeroshield/index.rst plotting/index.rst Submodules ---------- .. toctree:: :titlesonly: :maxdepth: 1 controller/index.rst Package Contents ---------------- Classes ~~~~~~~ .. autoapisummary:: aeroshield.AeroShield aeroshield.DummyShield aeroshield.AeroController Attributes ~~~~~~~~~~ .. autoapisummary:: aeroshield.__version__ .. py:data:: __version__ .. py:class:: AeroShield(baudrate: Optional[int] = 115200, port: Optional[str] = None) .. py:attribute:: RUN :value: 1 .. py:attribute:: STOP :value: 2 .. py:attribute:: TIMEOUT :value: 3 .. py:method:: find_arduino() -> str Get the name of the port that is connected to Arduino. Raises exception if no port was found. :raises AeroShieldException: Raised if no Arduino was found. :return: COM port of the Arduino. :rtype: str .. py:method:: raw_angle_to_deg(raw: int) -> float :staticmethod: Convert raw angle to degrees. :param raw: 12-bit value of angle sensor. :type raw: int :return: Angle value scaled to degrees. :rtype: float .. py:method:: raw_angle_to_rad(raw: int) -> float :staticmethod: Convert raw angle to radians. :param raw: 12-bit value of angle sensor. :type raw: int :return: Angle value scaled to radians. :rtype: float .. py:method:: calibrated_angle_deg(raw_angle: int) -> float Convert angle to degrees and calibrate with zero angle. :param raw_angle: Raw 12-bit angle value. :type raw_angle: int :return: Calibrated angle in degrees. :rtype: float .. py:method:: raw_pot_to_percent(raw: int) -> float :staticmethod: Convert 10-bit potentiometer reading to percentage value. :param raw: 10-bit potentiometer value. :type raw: int :return: Potentiometer value as percentage [0, 1). :rtype: float .. py:method:: read() -> tuple[float] Read data from Arduino. Convert potentiometer and angle readings. Calibrate angle to zero reference. :raises AeroShieldException: Raised if no data was received. This can happen if there was no `write` command preceding a call to `read`. :return: Converted and calibrated potentiometer and angle readings, in that order. :rtype: tuple[float] .. py:method:: saturate(value: float, bits: int) -> int :staticmethod: Saturate value between `0` and `2**bits - 1`. :param value: Raw value. :type value: float :param bits: Number of bits. :type bits: int :return: Saturated value. :rtype: int .. py:method:: write(flag: int, motor: float) -> int Write run/stop flag and motor value to Arduino. Saturate the motor value. :param flag: `AeroShield.RUN` or `AeroShield.STOP`. The former signals normal running mode, the latter tells the Arduino to stop the motor. :type flag: int :param motor: Motor value. :type motor: float :return: Saturated 8-bit motor value. :rtype: int .. py:method:: calibrate() Read out a zero reference. Pendulum should be at rest when calling this method. .. py:method:: stop() Send stop signal to Arduino. .. py:method:: open() Reset buffers and open connection to Arduino if it is not open already. Wait for `AeroShield.TIMEOUT` seconds to make sure connection is established. .. py:method:: close(*args) Close connection to Arduino. .. py:method:: __enter__() .. py:method:: __exit__(*args) .. py:exception:: AeroShieldException Bases: :py:obj:`Exception` Common base class for all non-exit exceptions. .. py:class:: DummyShield Bases: :py:obj:`aeroshield.aeroshield.aeroshield.AeroShield` .. py:method:: read() -> tuple[float] Read data from Arduino. Convert potentiometer and angle readings. Calibrate angle to zero reference. :raises AeroShieldException: Raised if no data was received. This can happen if there was no `write` command preceding a call to `read`. :return: Converted and calibrated potentiometer and angle readings, in that order. :rtype: tuple[float] .. py:method:: write(flag: int, motor: float) Write run/stop flag and motor value to Arduino. Saturate the motor value. :param flag: `AeroShield.RUN` or `AeroShield.STOP`. The former signals normal running mode, the latter tells the Arduino to stop the motor. :type flag: int :param motor: Motor value. :type motor: float :return: Saturated 8-bit motor value. :rtype: int .. py:method:: open() Reset buffers and open connection to Arduino if it is not open already. Wait for `AeroShield.TIMEOUT` seconds to make sure connection is established. .. py:method:: close(*args) Close connection to Arduino. .. py:class:: AeroController(aero_shield: aeroshield.aeroshield.AeroShield) .. py:method:: variables() -> None Define variables to be used by the controller or saved during the experiment. .. py:method:: add_tracked_variable(name: str, size: Optional[int] = 1) -> dict[str, int] Add a variable to the list of variables whose value should be tracked during the experiment and returned afterwards. Variables should be instance variables of the class, otherwise they won't be accessible! :param name: Name of the variable, without 'self.' :type name: str :param size: Size of the variable, e.g. 3 for a three-dimensional position vector. Defaults to 1, i.e. single values. :type size: int, optional :return: A copy of the current map of tracked variables and their respective size. :rtype: dict[str, int] .. py:method:: controller(t: float, dt: float, ref: float, pot: float, angle: float) -> float Implement the controller here. You can subclass AeroController and overwrite the controller. :param t: Time since start of run in seconds. :type t: float :param dt: Length of current time step in seconds. :type dt: float :param ref: reference value for the current step. :type ref: float :param pot: potentiometer value in percent. :type pot: float :param angle: calibrated angle in degrees. :type angle: float :return: input value for motor. the motor value will be saturated (int between 0 and 255 incl.) afterwards :rtype: float .. py:method:: run(freq: int, cycles: int, ref: Optional[float | int | Iterable[float | int]] = None, live_plotter: Optional[aeroshield.plotting.LivePlotter] = None) -> numpy.ndarray Run the controller on the AeroShield. :param freq: Desired frequency of the loop. :type freq: int :param cycles: Number of cycles to run the experiment. :type duration: int :param ref: The reference to follow should have a lenght equal to freq * time. :type ref: np.ndarray[float|int] :param live_plotter: Optional. LivePlotter instance to use for displaying a live plot. :type live_plotter: LivePlotter .. py:method:: _update_hist(hist: numpy.ndarray[float], cntr: int, t: float, ref: float, pot: float, angle: float, motor: float) Update hist array with variables of the current iteration (cntr). If variables were added to `extra_hist_vars`, add them to the hist as well. :param hist: array to update. :type hist: np.ndarray[float] :param cntr: Iteration counter. Provides the first index to hist. :type cntr: int :param t: Time. :type t: float :param ref: Current reference value. :type ref: float :param angle: Current pendulum angle :type angle: float :param motor: Current Motor value. :type motor: float