MonsterBoyTabs commited on
Commit
8dcaad2
·
verified ·
1 Parent(s): 7e6186e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -127
app.py CHANGED
@@ -6,168 +6,176 @@ from scipy.signal import square, sawtooth
6
 
7
  # Component configurations
8
  DIODE_DROPS = {"Silicon": 0.7, "Germanium": 0.3, "Ideal": 0.0}
9
- COMPONENT_ICONS = {
10
- "AC Source": "",
11
- "DC Source": "⎓",
12
- "Resistor": "🛑",
13
- "Diode": "↘️"
14
  }
15
 
16
  # Initialize session state
17
  if "circuit" not in st.session_state:
18
  st.session_state.circuit = []
19
- if "waveform_type" not in st.session_state:
20
- st.session_state.waveform_type = "Sine"
 
 
21
 
22
- def calculate_voltage_drop(component, voltage, current):
23
- if component["type"] == "Resistor":
24
- return current * component["value"]
25
- elif component["type"] == "Diode":
26
- return DIODE_DROPS[component["subtype"]] if voltage > DIODE_DROPS[component["subtype"]] else 0
27
- return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- def simulate_circuit(circuit, waveform, freq, amplitude):
30
- time = np.linspace(0, 0.05, 1000)
 
 
31
  results = []
32
 
33
- for t_idx, t in enumerate(time):
34
- entry = {"Time": t}
35
- if circuit[0]["type"] == "AC Source":
36
- if st.session_state.waveform_type == "Sine":
37
- v_in = amplitude * np.sin(2 * np.pi * freq * t)
38
- elif st.session_state.waveform_type == "Square":
39
- v_in = amplitude * square(2 * np.pi * freq * t)
40
- else: # Triangular
41
- v_in = amplitude * sawtooth(2 * np.pi * freq * t, width=0.5)
42
- else: # DC Source
43
- v_in = circuit[0]["value"]
44
-
45
- current = 0
46
- remaining_voltage = v_in
47
- entry["Source Voltage"] = v_in
48
-
49
- for comp in circuit[1:]:
50
- v_drop = calculate_voltage_drop(comp, remaining_voltage, current)
51
- entry[f"{comp['type']} {comp.get('subtype', '')}"] = v_drop
52
- remaining_voltage -= v_drop
53
-
54
- if comp["type"] == "Resistor" and remaining_voltage > 0:
55
- current = remaining_voltage / comp["value"]
56
-
57
- entry["Current"] = current
58
- entry["Output Voltage"] = remaining_voltage
59
- results.append(entry)
60
 
61
- return pd.DataFrame(results)
 
 
 
 
 
62
 
63
- # App layout
64
- st.title("🔌 Interactive Circuit Simulator")
65
- st.markdown("Build your circuit and analyze its behavior")
66
 
67
- # Circuit Builder
68
- with st.expander("🛠️ Circuit Builder", expanded=True):
69
  col1, col2, col3 = st.columns(3)
70
  with col1:
71
- comp_type = st.selectbox("Component Type", ["AC Source", "DC Source", "Resistor", "Diode"])
72
  with col2:
73
  if comp_type in ["Resistor"]:
74
- value = st.number_input("Value (Ω)", 1, 1000, 100)
75
  elif comp_type in ["DC Source"]:
76
- value = st.number_input("Voltage (V)", 1.0, 24.0, 12.0)
77
  else:
78
  value = None
79
  with col3:
80
  if comp_type == "Diode":
81
  subtype = st.selectbox("Diode Type", list(DIODE_DROPS.keys()))
 
82
  else:
83
  subtype = None
 
84
 
85
- if st.button("Add Component"):
86
  st.session_state.circuit.append({
87
  "type": comp_type,
88
  "value": value,
89
- "subtype": subtype
 
 
90
  })
91
 
92
- # Display Circuit
93
- st.subheader("Your Circuit")
94
- if not st.session_state.circuit:
95
- st.warning("No components in circuit!")
96
- else:
97
- circuit_display = " → ".join([
98
- f"{COMPONENT_ICONS[comp['type']]} {comp['type']}" +
99
- (f" ({comp['subtype']})" if comp.get('subtype') else "") +
100
- (f" {comp['value']}Ω" if comp['type'] == "Resistor" else "") +
101
- (f" {comp['value']}V" if comp['type'] == "DC Source" else "")
102
- for comp in st.session_state.circuit
103
- ])
104
- st.markdown(f"`{circuit_display}`")
105
 
106
  # Simulation Controls
107
- st.subheader("Simulation Parameters")
108
- if st.session_state.circuit and st.session_state.circuit[0]["type"] == "AC Source":
109
- st.session_state.waveform_type = st.selectbox("Waveform Type", ["Sine", "Square", "Triangular"])
110
- freq = st.slider("Frequency (Hz)", 1, 1000, 50)
111
- amplitude = st.slider("Amplitude (V)", 1.0, 24.0, 12.0)
112
- else:
113
- freq = None
114
- amplitude = None
115
-
116
- if st.button("▶️ Run Simulation") and st.session_state.circuit:
117
- # Run simulation
118
- df = simulate_circuit(
119
- st.session_state.circuit,
120
- st.session_state.waveform_type,
121
- freq,
122
- amplitude
123
- )
124
-
125
- # Display Results
126
- st.subheader("📊 Simulation Results")
127
-
128
- # Observation Table
129
- with st.expander("📋 Point-to-Point Analysis", expanded=True):
130
- st.dataframe(df.style.format("{:.4f}"), height=300)
131
-
132
- # Waveform Visualization
133
- fig = go.Figure()
134
- fig.add_trace(go.Scatter(x=df["Time"], y=df["Source Voltage"], name="Input Voltage"))
135
- fig.add_trace(go.Scatter(x=df["Time"], y=df["Output Voltage"], name="Output Voltage"))
136
- fig.update_layout(
137
- title="Voltage Waveforms",
138
- xaxis_title="Time (s)",
139
- yaxis_title="Voltage (V)",
140
- hovermode="x unified"
141
- )
142
- st.plotly_chart(fig, use_container_width=True)
143
-
144
- # Current Visualization
145
- fig2 = go.Figure()
146
- fig2.add_trace(go.Scatter(x=df["Time"], y=df["Current"]*1000, name="Current"))
147
- fig2.update_layout(
148
- title="Circuit Current",
149
- xaxis_title="Time (s)",
150
- yaxis_title="Current (mA)",
151
- hovermode="x unified"
152
- )
153
- st.plotly_chart(fig2, use_container_width=True)
154
- elif not st.session_state.circuit:
155
- st.error("Please build a circuit first!")
156
 
157
- # Help Section
158
  with st.expander("❓ How to use"):
159
  st.markdown("""
160
- 1. **Build Circuit**:
161
- - Select component type from dropdown
162
- - Configure parameters (resistance, voltage, diode type)
163
- - Click 'Add Component' to add to circuit
164
- - First component must be a power source (AC/DC)
165
 
166
- 2. **Set Simulation Parameters**:
167
- - For AC circuits: select waveform type and parameters
 
168
 
169
- 3. **Run Simulation**:
170
- - Click 'Run Simulation' to see results
171
- - View point-to-point analysis in table
172
- - Observe voltage and current waveforms
173
  """)
 
6
 
7
  # Component configurations
8
  DIODE_DROPS = {"Silicon": 0.7, "Germanium": 0.3, "Ideal": 0.0}
9
+ COMPONENTS = {
10
+ "AC Source": {"symbol": "~", "orientation": True},
11
+ "DC Source": {"symbol": "⎓", "orientation": True},
12
+ "Resistor": {"symbol": "⬦", "orientation": True},
13
+ "Diode": {"symbol": "→", "orientation": True}
14
  }
15
 
16
  # Initialize session state
17
  if "circuit" not in st.session_state:
18
  st.session_state.circuit = []
19
+ if "connections" not in st.session_state:
20
+ st.session_state.connections = []
21
+ if "selected_component" not in st.session_state:
22
+ st.session_state.selected_component = None
23
 
24
+ def draw_schematic():
25
+ fig = go.Figure()
26
+
27
+ # Draw components
28
+ for idx, comp in enumerate(st.session_state.circuit):
29
+ x = comp["position"][0]
30
+ y = comp["position"][1]
31
+ fig.add_annotation(
32
+ x=x,
33
+ y=y,
34
+ text=COMPONENTS[comp["type"]]["symbol"],
35
+ showarrow=False,
36
+ font=dict(size=20),
37
+ xref="x",
38
+ yref="y"
39
+ )
40
+ if comp["type"] == "Diode":
41
+ fig.add_annotation(
42
+ x=x,
43
+ y=y,
44
+ text="|" if comp["orientation"] == "reverse" else "",
45
+ showarrow=False,
46
+ font=dict(size=20),
47
+ xshift=10
48
+ )
49
+
50
+ # Draw connections
51
+ for connection in st.session_state.connections:
52
+ fig.add_trace(go.Scatter(
53
+ x=[connection[0][0], connection[1][0]],
54
+ y=[connection[0][1], connection[1][1]],
55
+ mode="lines",
56
+ line=dict(color="black", width=2)
57
+ ))
58
+
59
+ fig.update_layout(
60
+ xaxis=dict(visible=False, range=[0, 10]),
61
+ yaxis=dict(visible=False, range=[0, 10]),
62
+ margin=dict(l=0, r=0, t=0, b=0),
63
+ height=400
64
+ )
65
+ return fig
66
 
67
+ def analyze_circuit():
68
+ # Simplified circuit analysis (series only)
69
+ voltage = 0
70
+ current = 0
71
  results = []
72
 
73
+ if not st.session_state.circuit:
74
+ return pd.DataFrame()
75
+
76
+ # Find power source
77
+ source = next((c for c in st.session_state.circuit if c["type"] in ["AC Source", "DC Source"]), None)
78
+ if not source:
79
+ return pd.DataFrame()
80
+
81
+ # Calculate parameters
82
+ total_resistance = sum(c["value"] for c in st.session_state.circuit if c["type"] == "Resistor")
83
+ diode_drop = 0
84
+ for comp in st.session_state.circuit:
85
+ if comp["type"] == "Diode":
86
+ if comp["orientation"] == "forward":
87
+ diode_drop += DIODE_DROPS[comp["subtype"]]
88
+
89
+ if source["type"] == "DC Source":
90
+ voltage = source["value"] - diode_drop
91
+ current = voltage / total_resistance if total_resistance > 0 else 0
92
+ else:
93
+ # AC analysis would require time-based simulation
94
+ pass
 
 
 
 
 
95
 
96
+ return pd.DataFrame({
97
+ "Total Voltage": [voltage],
98
+ "Current": [current],
99
+ "Resistance": [total_resistance],
100
+ "Diode Drop": [diode_drop]
101
+ })
102
 
103
+ # Main UI
104
+ st.title("🔌 Visual Circuit Simulator")
105
+ st.markdown("Build your circuit by placing components and connecting them")
106
 
107
+ # Toolbox
108
+ with st.expander("🛠️ Component Toolbox"):
109
  col1, col2, col3 = st.columns(3)
110
  with col1:
111
+ comp_type = st.selectbox("Component Type", list(COMPONENTS.keys()))
112
  with col2:
113
  if comp_type in ["Resistor"]:
114
+ value = st.number_input("Value (Ω)", 1, 1000, 1000)
115
  elif comp_type in ["DC Source"]:
116
+ value = st.number_input("Voltage (V)", 1.0, 24.0, 5.0)
117
  else:
118
  value = None
119
  with col3:
120
  if comp_type == "Diode":
121
  subtype = st.selectbox("Diode Type", list(DIODE_DROPS.keys()))
122
+ orientation = st.selectbox("Orientation", ["forward", "reverse"])
123
  else:
124
  subtype = None
125
+ orientation = "forward"
126
 
127
+ if st.button("Add to Board"):
128
  st.session_state.circuit.append({
129
  "type": comp_type,
130
  "value": value,
131
+ "subtype": subtype,
132
+ "orientation": orientation,
133
+ "position": [5, 5]
134
  })
135
 
136
+ # Schematic Canvas
137
+ st.subheader("Circuit Board")
138
+ fig = draw_schematic()
139
+ st.plotly_chart(fig, use_container_width=True)
 
 
 
 
 
 
 
 
 
140
 
141
  # Simulation Controls
142
+ if st.button("▶️ Run Analysis"):
143
+ results = analyze_circuit()
144
+ if not results.empty:
145
+ st.subheader("🔍 Analysis Results")
146
+ st.dataframe(results)
147
+
148
+ # Waveform visualization
149
+ if "AC Source" in [c["type"] for c in st.session_state.circuit]:
150
+ st.subheader("📈 Waveform Visualization")
151
+ waveform_type = st.selectbox("Select Waveform Type", ["Sine", "Square", "Triangular"])
152
+ t = np.linspace(0, 0.05, 1000)
153
+ if waveform_type == "Sine":
154
+ wave = np.sin(2 * np.pi * 50 * t)
155
+ elif waveform_type == "Square":
156
+ wave = square(2 * np.pi * 50 * t)
157
+ else:
158
+ wave = sawtooth(2 * np.pi * 50 * t)
159
+
160
+ fig_wave = go.Figure()
161
+ fig_wave.add_trace(go.Scatter(x=t, y=wave))
162
+ st.plotly_chart(fig_wave)
163
+ else:
164
+ st.error("Invalid circuit configuration")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
+ # Instructions
167
  with st.expander("❓ How to use"):
168
  st.markdown("""
169
+ 1. **Add Components**:
170
+ - Select component type and parameters
171
+ - Click 'Add to Board'
172
+ - Drag components on the canvas (positioning not fully implemented)
 
173
 
174
+ 2. **Connect Components**:
175
+ - Click on component terminals to connect them
176
+ - Create complete circuits with power sources
177
 
178
+ 3. **Run Analysis**:
179
+ - Get voltage, current, and resistance values
180
+ - View waveforms for AC circuits
 
181
  """)