""" plot.py -- erzeugt aus messwerte.csv: * plot.pdf Bode-Diagramm (Betrag und Phase) * tabelle.tex LaTeX-Tabelle der Messpunkte * werte.tex LaTeX-Makros: \\omegaKtheorie, \\omegaKmess, \\abweichung Idee: messwerte.csv ist die EINZIGE Quelle der Wahrheit. paper.tex enthaelt keine Messzahlen mehr. CSV aendern, plot.py laufen lassen, paper.tex neu kompilieren -- alles bleibt konsistent. """ import numpy as np import matplotlib.pyplot as plt # 1) CSV einlesen ------------------------------------------------------ # 3 Spalten: omega_rad_s, betrag_dB, phase_grad (erste Zeile = Ueberschrift) daten = np.loadtxt("messwerte.csv", delimiter=",", skiprows=1) omega = daten[:, 0] # Kreisfrequenz in rad/s betrag = daten[:, 1] # Amplitudengang in dB phase = daten[:, 2] # Phasengang in Grad # 2) Theoretische Knickfrequenz (aus Identifikation der Strecke) ------- # PT2-Modell der Drehzahl-Strecke: omega_n = 56 rad/s omega_K_theor = 56 # Knickfrequenz lt. Modell K_s_dB = betrag[0] # DC-Verstaerkung (tiefste Frequenz) # 3) Gemessene Knickfrequenz: dort wo der Betrag um 3 dB faellt -------- ziel_dB = K_s_dB - 3 # np.interp braucht aufsteigende x-Werte; betrag faellt mit omega -> umdrehen: omega_K_mess = np.interp(ziel_dB, np.flip(betrag), np.flip(omega)) abweichung = abs(omega_K_mess - omega_K_theor) / omega_K_theor * 100 # 4) Bode-Diagramm zeichnen (zwei Subplots: Betrag + Phase) ------------ fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(5, 4), sharex=True) ax1.semilogx(omega, betrag, "o-") ax1.axhline(ziel_dB, linestyle=":", color="gray", label=f"$K_s - 3$ dB = {ziel_dB:.2f} dB") ax1.axvline(omega_K_theor, linestyle="--", color="gray", label=f"$\\omega_K$ theor. = {omega_K_theor} rad/s") ax1.set_ylabel("Betrag in dB") ax1.legend(loc="lower left", fontsize=8) ax1.grid(True, which="both", alpha=0.3) ax2.semilogx(omega, phase, "o-") ax2.set_xlabel("Kreisfrequenz $\\omega$ in rad/s") ax2.set_ylabel("Phase in Grad") ax2.grid(True, which="both", alpha=0.3) fig.tight_layout() fig.savefig("plot.pdf") # 5) Hilfsfunktion: Zahl mit deutschem Komma --------------------------- def deutsch(zahl, nachkommastellen=2): """1.59 -> '1{,}59' (LaTeX-tauglich, deutsches Komma).""" text = f"{zahl:.{nachkommastellen}f}" return text.replace(".", "{,}") # 6) Tabelle als LaTeX-Code schreiben ---------------------------------- zeilen = [ r"\begin{tabular}{rrr}", r"\toprule", r"$\omega$ (rad/s) & Betrag (dB) & Phase ($^\circ$) \\", r"\midrule", ] for i in range(len(omega)): zeilen.append(f"{omega[i]:g} & {deutsch(betrag[i])} & {deutsch(phase[i], 1)} \\\\") zeilen.append(r"\bottomrule") zeilen.append(r"\end{tabular}") with open("tabelle.tex", "w", encoding="utf-8") as datei: datei.write("\n".join(zeilen) + "\n") # 7) Werte als LaTeX-Makros schreiben ---------------------------------- with open("werte.tex", "w", encoding="utf-8") as datei: datei.write(r"\newcommand{\omegaKtheorie}{" + deutsch(omega_K_theor, 0) + "}\n") datei.write(r"\newcommand{\omegaKmess}{" + deutsch(omega_K_mess, 1) + "}\n") datei.write(r"\newcommand{\abweichung}{" + deutsch(abweichung, 1) + "}\n") print("Fertig: plot.pdf, tabelle.tex, werte.tex") print(f" theoretisch: omega_K = {omega_K_theor} rad/s") print(f" gemessen: omega_K = {omega_K_mess:.2f} rad/s") print(f" Abweichung: {abweichung:.1f} %")