#import necessary libraries
import matplotlib.pyplot as plt
import numpy as np
import math
from scipy.optimize import curve_fit
Metingen & constanten
# Measurements:
R = 9962.9 #waarde gebruikte weerstand in Ohm
#Dit is ongeveer gelijk aan 1% van de interne weerstand van de Voltmeter.
#De weerstand had als label 10kohm, een meting met multimeter leverde deze waarde
q = -1.602*10**-19 #elementaire lading in Coulomb
T = 12+273 #temperatuur van diode tijdens experiment in Kelvin
n = 2 #idealiteits factor, voor de door ons gebruikte halfgeleider gelijk aan 2
#gemeten data Ve is de voltspanning, en Vr is de gemeten spanning over de weerstand.
#Beide spanningen gemeten in Volt
Ve = np.array([0.01,0.02, 0.013,0.22,0.31,0.53,0.71,1.31,1.66,2.72,3.04,4.24,5.44,6,6.52,
0.07,0.09,0.13,0.19,0.26,0.33,0.39,0.45,0.49,0.53
])
Vr = np.array([0.006*10**-3,0.01*10**-3,0.308*10**-3,2.187*10**-3, 11.334*10**-3,114.015*10**-3,0.2572,0.8040,1.137,2.1715,2.4756,
3.657,4.8403,5.4026,5.9201, 0.077*10**-3, 0.148*10**-3,0.355*10**-3,1.604*10**-3, 5.113*10**-3, 16.116*10**-3,
35.429*10**-3,67.542*10**-3,91.558*10**-3,121.50*10**-3
])
Outliers & data management
#In de arrays met metingen staan de metingen met verschillende onzekerheden door elkaar heen.
#Om de arrays op te delen in twee arrays moeten de metingen met dezelfde onzekerheid achter elkaar staan.
#onderstaande code verwijderd een sectie van beide arrays en plaatst dezelfde sectie achter aan de array
#zodat de arrays ge-sliced kunnen worden op een manier zodat
#alle datapunten met dezelfde meetonzekerheid in hetzelfde resulterende array zitten.
begin = 6 #begin en eind punt van verplaatste sectie
end = 15
plt.scatter(Ve,Vr) #zie laatste comment van deze cell.
Vrinj = Vr[begin:end] #selecteer gekozen sectie en verwijder het, plaats het vervolgens weer achteraan de array.
Vr = np.delete(Vr,np.s_[begin:end])
Vr = np.append(Vr,Vrinj)
Veinj = Ve[begin:end] #herhaal voor andere array met metingen.
Ve = np.delete(Ve,np.s_[begin:end])
Ve = np.append(Ve,Veinj)
plt.yscale('log')
plt.scatter(Ve,Vr) #deze scatter plot is om na te gaan of alle datapunten nog op dezelfde positie liggen,
#Te zien is dat alle data punten over elkaar liggen. Dit is de bedoeling.
#Er zijn geen datapunten verschoven tijdens de herindeling van de arrays.
plt.show()
#We hebben besloten de derde meting te verwijderen, dit was een duidelijke outlier, veroorzaakt door een foute aflezing van de meet apparatuur.
#We konden hiervoor geen gebruik maken van het chauvents criterium omdat er slechts 1 meting van Vr is per Ve en er dus geen gausische verdeling is.
Ve = np.delete(Ve,2)
Vr = np.delete(Vr,2)
#De metingen moeten opgedeeld worden in twee delen omdat vanaf datapunt 15 de onzekerheid in Vr veranderd.
#Het display van de multimeter gaat op dat moment automatisch over van mV naar dV.
#De arrays geassocieerd met mV worden 1 genoemd en geassocieerd met dV worden 2 genoemd.
print(len(Vr))
Vr1 = Vr[:15]
Vr2 = Vr[15:]
Ve1 = Ve[:15]
Ve2 = Ve[15:]
print(Vr1,Vr2)
print(Ve,Vr)
#Data processing and analysis:
Vd = Ve-Vr #naar de wetten van kirchoff wordt met deze formule de spanning over de diode berekend
Id = Vr/R #aan de hand van de wet van Ohm wordt de stroom door de diode berekend.
Ir = Id
#voor de error bars wordt hetzelfde uitgevoerd maar dan per apart array:
Vd1 = Ve1-Vr1
Id1 = Vr1/R
Ir1 = Id1
Vd2 = Ve2-Vr2
Id2 = Vr2/R
Ir2 = Id2
Onzekerheden
#onzekerheid in gemeten weerstand:
u_R = (0.002/100)*R+0.005 #gegeven door datasheet van de agilent multi meter. Deze is altijd constant omdat het slechts een meting is.
#onzekerheid in bronspanning Ve, deze is altijd hetzelfde
#maar om de error bars goed weer te geven moet ook deze array opgesplitst worden.
#de onzekerheden zijn verkregen uit de datasheet van de handheld multimeter
u_Ve1 = Ve1*7*10**(-3)+0.01
u_Ve2 = Ve2*7*10**(-3)+0.01
#De onzekerheid in de spanning over de weerstand verschilt voor array 1 en 2.
#deze onzekerheden zijn verkregen uit de datasheet van de agilent multi meter.
u_Vr1 = Vr1*3*10**(-5)+4*10**(-6)
u_Vr2 = Vr2*1.5*10**(-5)+10**(-4)+4*10**(-5)
#Met deze basis onzekerheden kunnen de onzekerheden in berekende waarden Id en Vd, de stroom en spanning over de diode berekend worden.
#Zie onderstaande cell voor de formule van deze grootheden
#Ook deze onzekerheden worden opgedeeld in twee arrays.
u_Vd1 = np.sqrt(((u_Ve1)**2)+(u_Vr1)**2)
u_Vd2 = np.sqrt(((u_Ve2)**2)+(u_Vr2)**2) #gegeven door standaard formule uit het dictaat te gebruiken van optellen meerdere variabelen.
u_Id1 = Id1*np.sqrt(((u_Vr1/Vr1)**2)+(u_R/R)**2)
u_Id2 = Id2*np.sqrt(((u_Vr2/Vr2)**2)+(u_R/R)**2) #gegeven door kwadratisch optellen van de relatieve onzekerheden.
print(u_Id1,Id1,u_Vd1,Vd1)
#om een onzekerheid van de volledige array te krijgen worden de onzekerheids array1 en 2 achter elkaar gevoegd.
u_Id = np.append(u_Id1,u_Id2)
u_Vd = np.append(u_Vd1,u_Vd2)
def f(V,a,b):
return a*(np.exp(b*V)-1)
popt, pcov = curve_fit(f,Vd,Id,p0=[2.6643716530399914e-09,20.387516506496972],sigma=u_Id) # curve fit om de constante van stefan boltzmann te berekenen.
a = popt[0] #sperstroom
b = popt[1] #deze variabele b is gelijk aan -q*V_d / n*k_B*T met K_b de constante van Boltzmann
perr = np.sqrt(np.diag(pcov))
u_a = perr[0]
u_b = perr[0]
V = np.linspace(0,0.601,1000)
print('fit waarde a:',a,'onzekerheid in fit waarde a:',u_a)
print('fit waarde b:',b,'onzekerheid in fit waarde b',u_b)
#Data processing and analysis:
#vormgeving van een dataplot met fit functie.
plt.yscale('log') #voor deze plot wordt gebruik gemaakt van een logaritmische schaal.
plt.ylabel('$Id (A)$')
plt.xlabel('$Vd (V)$')
plt.plot(Vd1,Id1, 'k.',linestyle='',label='Vr gemeten in mV')
plt.plot(Vd2,Id2, 'k.',linestyle='',label='Vr gemeten in dV')
plt.plot(V,f(V,a,b),'r',label='fit: a=%.2E, b=%.2E' % tuple(popt))
plt.errorbar(Vd1,Id1,u_Id1,u_Vd1,linestyle='',fmt='g')
plt.errorbar(Vd2,Id2,u_Id2,u_Vd2,linestyle='',fmt='g')
plt.legend()
plt.show()
#een tweede curve fit funtie om de richtingscoefficient te bepalen van de asymptoot van de datapunten.
def f1(V,a,b):
return a*(np.exp(b*V))
popt, pcov = curve_fit(f,Vd,Id) # curve fit om de constante van stefan boltzmann te berekenen.
a1 = popt[0] #sperstroom
b1 = popt[1] #deze variabele b is gelijk aan -q*V_d / n*k_B*T met K_b de constante van Boltzmann
perr1 = np.sqrt(np.diag(pcov))
u_a1 = perr[0]
u_b1 = perr[0]
V = np.linspace(-0.0001,0.601,1000)
#Data processing and analysis:
#vormgeving van een dataplot met fit functie.
plt.yscale('log') #voor deze plot wordt gebruik gemaakt van een logaritmische schaal.
plt.ylabel('$Id (A)$')
plt.xlabel('$Vd (V)$')
plt.plot(Vd1,Id1, 'k.',linestyle='',label='Vr gemeten in mV')
plt.plot(Vd2,Id2, 'k.',linestyle='',label='Vr gemeten in dV')
plt.plot(V,f1(V,a1,b1),'k-',color = 'grey',label='fit: a=%.2E, b=%.2E' % tuple(popt))
plt.errorbar(Vd1,Id1,u_Id1,u_Vd1,linestyle='',fmt='g')
plt.errorbar(Vd2,Id2,u_Id2,u_Vd2,linestyle='',fmt='g')
plt.plot(V,f(V,a,b),'r',label='fit: a=%.2E, b=%.2E' % tuple(popt))
plt.legend()
plt.savefig('plot kB.pdf')
plt.show()
kB = -q/(n*b*T) #berekening constante van boltzmann uit waarde van b.
#onzekerheid in kB wordt gegeven door de onzekerheid in b te vermenigvuldigen met de partieel afgeleide naar b van de formule voor kB
u_kB = abs(u_b*q*(1/(n*T*b**(-2))))
print('constante van Boltzmann:',kB,'onzekerheid in de meting van de constante:',u_kB)
#Data processing and analysis:
plt.yscale('log') #voor deze plot wordt gebruik gemaakt van een logaritmische schaal.
plt.ylabel('$Id (A)$')
plt.xlabel('$Vd (V)$')
plt.plot(Vd1,Id1, 'k.',linestyle='',label='Vr gemeten in mV')
plt.plot(Vd2,Id2, 'k.',linestyle='',label='Vr gemeten in dV')
plt.plot(V,f1(V,a1,b1),'r',label='fit: a=%.2E, b=%.2E' % tuple(popt))
plt.errorbar(Vd1,Id1,u_Id1,u_Vd1,linestyle='',fmt='g')
plt.errorbar(Vd2,Id2,u_Id2,u_Vd2,linestyle='',fmt='g')
plt.legend()
plt.show()
#Calculations of e.a. measurement uncertainties, and providing final answers.
#strijdigheidsanalyse, het verschil tussen de twee waarden dient niet groter te zijn dan twee maal de onzekerheid kwadratisch opgeteld.
#literatuur waarde van kB: 1.380649·10**{−23}
kB_lit = 1.38064852*10**(-23)
u_kB_lit = 0.00000079*10**(-23) #de constante van boltzman is sinds 2019 een exacte waarde gedefineerd als bovenstaande
delta_kB = abs(kB-kB_lit) #het verschil tussen de gevonden waarde en literatuur waarde
u_double = 2*np.sqrt(u_kB**2+u_kB_lit**2)
if delta_kB>u_double:
print('de waarden komen niet overeen')
else:
print('wel')
proc = (1.38064852-1.38129)/1.38064*100
print(proc,'%')