HobbyElectro

Petrescu Cristian . Un produs Blogger.

vineri, 3 martie 2017

Sursa de alimentare cu Arduino (1)

0 comentarii | Read more...

Salutare prieteni !

In sfarsit e gata. Ma rog, in proportie de 80%, dar functioneaza. Mi-a mancat ceva timp pana am pus totul cap la cap, dar in final sunt multumit: am construit prima mea sursa de alimentare digitala

Dap. Am facut-o si sunt tare mandru de rezultat. Asadar, puteti vedea rezultatul provizoriu in clipul de mai jos:





Functionarea...


Mai jos aveti schema electronica: 

Schema electronica

    Dupa cum se observa stabilizarea se invarte in jurul "batranului" LM317, doar ca este parte buclei de reactie negativa a amplificatorului operational OPA 241A. La randul sau amplificatorul operational primeste tensiunea pe intrarea neinversoare de la potentiometrul digital MCP4251. 
Rezistentele din bucla de reactie R5 si R6  determina amplificarea. Cum? Sa facem putina matematica.

Se stie ca impedanta de intrare a amplificatoarelor operationale este foarte, foarte mare, si din acest motiv curentii care circula la intrari pot fi aproximativ cu zero. De asemenea se mai cunoaste si faptul ca tensiunea aplicata oricarei intrari se regaseste identic si la cea de-a doua.

Asadar, caderea de tensiune pe rezistenta R6, sa ii zicem U1, va fi exact tensiunea aplicata la intrarea neinversoare. Curentul prin acesta rezistenta va fi:

I=U1/R6.

Cum curentul care circula prin intrarea inversoare este ffff mic poate fi aproximat cu zero. Astfel acelasi curent I va circula si prin R5. Caderea de tensiune pe aceasta va fi - U2: 

U2=I x R5=(U1/R6) x R5

aranjand un pic avem:

U2=U1 x (R5/R6)

Asadar tensiunea de la iesirea stabilizatorului de tensiune, Ue,  va fi U1+U2, adica 

Ue = U1+U1(R5/R6) sau, dupa factor comun :)))

Ue=U1+(1+R5/R6) Ta-dam !!!

Deci, dupa cum se  observa, tensiunea de la iesirea stabilizatorului nu depinde decat de valoarea tensiunii de la intrarea neinversoare si de raportul rezistetelor R5 si R6. In cazul de fata valoarea tensiunii de iesire va fi  U1x3.13V. 

Buuuun! Tensiunea U1 este furnizata de potentiometrul digital U3 pe pinul 9 (cursorul potentiometrului). Dar cum functioneaza acest potentiometru? 

In estenta nu este altceva decat o retea de rezistoare:


      In imaginea de mai sus se observa modul in care este aranjata reteaua : rezistenta totala, intre punctele A-B este 10 Kohmi. Cum rezolutia este de 8 biti rezulta un numar maxim de 256 de valori, incluzand valoarea de 0 ohmi . In cazul de fata "pasul" este de aproximativ 39ohmi, neincluzand Rw (rezistenta cursorului).

      Programarea potentiometrului se face utilizand protocolul SPI si in esenta este foarte simpla: se transmite adresa potentiometrului pe care dorim sa il controlam si valoarea la care vrem sa il setam (0=0V si 255=5V).

    Dupa cum ziceam, cursorul potentiometrului este conectat direct la intrarea neinversoare a amplificatorului operational, deci putem amplifica o tensiune cuprinsa intre 0 si 5v. Valoarea maxima a tensiunii de iesire, Ue, (in aceasta configuratie) fiind 5x3.13=15.65V.

Controlul intregii "improvizatii" se realizeaza cu ajutorul "minunatului" convertor ADC ADS1115. Acesta are rolul de a "citi" valorile tensiunilor in urmatoarele puncte:
  • Tensiunea Vcc (5V) de la alimentarea potentiometrului - A3;
  • Tensiunea de la intrarea neinversoare - A0;
  • Tensiunea de la intrarea inversoare - A1;
  • Tensiunea de iesiere, prin intermediul divizorului de tensiune R2-R4 - A2.
In functie de valorile citite se seteaza tensiunea de iesiere ceruta.

    Un ultim cuvant aici: curentul prin stabilizator, LM317, este limitat la aproximativ 70 de mA. Cand curentul prin rezistorul R1 depaseste aceasta valoare tranzistorul Q1 se deschide comportandu-se ca un generator de curent.


Realizarea practica...

Montajul l-am realizat sub forma unui shield pentru Arduino Uno. Cum a iesit (mai bine sau mai rau :) ) puteti vedea in pozele de mai jos:












Controlul...

Pentru partea de control am scris un program in Python. Nu este prea mult de zis aici poza vorbeste de la sine:


    In esenta programul va scana toate porturile seriale disponibile dupa care utilizatorul se va conecta la portul lui Arduino. Dupa conectare se pot alege valori standard ale tensiuni 4.5, 5 etc sau se pot introduce manual in caseta de text "Custom Voltage". Programul va trimite datele luiArduino care la randul sau va trece la a seta tensiunea in mod corespunzator. Dupa setare Arduino va transmite in mod constant valorile tensiunilor citite de catre ADC.

To do list...

Dupa cum am zis si la inceputul articolului proiectul nu este 100% terminat. Mai trebuie facuta partea de alimentare: traf, punte, filtru, partea de putere: introdus tranzistorul in circuit si in sfarsit partea cea mai grea: o carcasa.


Cam atat pentru azi. Sa auzim de bine. Nu va sfiiti sa lasati un comentariu!





sâmbătă, 25 februarie 2017

Placa de teste pentru Arduino

0 comentarii | Read more...


Salutare tuturor !

     Urasc firele, cablurile, jumperii si breadboard-urile. De multe ori o idee se pierde fiindca gandul de a intinde fire, conectori si tot felul de alte sarmulite ma face de obicei sa ma las pagubas. 

     De foarte mult timp mi-am facut tot felul de planuri despre cum ar trebui sa arate o placa de teste cu strictul necesar pentru a putea simula diferite situatii intalnite in practica. Nu am avut niciodata timp sa ma asez la calculator si sa concep una, asa ca m-am multumit sa intind firele pe breadboard sau dupa cum ati observat (poate) sa concep mici module care sa mai aline chinul firelor. 

    Pana cand... pana cand am cautat un bug intr-un program care implementa senzorul ds18B20 intr-un termostat mai special. Totul facut corect, ca la carte - dar pe breadboard. Si totusi nu functiona. Probabil ca ati patit-o si voi. Contact imperfect. Si atunci m-am hotarat: voi face o placa de teste cu tot dichisul. 
     Dupa cativa ani de experienta in "bransa" am cat e cat idee despre ce ar trebui sa continea o astfel de placa:
      • Leduri - pentru simularea iesirilor;
      • Potentiometre (macar doua) pentru s(t)imularea ADC-ului;
      • Butoane - macar 4 :)
      • Comutatoare -  pentru intrarile digitale;
      • Relee;
      • Buzzer;
      • Drivere pentru motoare (DC si STEPPERE);
      • Compatibilitatea cu Raspberry Pi (3.3V);
    Ce a iesti vedeti mai jos: 









MULTE MULTUMIRI LUI TOMMY PLUSS PENTRU REALIZAREA CABLAJULUI PRIN METODA FOTO!



     Schema electronica...

Schema electronica

     Pentru a oferi protectie si flexibiliate m-am hotarat sa folosesc batranul driver ULN2003. Curentul de comanda este insignifiant si daca merge ceva prost Arduino/Pi nu are de suferit. 

     Dupa cum se observa circuitul integrat U1 (ULN2003) este responsabil de comnda ledurilor. Cum integratul are doar sapte iesiri si mie im place "byte-ul :)" am mai adaugat un led comandat direct de Arduino.  Cu U2 treaba e ceva mai sensibila: trei iesiri au fost folosite pentru a putea comanda relee direct la 5V, iar celelalte 4 pentru a comanda diverse sarcini (1 stepper, 4 motoare de cc etc.). 

     Daca va uitati cu atentie observati ca ULN-ul - U2 poate fi alimentat fie la 5V fie la o alta tensiune (in functie de sarcina comandata). In cazul in care se doreste utilizarea unei alte tensiuni, de exemplu 12V, se comuta JP5 de pe ramura de 5V pe ramura de 12V, se anuleaza JP1, JP2, JP3 iar JP4, JP6, JP7, JP8 se comuta la 12V. In acest fel decuplam releele (protejandu-le de o comanda accidentala) si alimentam sarcinile la tensiunea de 12V (in realitate ULN2003 poate comanda sarcini cu tensiunea de pana la 50V !!!). Cam atat pentru partea de iesiri. Aaaaa ar mai fi buzzer-ul comandat de tranzistorul Q1.

  Intrarile digitale sunt reprezentate de dip-switch-ul DSW1, de patru butoane si de doua potentiometre de 10k. Cum Rasperry Pi moare dupa tensiunea de 5V am ales sa pot comuta (pentru butoane si switch) aceasta tensiune la 3.3V prin jumper-ul JP9. 

Alimentarea se face direct la 5V (gata cu curentul consumat din USB) si prin minunatul LM1117T-3.3 se obtine si tensiunea de 3.3V pentru Raspberry.

Acum, ca in sfarsit am totul grupat, voi face si o a doua placa pentru chestii mai de finete: RTC, LCD, I2C etc... TIMP SA FIE :)

Daca cineva este interesat de cablaj il ofer cu mare placere, lasati doar un mesaj.

Sa auzim de bine!


sâmbătă, 4 februarie 2017

Server GPIO cu Raspberry Pi si Flask

0 comentarii | Read more...


Pentru inceput...

     Salutare tuturor! Iata ca am gasit ragazul sa sa mai adaug un articol pe blog.

     Daca pana acum comenzile pe care le-am trimis Pi-ului erau preluate de la tastatura prin SSH, am zis sa ridic un pic stacheta si sa programez pentru Raspberry un server web. Zis si facut! Cum Python-ul este obiectivul meu pe termen lung am ales ca server o veche cunostinta: Flask-ul. Server-ul este usor de programat iar documentatie se gaseste garla pe internet. Ce a iesit puteti vedea in filmuletul de mai jos:









Si o poza cu realizarea practica:




Aaa si il  puteti vedea live la http://84.117.194.136:64000/

username: guest ; password 1234


Cum functioneaza?

     Daca sunteti interesati de fenomenul IOT (internet of things) si ati mai configurat ceva servere, fie cu Arduino fie cu NodeMcu, ati observat, probabil, faptul ca este realtiv greu sa realizati o protectie minimala impotriva "vizitatorilor" nepoftiti. Cat timp rulati serverul in reteaua locala nu este nici o problema, insa cand "iesiti" cu el pe internet va puteti trezi ca aerul conditionat porneste din senin sau lumina se stinge si se aprinde haotic. Cu alte cuvinte cineva se joaca la butoanele voastre! 

     Ceea ce voi prezenta in continuare este o solutie sigura, deoarece permite autentificarea pe baza de user-name si parola. 

Cum se face?

     Pentru a putea instala cu succes server-ul trebuie sa urmati tutorialele anterioare, pe care evident, le gasiti pe blog.

     Fiindca sunt baiat bun voi face public codul ba mai mult va voi explica in cateva cuvinte cum lucreaza pentru a-l putea adapta la nevoile voastre. Sa incepem:

     Pe lanaga Python care, impreuna cu libraria Flask, ruleaza pe Raspberry Pi a mai fost necesar sa scriu codul HTML pentru paginile web (cea de logare si cea de control) si sa folosesc  un pic de JavaScript impreuna cu Ajax si jQuery. Pheeewww :) !

     Daca insiruirea de mai sus pare impresionanta (mi-a mancat ceva din viata :) ), pentru cei care vor sa foloseasca serverul "as it is" este necesara modificarea doar a catorva linii de cod. Chiar este simplu, credeti-ma!

   In prezent serverul are implementat controlul GPIO impreuna cu senzorul de temperatura DS18B20. In viitor daca va fi cazul probabil voi mai adauga si alti senzori. Asadar, pentru a adapta codul necesitiatilor voastre tot ce aveti de facut este sa urmati pasii:


  1. Deschideti o noua sesiune SSH (recomand cu caldura Moba Xterm) cu Raspberry Pi si instalati libraria Flask:

    sudo pip3 install flask
    


         2. Descarcati proiectul de aici 

         3. Creati un folder nou in ' /home/pi/' pe care il puteti denumi, de exmplu, Server_Login

         4. In noul folder desarcati proiectul dezarhivat. Din nou MobaXterm este prietenul vostru.



         Haideti sa vedem un pic structura folderelor si continutul acestora:

         In folderul radacina al proiectului:


    Folderul radacina

    -folderul 'static' contine fisierele necesare pentru pagina web: stiluri css de formatare, codul javascript.

    Folderul 'static'

    -folderul 'templates' contine codul paginilor web dinamice. Daca va 'bagati nasul' un pic prin ele veti observa ca acesta difera de codul html traditional. Asta deoarece paginile se genereaza in timp real in functie de user (admin sau guest), de numarul de iesiri si de cel de senzori. 



    Folderul templates

          Dupa cum spuneam si la inceputul articolului, daca doriti sa folositi serverul asa cum este el, nu aveti de modificat absolut nimic in fisierele rezidente in folderele 'static' si 'templates'.
    Folderul radacina mai contine doua fisiere: 'flask_server_login.py' si 'ds18b20.py'. Primul reprezinta serverul propriu-zis, iar cel de-al doilea driverul pentru senzorul de temperatura DS18B20.

    Codul pe care va trebui sa-l modificati este cel din fisierul 'flask_server_login.py'. Listingul este prezentat mai jos:



      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    #https://pythonspot.com/login-authentication-with-flask/
    #https://www.tutorialspoint.com/flask/flask_sessions.htm
    from flask import Flask
    from flask import Flask, flash, redirect, render_template, request, session, abort
    import os
    import time
    import threading as th
    import RPi.GPIO as g
    import ds18b20 as ts
    
    time.sleep(20)
     
    app = Flask(__name__)
    
    #date pentru tabel
    
    users=[{'Name':'admin','Pass':'1234','Rank':'admin'}, #users names, passwords, and ranks
    {'Name':'User','Pass':'1234','Rank':'admin'},
    {'Name':'guest','Pass':'1234','Rank':'guest'}]
    
    title="PANOU CONTROL RASPBERRY PI" # title of the table
    
    
    switches=(('Priza AC','p0'),('Bec Intrare','p1'),('Releu centrala','p2'),('Masina de spalat','p3'),('Veioza','p4'))# tupple of switches: switch designation and html id
    sensors = (('S.T. Dormitor','s1'),) # tupple of sensors: sensor name and html id
    
    a='enabled'  #template prototipe -> html enabled for switches. Only if rank is admin
    b='disabled' #template prototipe -> html enabled for switches. If rank is guest
    
    x=0
    y=0
    
    g.setmode(g.BCM)
    pins=[26,19,13,6,5]
    
    status=[0,0,0,0,0] #status array -> contains the status of switches
    sensorStatus=['-125'] #status of sensors
    
    def readTemp(): #read the temperature 
     ds=ts.ds18b20(1)
     sensorStatus=ds.readTemp()
     th.Timer(10,readTemp).start()
    
    def checkQuerry(a): # check if a valid request was sent. 
     for i in switches:
      if i[1]==a:
       return True
     return False  
    
    
    def setStringChange(): # the return string of change request
     j=0
     a=""
     for i in switches:
      a=a+i[1]+'_'+str(status[j])+':'
      g.output(pins[j],status[j])
      j=j+1 
     return a[0:len(a)-1]
    
    def setStatusString(): #the return of a status request
     a=setStringChange()
     b=""
     j=0
     #for i in switches:
      #a=a+i[1]+'_'+str(status[j])+':'
      #j=j+1 
     #a=a[0:len(a)-1] 
     #j=0
     for i in sensors:
      b=b+i[1]+'_'+str(sensorStatus[j])+':'
      j=j+1 
     b=b[0:len(b)-1]
     return a+"#"+b # return string has following pattern: p0_1:p1_0:p3_0:p4_0#s1_24.5:s2_19.1
     
    
    @app.before_first_request #before first request initiate the temperature loop
    def initTemp():
     readTemp()
     os.system('clear')
     cnt=0
     for i in pins:
      g.setup(i,g.OUT)
      g.output(pins[cnt],0)
      cnt=cnt+1
     
    @app.route('/') #
    def home():
     if not session.get('logged_in'): #if there is no field called 'logged_in' redirect the client to login form
      print('nelogat_home()')
      return render_template('login.html', mesaj='Ok')
     if session['rank']=='admin' and session.get('logged_in'): # if the client has already logged in return the control page for admin 
      return render_template('ctrl.html',title=title,switches=switches,sensor=sensors,st=a)
     if session['rank']=='guest' and session.get('logged_in'): # if the client has already logged in return the control page for guest
      return render_template('ctrl.html',title=title,switches=switches,sensor=sensors,st=b)
      
    @app.route('/login', methods=['POST'])
    def do_admin_login():
     u=request.form['username'] # read the values of fields 'username' and 'password'
     p=request.form['password']
     for us in users: # check if the user is in the dictionary
      if us['Name']==u and us['Pass']==p and us['Rank']=='admin':
       session['logged_in'] = True # asign to the session the filed logged_in 
       session['rank']='admin' # asign to the session the filed rank
       session['name']=u # asign to the session the name of user
      if us['Name']==u and us['Pass']==p and us['Rank']=='guest':
       session['logged_in'] = True
       session['rank']='guest'
       session['name']='Guest'
     return home()
     
    @app.route("/logout")
    def logout():
        session['logged_in'] = False
        return home()
     
    @app.route('/change',methods=['GET']) #change request
    def change():
     if not session.get('logged_in'): #if only the client is not logged_in
      return render_template('login.html',mesaj='Nu esti autentificat !') 
     if session.get('logged_in') == True and session.get('rank')=='admin': #if the client has the rank of admin
      req = request.args.get('change') # read the value of change request
      if checkQuerry(req): #check if it's a valid request 
       a=int(req.strip('p'))
       if status[a]==0:
        status[a]=1
       else:
        status[a]=0
       return setStringChange() #return the current status of switches
      else:
       session['logged_in']=False #if change request was written by hand logout the user
       return render_template('login.html',mesaj='Gotcha...')   
     elif session.get('logged_in')==True and session.get('rank')=='guest': #if a guest wants to change the switch from html logg him out
      session['logged_in']=False
      return render_template('login.html',mesaj='Autentifica-te ca admin !')
    
    
    @app.route('/status',methods=['GET'])
    def getStatus():
     if not session.get('logged_in'):
      return render_template('login.html',mesaj='Nu esti autentificat !') 
     elif session.get('logged_in') == True : 
      return setStatusString()
    
    
      
    if __name__ == "__main__":
     app.secret_key = os.urandom(12)
     app.run(debug=True,host='192.168.0.199', port=6000, threaded=True)
    
     
    

    Asadar sa incepem :) :

         Crearea userilor se face  modificand array-ul de dicitionare users (linia 17). Fiecare user trebuie sa contina un nume, o parola si un privilegiu (rank). Cei care au voie sa modifice starea switch-urilor vor avea rolul de 'admin', iar cei care pot doar vizualiza starea acestora sunt 'guest'. Puteti adauga oricat de multi useri cu conditia sa respecati tiparul din cod, cu alte cuvinte atentie la sintaxa.

         Dupa cum am zis crearea paginilor este dinamica, cu alte cuvinte codul html poate fi modificat direct de aici fara a necesita interventia asupra paginii. Variabila 'titlu' va  contine informatia necesara pentru afisarea denumirii panoului de comanda. Eu am ales sa se numeasca "PANOU CONTROL RASPBERRY PI", voi puteti sa modificati.

         Tupple-urile 'switches' si 'sensors' contin informatiile despre comutatoare si senzori. Prima intrare defineste denumirea senzorului iar cea de-a doua id-ul sau din pagina html. Puteti adauga sau sterge oricat de multe comutatoare, cu conditia sa fiti atenti la sintaxa. Ca ultim cuvant, in cazul in care aveti un singur switch sau senzor virgula de final este obligatorie (vezi cazul de fata tupple-ul sensors)

        Cele doua variabile 'a' si 'b', folosite in functie de 'rank' dau sau nu privilegiul de a schimba sau nu starea comutatoarelor.

      Mai departe (in linia 33) definim cum va fi numerotarea pinilor. In cazul de fata s-a ales numerotarea fizica la terminalele microprocesorului. In urmatoarea linie se defineste un array care contine numarul pinilor. Array-ul status (linia 36) contine starea initiala a switch-urilor. El trebuie sa contina tot atatea  elemente cate  cate comutatoare au fost definite. In cazul de fata sunt utilizate 5 comutatoare, deci 'status' contine tot cinci elemente.  Analog si pentru sensorStatus. 

    Astea sunt toate modificarile pe care le aveti de facut.

         Acum haideti sa vedem care este functionarea. Flask foloseste un sistem 'decorator', sistem pe care inca nici eu nu il stapanesc prea bine. Din ceea ce stiu va pot spune doar ca in functie de context sunt apelate functiile specifice. In cazul de fata au fost utilizate urmatoarele 'decoratoare':

    @app.before_first_request - inainte de a executa primul request se executa functia asociata:
     in cazulde fata - def initTemp():

    @app.route('/') - primul request atunci cand user-ul acceseaza adresa- se executa functia
    def home():

    @app.route('/login', methods=['POST']) - atunci cand userul trimite datele de autentificare
     se executa functia def do_admin_login():
    
    
    @app.route("/logout") - atunci cand userul doreste sa incheie sesiunea - se executa functia
    def logout():

    @app.route('/change',methods=['GET']) - atunci cand userul doreste sa schimbe starea unui
    comutator - se executa functia def change():

    @app.route('/status',methods=['GET']) - atunci cand userul doreste sa fle starea sistemului
    se apeleaza functia def getStatus():

    Cam atat ar fi de zis. Pentru intrebari va rog sa nu sfiiti sa lasati comentarii.

    Sa auzim de bine !


    sâmbătă, 14 ianuarie 2017

    Primii pasi cu Raspberry Pi (2) - GPIO

    0 comentarii | Read more...
    Salutare tuturor!

         In acest articol vom pune bazele lucrului cu GPIO-ul micutului computer numit Raspberry Pi. Daca nu ati parcurs articolul anterior va recomand sa o faceti acesand pagina de aici

         GPIO este o abreviere de la englezescul general purpose in-out. Cu alte cuvinte, pe langa pinii microprocesorului (si nu ai microcontroller-ului :) ) care asigura functii speciale, exista si un set de pini care ne sunt pusi la dispozitie si pe care putem sa ii programam dupa bunul plac. 

    In functie de versiunea de Raspberry Pi pe care o detineti acesti pini sunt diferiti. Prin diferiti se intelege atat pozitionarea lor pe placa cat si functiile auxiliare pe care le indeplinesc. Pentru acest articol am folosit un Raspberry Pi V2 al carui header este urmatorul:


    Daca detineti o alta versiune va recomand cu caldura sa accesati pagina aceasta.

    ATENTIE: 


    TENSIUNEA PE CARE O FURNIZEAZA UN PIN ESTE DE 3.3V, ATUNCI CAND ESTE CONFIGURAT CA SI PIN DE IESIRE. LA FEL SI IN CAZUL IN CARE ESTE CONFIGURAT CA PIN DE INTRARE: VALOAREA MAXIMA PE CARE O POATE "CITI" ESTE TOT DE 3.3V. O TENSIUNE MAI MARE SI... PLICI! 
    IN CAZUL CURENTILOR, LUCRURILE SUNT UN PIC MAI COMPLICATE: CURENTUL TOTAL PE CARE IL POATE FURNIZA - PENTRU TOTI PINII - ESTE DE 50mA. CONSIDERAND CA FOLOSIM TOTI CEI 17 PINI DISPONIBILI, CURENTUL MAXIM/PIN ESTE DE 50/17=3mA. IN GENERAL, CA REGULA DE BAZA CURENTUL PER PIN TREBUIE SA FIE CAT MAI MIC CU PUTINTA!

    Cum in articolul de fata ne vom juca cu leduri, consider ca este necesar sa explic un pic montajul:







         Asadar bargraph-ul contine 10 leduri. Conform datasheet-ului, caderea de tensiune pe fiecare led este de 2V. Din totalul de 3.3V mai raman 1.3V, caderea de tensiune pe fiecare rezistenta.Cunoscand valoarea unei rezistente (1000 ohmi) se poate calcula curentul consumat de fiecare led: 1.3/1000=1.3mA. Cum avem 10 leduri, atunci cand toate sunt aprinse, curentul maxim consumat de pe bara de 3.3V este de 13mA. Deci este OK.
         Intregul montaj a fost conceput pe un breadboard. Si sa nu uit, va recomand din tot sufletul sa cumparati un adaptor pentru breadboard la header-ul Raspberry Pi.



    Programarea...

         In scop demonstrativ au fost realizate 4 programe, de la simplu la complex. Ce a iesit puteti vedea in clipul de mai jos:



         Inainte de a ne baga nasul in Python trebuie instalata libraria care ne ofera acces la GPIO. Pentru aceasta realizati o conexiune la Pi printr-un client SSH (Putty, MobaXterm) si dupa logare tastati urmatoarea coamanda:



    sudo apt-get install rpi.gpio
    

    Dupa instalarea librariei urmati urmatorii pasi:

    1. Porniti programul MobaXterm;
    2. Deschideti o sesiune SSH cu Raspberry Pi (vezi articol anterior);
    3. Deschideti tabul  Sftp;
    4. Creati un folder nou: GPIO_SCRIPTS;



    Acum in interiorul folder-ului creati primul fisier python cu numele : GPIO_0.PY:




    Click dreapta pe fisierul noucreat si alegeti deschiderea acestuia cu editorul incorporat in MobaXterm:



    Primul program...

    Dupa cum spuneam si in randurile de mai sus cele 4  programe sunt realizate de la simplu la complex. Primul program va "clipi" doua leduri pe rand la interval de o secunda. Listingul il gasiti mai jos:



     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import RPi.GPIO as gp
    import time
    import os
    os.system('clear')
    print('Running...')
    gp.setmode(gp.BCM)
    
    pin1 =26
    pin2=19
    
    cnt=0;
    gp.setup(pin1,gp.OUT)
    gp.setup(pin2,gp.OUT) 
    
    while(1):
      gp.output(pin1,1)
      gp.output(pin2,0)
      time.sleep(1)
      gp.output(pin1,0)
      gp.output(pin2,1)
      time.sleep(1)
    

    Pentru cei care au experienta cu Arduino codul pare familiar: 

    • In linia 1 de cod se importa libraria GPIO;
    • Pentru a putea avea acces la delay-uri se importa modulul time;
    • In liniile 12 si 13  se seteaza directia pininilor, in cazul de fata este OUT
    • Incepand cu linia 15 se creaza bucla infinita care va "clipi" ledurile la interval de 1 secunda.
         Am lasat la urma explicatia pentru cea mai importanta linie de cod: linia cu numarul 6. Dupa cum spuneam si la inceputul articolului arnajarea pinilor pe placa este un pic confuza. Exista doua numerotari: numerotarea pinilor in ordinea plantarii acestora pe header (de la 1 la 40) si numerotarea in functie de terminalele microprocesorului, cea in care apare prefixul GPIO. Cand se importa modulul GPIO ambele optiuni pot fi luate in calcul.

    Daca se doresete utilizarea pinilor in ordinea plantarii pe placa se va folosi instructiunea,

    gp.setmode(gp.BOARD)
    

    iar daca se doreste utilizarea pinilor in functie de numele pe care le au terminalele microprocesorului, se va utiliza instructiunea


    gp.setmode(gp.BCM)
    

    In cazul de fata, deoarece mi-a fost mult mai comod sa folosesc denumiriele deja gravate pe adaptorul de breadboard, am utilizat cea de-a doua varianta. Astfel, ca o ultima lamurire, in cazul de fata GPIO26 corespunde de fapt celui de-al 37-lea pin iar GPIO19 celui de-al 35-lea.

    Mare atentie: alegeti intotdeauna varianta pentru care ati facut montajul deoarece exista posibilitatea (destul de mare) sa ardeti computerul.

    Copiati codul de mai sus (fara numarul liniei de cod) si paste in editorul de text deschis. Salvati, dupa care in SSH tastati scuccesiv comenzile:


    cd GPIO_SCRIPTS
    sudo python3 GPIO_0.PY
    




    Programul va rula. Nu uitati ca sunteti intr-o bucla infinita. Pentru a inchide programul tastati in acelasi timp CTRL+C.

    Al doilea program...

    Cel de-al doilea program este ceva mai complicat, dar nu foarte... Acesta va aprinde si va stinge ledurile succesiv, la interval de o secunda.
    Urmand pasii de mai sus creati un al doilea fisier numit de data aceasta GPIO_1.PY. Si copiati listingul de mai jos:


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import RPi.GPIO as gp
    import time
    gp.setmode(gp.BCM)
    
    pins=[26,19,13,6,5,22,27,17,4,21]
    
    cnt=0;
    for i in pins:
     gp.setup(i,gp.OUT)
     gp.output(pins[cnt],False) 
     cnt=cnt+1
     
    while(1):
     for i in range(0,10):
      gp.output(pins[i],True)
      time.sleep(1);
      
     for i in range(0,10):
      gp.output(pins[i],False)
      time.sleep(1); 
    

    Rulati programul cu comanda:


    sudo python3 GPIO_1.PY
    

    Al treilea program...

         Daca pana acum "am fost martori" la ceea ce face Pi-ul, acum a sosit momentul sa ii trimitem comenzi. Programul de fata aprinde si stinge ledurile in functie de numarul acestora care a fost preluat de la tastatura. Nu voi explica prea mult programul  deoarece contine elemente proprii limbajului de programare Python3 lucru care nu face obiectul articolului de fata. Pentru un tutorial foarte bun in ceea ce priveste limbajul de programare mai sus mentionat va recomand cu caldura sa mergeti aici.

    Urmati pasii anteriori si creati un fisier denumit GPIO_1.PY. Copiati si salvati listingul urmator:



     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    import RPi.GPIO as gp
    import time
    import os
    from colorama import Fore, Back, Style
    
    os.system('clear')
    
    gp.setmode(gp.BCM)
    
    pins=[26,19,13,6,5,22,27,17,4,21]
    state=[0,0,0,0,0,0,0,0,0,0]
    check=False
    cnt=0;
    for i in pins:
     gp.setup(i,gp.OUT)
     gp.output(pins[cnt],False) 
     cnt=cnt+1
    def printLeds():
     print(Fore.YELLOW+"RASPBERRY PI SSH LED CONTROL")
     print(Back.BLACK+"",end='\n')
     for i in state:
      if i==1:
       print(Back.RED+' ',end='')
      else:
       print(Back.WHITE+' ',end='')
      print(Fore.WHITE+Back.BLACK+"|",end='') 
     print(Back.BLACK+"",end='\n')
     for i in range(0,10):
      print(Fore.GREEN+str(i),end='')
      print(Fore.WHITE+Back.BLACK+"|",end='')
     print(Back.BLACK+"",end='\n')
    
    printLeds() 
    while(1):
     print("")
     pin=input(Fore.GREEN+"Insert led number:")
     if pin.isnumeric():
      check=False
      k=int(pin)
      #check if it's a valid led number
      for i in range(0,10):
       if k==i:
        os.system('clear')
        print("")
        check=True;
        if state[i]==0:
         state[i]=1
         gp.output(pins[i],True)
        else:
         state[i]=0
         gp.output(pins[i],False)
        printLeds() 
      if check==False:
       print(Fore.RED+"No led number!")
     else:
      print(Fore.RED+"Insert a number in range 0-9")
    


    Rulati programul cu urmatoarea comanda:




    sudo python3 GPIO_2.PY
    



    Dupa incarcare puteti comanda ledurile tastand numarul ledului (de la 0 la 9) iar ledul isi va schimba starea.




    Al patrulea program...


         Programul de mai sus ne permite in sfarsit sa interactionam cu Raspberry Pi. Problema este ca nu putem citi starea curenta a ledurilor. Acest lucru este de dorit daca sunt mai multi utilizatori care vor sa comande ledurile. Urmatorul program rezolva (partial) problema. Starea ledurilor este salvata intr-un fisier. Acest lucru ne permite sa rulam mai multe instante ale programului si chiar daca sunt procese diferite toate vor imparti aceeasi resursa: fisierul text in care sunt salvate starile. Cum python nu ne permite (in mod direct) sa aflam daca un fisier este deschis sau nu, mecanismul prin care se incerca evitarea scrierii concomitente de catre doi sau mai multi utilizatori in fiser este... redenumirea fisierului. Ca si in cazul programului anterior va recomand sa urmati cat mai multe tutoriale Python3.

    Fisierul se va numi "status", si va trebui sa se afle in acelasi folder ca si programul. Continutul initial al fisierului este urmatorul:


    0,0,0,0,0,0,0,0,0,0
    

    Dupa cum se observa, initial toate ledurile sunt stinse.

    Cunoscand deja mecanismul vom crea al 4-lea (si ultimul fisier) cu denumirea GPIO_3.PY. Apoi vom copia codul din listingul de mai jos:



      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    import RPi.GPIO as gp
    import time
    import os
    from colorama import Fore, Back, Style
    
    os.system('clear')
    
    gp.setmode(gp.BCM)
    
    pins=[26,19,13,6,5,22,27,17,4,21]
    state=[0,0,0,0,0,0,0,0,0,0]
    check=False
    cnt=0;
    for i in pins:
     gp.setup(i,gp.OUT)
     gp.output(pins[cnt],False) 
     cnt=cnt+1
    def printLeds():
     print(Back.BLACK+"",end='\n')
     for i in state:
      if i==1:
       print(Back.RED+' ',end='')
      else:
       print(Back.WHITE+' ',end='')
      print(Fore.WHITE+Back.BLACK+"|",end='') 
     print(Back.BLACK+"",end='\n')
     for i in range(0,10):
      print(Fore.GREEN+str(i),end='')
      print(Fore.WHITE+Back.BLACK+"|",end='')
     print(Back.BLACK+"",end='\n')
    
      
    def renameFile():
     r=False
     while(r==False):
      try:
       os.rename('status','temp')
       r=True
      except IOError:
       r=False
    
    
    
    def writeFile():
     renameFile()
     print(Fore.YELLOW+"RASPBERRY PI SSH LED CONTROL")
     print('Writing data...')
     try:
      temp=open('temp','r+')
      a=''
      for i in state:
       a=a+str(i)+',' 
      temp.write(a[0:len(a)-1])
      temp.close()
      os.rename('temp','status')
      print('Writing complete!')
     except IOError:
      print('File not found...')
    
    
    def readFile():
     os.system('clear')
     renameFile()
     print(Fore.YELLOW+"RASPBERRY PI SSH LED CONTROL")
     print('Reading data...')
     try:
      temp=open('temp','r+')
      a=temp.readline().split(',')
      for i in range(0,10):
       state[i]=int(a[i])
       gp.output(pins[i],state[i]) 
      temp.close()
      os.rename('temp','status')
      print('Reading complete!') 
      printLeds()
     except IOError:
      print('File not found...')
      
    readFile()
    
    while(1):
     print("")
     pin=input(Fore.GREEN+"Insert led number or r to read status:")
     if pin.isnumeric():
      check=False
      k=int(pin)
      #check if it's a valid led number
      for i in range(0,10):
       if k==i:
        os.system('clear')
        print("")
        check=True;
        if state[i]==0:
         state[i]=1
         gp.output(pins[i],state[i])
        else:
         state[i]=0
         gp.output(pins[i],state[i])
        writeFile()  
        printLeds()
        break 
      if check==False:
       readFile()
       print(Fore.RED+"No such command...")
     elif pin=='r':
      readFile()
     else:
      readFile()
      print(Fore.RED+"No such command...")
    



    Cam atat pentru azi. Fisierele cu codurile sursa se pot descarca de aici.

    Sa auzim de bine !!!!

    P.S. Nu va sfiiti sa lasati comentarii !!!

    Totalul afișărilor de pagină

    Despre

    Blog cu si despre electronica !