It could happen that the mains voltage fluctuates because of voltage collapses. Nevertheless, the resulting signal has to be stable enough so that the fluctuations don't influence the final result. A usual voltage divider with 2 resistors wouldn't achieve that. Therefore, adding an additional source from the microcontroller and resistor will make the signal more resistant to voltage flucutations. Furthermore, the microcontroller can only "read" positive voltages. The additional DC voltage source lifts the sine to an only positive range.
In [1]:
from IPython.display import Image
Image(filename='circuit.png')
Out[1]:
In [2]:
# %matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from IPython.display import HTML, display
In [3]:
# For tables
def tableit(data):
display(HTML(
'<table><tr>{}</tr></table>'.format(
'</tr><tr>'.join(
'<td>{}</td>'.format('</td><td>'.join(str(_) for _ in row)) for row in data)
)
))
In [2]:
U0 = 17.1 # mains voltage in Volt (transformed from 230 V ~ to 17.1 V ~)
U_B = 5 # DC voltage from an external supply in Volts
R1 = 10000 # Ohm
R2 = 2400 # Ohm
R3 = 3000 # Ohm
f = 50 # Hz
fs = 44100 # Hz
duration = 0.06 # Duration of plots in seconds
In [5]:
t = np.arange(0, duration, 1 / fs)
In [6]:
I1 = (U0 * np.sin(2 * np.pi * f * t) * R2 + U_B * R1) / (R1 * (R2 + R3) + R2 * R3)
I2 = (U0 * np.sin(2 * np.pi * f * t) * R3 - U_B * (R1 + R3)) / (R1 * (R2 + R3) + R2 * R3)
I0 = I1 + I2
In [7]:
plt.plot(t * 1000, I0 * 1000, label="I0")
plt.plot(t * 1000, I1 * 1000, label="I1")
plt.plot(t * 1000, I2 * 1000, label="I2")
plt.title("Currents")
plt.ylabel("I / mA")
plt.xlabel("t / ms")
plt.legend(loc='upper left', bbox_to_anchor=(1.1, 0.6))
plt.grid()
plt.show()
In [8]:
U_R1 = I0 * R1
U_R2 = I2 * R2
U_R3 = I1 * R3
signal = U_R3 # U_R3 == signal voltage
In [9]:
plt.plot(t * 1000, U_R1, label="U_R1")
plt.plot(t * 1000, U_R2, label="U_R2")
plt.plot(t * 1000, signal, label="signal")
plt.title("Voltages")
plt.ylabel("U / V")
plt.xlabel("t / ms")
plt.legend(loc='upper left', bbox_to_anchor=(1.1, 0.6))
plt.grid()
plt.show()
In [10]:
signal_max = np.max(signal)
signal_min = np.min(signal)
In [11]:
signal_pp = signal_max - signal_min
In [12]:
offset = (signal_max + signal_min) / 2
In [13]:
tableit([["signal_max / V", "signal_min / V","signal_pp / V", "Offset / V"],
[np.around(signal_max, 2), np.around(signal_min, 2), np.around(signal_pp, 2), np.around(offset, 2)],
])
In [14]:
plt.plot(t * 1000, signal, label="Signal Voltage")
plt.title("Signal Voltage")
plt.ylabel("U / V")
plt.xlabel("t / ms")
plt.axhline(y=offset, color='r', linestyle='-', label='Offset')
plt.legend(loc='upper left', bbox_to_anchor=(1.1, 0.6))
plt.ylim(-0.1, signal_max + 0.2)
plt.grid()
plt.show()
In [15]:
voltage_range = np.arange(U0 - 8, U0 + 8 ,0.1) # mains voltage fluctuations
I1_DC = (voltage_range * R2 + U_B * R1) / (R1 * (R3 + R2) + R3 * R2)
signal_DC = I1_DC * R3
In [16]:
plt.plot(voltage_range, signal_DC)
plt.title('Mains voltage fluctuations and the effect on the signal')
plt.xlabel('Mains Voltage / V')
plt.ylabel('Signal Voltage (DC) / V')
plt.grid()
plt.show()
The computation shows a good stability of the signal voltage if the mains voltage fluctuates. A change of 1V in the mains voltage results just in an approx. 100mV deviation of the signal.
In [17]:
Image(filename='schmitt.png')
Out[17]:
In [18]:
Image(filename='schmitt_drawing.png')
Out[18]:
In [19]:
R4 = 10000 # Ohm
R5 = 34800 # Ohm
R6 = 10000 # Ohm
R7 = 10000 # Ohm
U_aH = U_B
U_aL = 0
In [20]:
U_ref = U_B * R6 / (R6 + R7)
In [21]:
U_High = (R4 / (R4 + R5) * U_aL - U_ref) / (R4 / (R4 + R5) -1)
In [22]:
U_Low = (R4 / (R4 + R5) * U_aH - U_ref) / (R4 / (R4 + R5) -1)
In [23]:
tableit([["U_ref / V", "U_Low / V","U_High / V"],
[U_ref, np.around(U_Low, 2), np.around(U_High, 2)],
])
In [24]:
def hyst(x, th_lo, th_hi, initial = False):
hi = x >= th_hi
lo_or_hi = (x <= th_lo) | hi
ind = np.nonzero(lo_or_hi)[0]
if not ind.size: # prevent index error if ind is empty
return np.zeros_like(x, dtype=bool) | initial
cnt = np.cumsum(lo_or_hi) # from 0 to len(x)
return np.where(cnt, hi[ind[cnt-1]], initial)
In [25]:
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
ax.add_patch(patches.Rectangle((U_Low, 0), U_High - U_Low, U_B, fill=False))
ax.set_title('Hysteresis')
ax.set_xlim([0,U_Low + 2]);
ax.set_ylim([0, U_B + 1]);
ax.set_xlabel('Ue / V')
ax.set_ylabel('Ua / V')
ax.arrow(U_High, U_B / 2 , 0, 0, head_width=0.2, head_length=0.3, fc='k', ec='k')
ax.arrow(U_Low, U_B / 2 , 0, -0.01, head_width=0.2, head_length=0.3, fc='k', ec='k')
ax.arrow((U_High + U_Low) / 2, U_B - 0.03 , -0.001, 0, head_width=0.2, head_length=0.3, fc='k', ec='k')
ax.arrow((U_High + U_Low) / 2, 0 , 0.001, 0, head_width=0.2, head_length=0.3, fc='k', ec='k')
plt.grid()
plt.show()
In [26]:
h1 = hyst(signal, U_Low, U_High)
plt.plot(t * 1000, signal, label='Signal Voltage')
plt.plot(t * 1000, U_B * h1, label='U_a')
plt.axhline(y=U_Low, color='k', linestyle='-', label='U_Low')
plt.axhline(y=U_High, color='r', linestyle='-', label='U_High')
plt.axhline(y=U_ref, color='y', linestyle='-', label='U_ref')
plt.title('Schmitt Trigger Result')
plt.xlabel('t / ms')
plt.ylabel('U / V')
plt.legend(loc='upper left', bbox_to_anchor=(1.1, 0.6))
plt.ylim([0, U_aH + 0.5])
plt.grid()
plt.show()