Premessa: Un amplificatore in classe A è un amplificatore che dissipa la stessa potenza a prescindere che vi sia applicato un segnale in ingresso oppure no. In protica un amplificatore in classe A da 5W consumerà sempre 5 watt dal momento che viene alimentato anche se all’ingresso non applicherete nessun segnale. Per questo motivo non si usa quasi mai negli amplificatori audio di potenza.
.
Ogni volta che inizio ad imparare un nuovo linguaggio di programmazione sorge il problema di come mettere in pratica quello che ho imparato. O almeno una parte di questo.
Avendo una fantasia che si spegne quando serve, risolvo ‘brillantemente’ applicando una parte di quanto studiato a scuola in epoca remota nelle ore di Elettronica e cioè:
“BJT: progetto della rete di polarizzazione di un preamplificatore monostadio in bassa frequenza in classe A”.
Il progetto è affrontato in maniera semplificata dato che il suo scopo è quello di applicare i concetti della programmazione, gli statements, la sintassi e quant’altro e possibilmente fissarli nella memoria.
Il programma è scritto in Python e non usa le classi così da essere di più semplice comprensione per la maggioranza.
Perché Python? Perché è simile al Basic, che mi ha guidato negli anni ’80 in un percorso da programmatore per approdare poi al Fortran. Non si compila e quindi è utile per cose veloci e poco impegnative che ci si può trovare a dover svolgere a sostegno di altre più complesse. Mi è sembrato utile come un coltellino svizzero che ti aiuta a risolvere i problemi contingenti del momento.
Oltre a ciò ha usa meno segni di interpunzione e caratteri speciali. Possiamo visualizzare un esempio preso da Internet (magari anche un po’ di parte) contrapponendolo al C++ che pure è un ottimo linguaggio di programmazione:
An example of C++ code:
#include #include using namespace std; int main() { string name; cin >> name; cout << "Good evening, " << name << endl; return 0; }
And here is an example of Python code:
name = input() print("Good evening, " + name)<code></code>
.
Lo schema
Nello schema presentato possiamo vedere che sono presenti i due principali resistori di polarizzazione, Rb ed Rc più il resistore di emettitore Re che ha funzione di stabilizzazione del punto di riposo per le variazioni del deltaVbe del transistor. Tale variazione è funzione della temperatura. Questa variazione non è l’unica dato che pupossono variare anche l’ICB0, ed il BETA. Oltre a questo bisognerebbe tenere anche conto della dispersione delle caratteristiche del semiconduttore, ma tutto questo va oltre l’obiettivo del nostro esercizio di programmazione.
In aggiunta abbiamo anche calcolato il valore dei condensatori di accoppiamento in ingresso ed in uscita oltre a quello di disaccoppiamento in alternata sulla resistenza di emettitore. E’ sottinteso che si useranno transistor al silicio e non i vecchi ed obsoleti transistor al germanio e di tipo NPN.
.
A cosa mi può servire?
Può essere utile a volte preamplificare un microfono, ad esempio per un robot che deve direzionarsi in base al suono. Se l’amplificazione di uno stadio non fosse sufficiente ad avere in uscita una ampiezza di segnale consona, se ne possono mettere in cascata due o più. Lo stesso circuito abbinato ad un multivibratore bistabile può essere usato per spegnere ed accendere luci con il battito delle mani. E poi tante altre cose che la fantasia può immaginare.
.
I parametri di progetto
I parametri richiesti all’avvio del programma sono in prima istanza, se si vuole applicare la resistenza di emettitore oppure no dato che questa serve solo per la stabilizzazione del punto di riposo. Poi chiede la frequenza minima da amplificare. E’ bene non usare valori assurdi tipo 2 Hz perché questo comporterebbe condensatori di accoppiamento dal valore eccessivo e non è detto che funzioni sempre.
Tenete presente che questo circuito potrebbe arrivare ad amplificare anche frequenze molto alte, oltre 300 KHz. Quindi se volete potete mettere in ingresso o in uscita un filtro passa-basso di tipo RC per tagliare oltre i 20 KHz.
Fatto questo verrà chiesto a che tensione viene alimentato il circuito, il guadagno in tensione del transistor, la corrente di collettore richiesta e la Vce richiesta. Questi parametri si pod+ssono trovare sui datasheet del transistor usato.
.
Valori risultanti
Come risultati di uscita avremo banalmente i resistori di base, di collettore e di emettitore oltre ai condensatori di disaccoppiamento. Quelli in ingresso ed uscita servono (ma questo già lo saprete) per evitare che eventuali tensioni indotte dai circuiti in ingresso ed uscita spostino il punto di riposo del nostro circuito lasciando passare solo la componente alternata del segnale. Il condensatore sulla Re serve per non far vedere questa al segnale in alternata (ne abbassa il valore ad un decimo).
Vengono stampati anche altri valori intermedi, ma ci serviranno in una implementazione futura.
Come si può vedere dal primo RUN, tutti i valori dei componenti non sono normalizzati. Non hanno cioè valori standard, quelli dovete deciderli voi scegliendo il valore standard più vicino. Per i meno esperti consiglio di usare resistori al 2% o 1%. Gli altri potranno scegliere valori al 5%. Questo perché valori non scelti bene potrebbero cambiare troppo il punto di riposo del transistor BJT. In futuro si implementerà anche questa funzione, magari usando delle classi.
.
Il Programma
Il programma è semplice da capire. E’ formato da tre funzioni principali richiamate dal main-program.
inputParameter() come dice il nome si occupa di chiedere i parametri di progetto e di normalizzarli prima dell’invio alla funzione:
calculateValues() che effettua tutti (e solo) i calcoli per determinare i valori dei componenti necessari a polarizzare il transistor e determinare i valori dei condensatori di disaccoppiamento. Nel caso non venga richiesta la presenza della Re non effettuerà i calcoli non necessari.
printValues() infine stampa tutti i risultati ottenuti, finali ed intermedi. I valori vengono stampati in notazione anglosassone, quindi le virgole diventano punti ed i punti diventano virgole.
Oltre a queste funzioni principali, sono presenti altre funzioni accessorie come resPower() e condVoltage() che scelgono la potenza di dissipazione dei resistori e la tensione di funzionamento dei condensatori elettrolitici.
.
Esecuzione del Programma
Aprire un programma di editig per script come Notepad++ (Windows) o Gedit (Linux) e incollarci dentro il programma presente alla fine di questo articolo. Salvarlo col nome PreClasse_A.py nella directory preferita.
Per mandare in esecuzione il programma sotto Linux basta andare nella directory dove è il nostro programma e digitare:
[greybear@localhost ~]$01 python PreClasse_A.py
Mentre sotto Windows bisognerà installare prima Python3 ricordandosi di far aggiornare in automatico il PATH con i percorsi di python. Poi si andrà nella cartella del nostro programma e si digiterà:
C:\dir\…\dir\python.exe PreClasse_A.py
.
Listato in Python
# Calcolo per la polarizzazione statica di un preamplificatore monostadio BF a BJT
# greybear (@officinecibernetiche.net) 16/03/2021 Rev. 1.1
''' Calcolo delle resistenze di polarizzazione di un amplificatore
monostadio in bassa frequenza a BJT. Vengono richiesti i seguenti
parametri:
Tensione di alimentazione,
corrente di collettore (Ic),
guadagno statico (hfe)
e tensione collettore-emettitore (Vce).
Dati questi parametri verranno calcolate le resistenze di
polarizzazione di base (Rb), di collettore (Rc) e su richiesta
anche la resistenza di emettitore (Re) con relativo condensatore
di disaccoppiamento. Si suppone che il BJT sia al silicio e di
tipo NPN, quindi con negativo a massa.
I valori risultanti sono stampati secondo la notazione angloassone. '''
import math
def inputParameter():
''' Inserendo i parametri di progetto si avrà in uscita il valore delle
resistenze di polarizzazione. Verranno calcolati anche i condensatori di
accoppiamento in ingresso ed in uscita in funzione della frequenza minima
del segnale audio da amplificare.
'''
i = 0
Vce = 100
Vcesat = 0.5
# ingresso dati di progetto
print('\n======================================')
print ('Parametri di progetto:')
print('---------------------------------------')
Vcc = float(input('Vcc (1-50V) = '))
hfe = int(input('hfe = '))
Ic = float(input('Ic (mA) = '))
while Vce >= (Vcc - Vcesat):
#if (Vce >= Vcc) and i == 1:
print('Vce deve sufficientemente inferiore a Vcc-Vcesat')
Vce = float(input('Vce (V) = '))
#i = 1
# normalizazione parametri di progetto
Vcc = float(Vcc)
hfe = int(hfe)
Ic = float(Ic) * pow(10, -3)
Vce = int(Vce)
return Vcc, hfe, Ic, Vce
def resPower(RmW):
''' Calcola la dissipazione della resistenza con parametro di sicurezza pari a 1.5 '''
valSic = 1.5
W = ''
if (RmW * valSic) < 250:
W = '1/4 W'
elif (RmW * valSic) < 500:
W = '1/2 W'
elif (RmW * valSic) < 1000:
W = '1 W'
elif (RmW * valSic) < 2000:
W = '2 W'
elif (RmW * valSic) < 5000:
W = '5 W'
else:
W = 'maggiore di 5 W'
return W
def condVoltage(Vcc):
''' Calcola la tensione di lavoro degli elettrolitici '''
if Vcc < 6.0:
vCe = '6 V'
elif Vcc < 12.0:
vCe = '12 V'
elif Vcc < 25.0:
vCe = '25 V'
elif Vcc < 50.0:
vCe = '50 V'
elif Vcc < 100.0:
vCe = '100 V'
else:
vCe = 'maggiore di 100 V'
return vCe
def calculateValues(Vcc, Vce, Vbe, hfe, Re, Ic, RE, lowFt):
# calcolo resistenze di polarizzazione statica
Ce = 0
vCe = 0
deltaVbe = 0.22 # per ora la fissiamo arbitrariamente
Ib = Ic / hfe
if RE.lower() == 'si':
# Re per variazione termica del Vbe
Re = 15 * deltaVbe / (Ic + Ib) # 10_20*DeltaVbe/Ic+Ib
reattCe = Re / 10
Ce = 1 / (2 * math.pi * lowFt * reattCe)
vCe = condVoltage(Vcc)
Rc = (Vcc - Vce - Re * Ic) / Ic
Rb = (Vcc - Vbe) / Ib
print('Vbe (V) =', Vbe)
if Re == 0:
RR = 'not available'
We = 0
else:
RR = int(Rb / Re)
RemW = Re * pow((Ic + Ib), 2) * pow(10, 3)
We = resPower(RemW)
RbmW = Rb * pow(Ib,2) * pow(10,3)
RcmW = Rc * pow(Ic,2) * pow(10,3)
Wb = resPower(RbmW)
Wc = resPower(RcmW)
Rx = (hfe + 1) * (26 * pow(10, -3) / (Ic + Ib))
Ry = Rb
rIngresso = Rx * Ry / (Rx + Ry)
Cinput = 1 / (2 * math.pi * rIngresso * lowFt)
return Ib, Rb, Rc, Re, Ce, vCe, RR, Wb, Wc, We, Cinput
def printValues(Ib, Rb, Rc, Re, vCe, RR, Wb, Wc, We, Cinput):
# stampa risultati di calcolo
print('\n======================================')
print('Parametri intermedi:')
print('---------------------------------------')
print('Ib =', '{:.3f}'.format(Ib * pow(10, 3)), 'mA')
print('Rb/Re =', RR)
print('\n======================================')
print('Valore componenti per la polarizzazione')
print('---------------------------------------')
print('Rc =', '{:,}'.format(int(Rc)), 'ohm', Wc)
if Rc < 0:
print('Alcuni parametri di progetto sono incoerenti (Es. Vce, Re)')
quit()
print('Rb =', '{:,}'.format(int(Rb)), 'ohm', Wb)
if Re != 0 or Ce != 0:
print('Re =', '{:,}'.format(int(Re)), 'ohm', We)
print('Ce =', round(Ce * pow(10, 6)), 'uF', vCe)
print('C in/out =', round(Cinput * pow(10, 6)), 'uF', vCe)
# MAIN PROGRAM
if __name__ == '__main__': # execute only as standalone, not as imported module
print(inputParameter.__doc__)
# parametri fissi
Vbe = 0.6
Re = 0
RE = input("E' presente la R sull'emettitore? si/no ")
RE = RE.strip()
lowFt = int(input('Frequenza di taglio inferiore? (20-1000 Hz) '))
Vcc, hfe, Ic, Vce = inputParameter()
Ib, Rb, Rc, Re, Ce, vCe, RR, Wb, Wc, We, Cinput = calculateValues(Vcc, Vce, Vbe, hfe, Re, Ic, RE, lowFt)
printValues(Ib, Rb, Rc, Re, vCe, RR, Wb, Wc, We, Cinput)