Guest User

Untitled

a guest
Jun 20th, 2025
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.01 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, messagebox
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
  6.  
  7. # Sample parts library
  8. def get_parts_library():
  9. return [
  10. {"part": "Bourns 5240-RC", "L_uH": 40, "SRF_MHz": 145, "DC_R_ohm": 0.16},
  11. {"part": "ExampleCo 1001", "L_uH": 10, "SRF_MHz": 100, "DC_R_ohm": 0.05},
  12. {"part": "RFChokes Inc 500", "L_uH": 50, "SRF_MHz": 200, "DC_R_ohm": 0.2},
  13. ]
  14.  
  15. # Calculation functions
  16. def calculate_impedance(L, freqs):
  17. return 2 * np.pi * freqs * L
  18.  
  19. class RFChokeSizerApp:
  20. def __init__(self, root):
  21. self.root = root
  22. self.root.title("RF Choke & Discharge Sizer")
  23. # Set global font size
  24. default_font = ('Helvetica', 12)
  25. self.root.option_add("*Font", default_font)
  26. # Make window resizable
  27. self.root.geometry('800x600')
  28.  
  29. self._build_ui()
  30.  
  31. def _build_ui(self):
  32. frame = ttk.Frame(self.root, padding=20)
  33. frame.pack(fill='both', expand=True)
  34.  
  35. # Inputs
  36. inputs = [
  37. ("Min Freq (MHz)", "7"),
  38. ("Max Freq (MHz)", "22"),
  39. ("Points", "100"),
  40. ("Z0 (Ω)", "50"),
  41. ("Multiple k", "10"),
  42. ("Elevation (m)","0"),
  43. ]
  44. self.vars = {}
  45. for i, (label, default) in enumerate(inputs):
  46. lbl = ttk.Label(frame, text=label)
  47. lbl.grid(row=i, column=0, sticky="e", padx=(0,10), pady=5)
  48. var = tk.StringVar(value=default)
  49. self.vars[label] = var
  50. entry = ttk.Entry(frame, textvariable=var, width=15)
  51. entry.grid(row=i, column=1, sticky="w", pady=5)
  52.  
  53. # Parts combobox
  54. row_idx = len(inputs)
  55. ttk.Label(frame, text="Select Part").grid(row=row_idx, column=0, sticky="e", padx=(0,10), pady=5)
  56. parts = get_parts_library()
  57. self.part_names = [p['part'] for p in parts]
  58. self.parts = parts
  59. self.part_var = tk.StringVar()
  60. self.part_combo = ttk.Combobox(frame, textvariable=self.part_var, values=self.part_names, state="readonly", width=20)
  61. self.part_combo.grid(row=row_idx, column=1, sticky="w", pady=5)
  62.  
  63. # Compute button
  64. compute_btn = ttk.Button(frame, text="Compute", command=self.compute)
  65. compute_btn.grid(row=row_idx+1, column=0, columnspan=2, pady=(15, 10))
  66.  
  67. # Results text
  68. self.result_text = tk.Text(frame, width=60, height=8)
  69. self.result_text.config(state="disabled", wrap='word')
  70. self.result_text.grid(row=row_idx+2, column=0, columnspan=2, pady=(10,0))
  71.  
  72. # Plot area
  73. plot_frame = ttk.Frame(frame)
  74. plot_frame.grid(row=row_idx+3, column=0, columnspan=2, pady=20, sticky='nsew')
  75. frame.rowconfigure(row_idx+3, weight=1)
  76. frame.columnconfigure(1, weight=1)
  77.  
  78. self.fig, self.ax = plt.subplots(figsize=(6,4))
  79. self.canvas = FigureCanvasTkAgg(self.fig, master=plot_frame)
  80. self.canvas.get_tk_widget().pack(fill='both', expand=True)
  81.  
  82. def compute(self):
  83. try:
  84. f_low = float(self.vars["Min Freq (MHz)"].get()) * 1e6
  85. f_high = float(self.vars["Max Freq (MHz)"].get()) * 1e6
  86. n_points = int(self.vars["Points"].get())
  87. Z0 = float(self.vars["Z0 (Ω)"].get())
  88. k = float(self.vars["Multiple k"].get())
  89. elev = float(self.vars["Elevation (m)"].get())
  90.  
  91. freqs = np.linspace(f_low, f_high, n_points)
  92. target = k * Z0
  93. L_ideal = target / (2 * np.pi * f_low)
  94. X_ideal = calculate_impedance(L_ideal, freqs)
  95.  
  96. selected_part = next((p for p in self.parts if p['part'] == self.part_var.get()), None)
  97. if selected_part:
  98. L_sel = selected_part['L_uH'] * 1e-6
  99. X_sel = calculate_impedance(L_sel, freqs)
  100. part_desc = f"Selected: {selected_part['part']} (L={selected_part['L_uH']}µH, SRF={selected_part['SRF_MHz']}MHz, DC R={selected_part['DC_R_ohm']}Ω)"
  101. X_at_high = X_sel[-1]
  102. else:
  103. X_sel = X_ideal
  104. part_desc = "No part selected; using ideal L"
  105. X_at_high = X_ideal[-1]
  106.  
  107. altitude_msg = ''
  108. if elev > 1000:
  109. altitude_msg = ('Warning: elevation >1000m may reduce air breakdown voltage; consider corona rings or lower DC bleed resistance.\n')
  110.  
  111. result_str = (
  112. f"Target Impedance: {target:.1f} Ω\n"
  113. f"Ideal L: {L_ideal*1e6:.2f} µH\n"
  114. f"{part_desc}\n"
  115. f"Impedance at {freqs[-1]/1e6:.1f} MHz: {X_at_high:.1f} Ω\n"
  116. f"{altitude_msg}"
  117. )
  118. self.result_text.config(state="normal")
  119. self.result_text.delete("1.0", tk.END)
  120. self.result_text.insert(tk.END, result_str)
  121. self.result_text.config(state="disabled")
  122.  
  123. # Plot
  124. self.ax.clear()
  125. self.ax.plot(freqs/1e6, X_ideal, label='Ideal L', linewidth=2)
  126. if selected_part:
  127. self.ax.plot(freqs/1e6, X_sel, '--', label='Selected Part', linewidth=2)
  128. self.ax.axhline(target, color='black', linewidth=1, label='Target')
  129. self.ax.set_xlabel('Frequency (MHz)')
  130. self.ax.set_ylabel('Impedance (Ω)')
  131. self.ax.set_title('Choke Impedance vs Frequency')
  132. self.ax.legend()
  133. self.canvas.draw()
  134.  
  135. except Exception as e:
  136. messagebox.showerror("Error", str(e))
  137.  
  138. if __name__ == '__main__':
  139. root = tk.Tk()
  140. app = RFChokeSizerApp(root)
  141. root.mainloop()
  142.  
  143. # --------------------------------------------------
  144. # A note from a reddit user
  145. # In response to your question on Reddit, CanNeverPassCaptch made this program for you.
  146. # Feel free to share, adapt, rename—it's all yours.
  147. # Enjoy and happy testing!
  148. # --------------------------------------------------
  149.  
Advertisement
Add Comment
Please, Sign In to add comment