Sari la conținut
ELFORUM - Forumul electronistilor

Modificare sursa ATX => Proiect didactic


Postări Recomandate

Revin si cu afisajul, am folosit PIC16F88 si LCD 16x1 penca sunt suficiente pentru ce se cere, codul sursa e scris de mine si aista ii:

/* Afisaj digital pentru sursa de laborator  -Tensiune: 0-35Vcc  -Curent: 0-5A    *Configuratie  -PIC16F88  -Cristal 4Mhz  -LCD alfanumeric 16x1    -Autor:  -Marian@Elforum*/  //LCD Connectionssbit LCD_RS at RB0_bit;sbit LCD_EN at RB1_bit;sbit LCD_D4 at RB2_bit;sbit LCD_D5 at RB3_bit;sbit LCD_D6 at RB4_bit;sbit LCD_D7 at RB5_bit;sbit LCD_RS_Direction at TRISB0_bit;sbit LCD_EN_Direction at TRISB1_bit;sbit LCD_D4_Direction at TRISB2_bit;sbit LCD_D5_Direction at TRISB3_bit;sbit LCD_D6_Direction at TRISB4_bit;sbit LCD_D7_Direction at TRISB5_bit;//Variabileunsigned char ch, ADCx;unsigned int Tensiune, Curent;unsigned long V, A;//Functie principalavoid main() {     INTCON = 0;          //Initializare LCD     Lcd_Init();     Lcd_Cmd(_LCD_CURSOR_OFF);     Lcd_Cmd(_LCD_CLEAR);     Delay_ms(1000);     Lcd_Out(1,1,"Sursa La");     Lcd_Out(2,1,"borator");     Delay_ms(2000);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"1,25 - 3");     Lcd_Out(2,1,"0Vcc");     Delay_ms(2000);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"0,15 - 3");     Lcd_Out(2,1,",5A");     Delay_ms(2000);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"U:");     Lcd_Out(2,2,"I:");     while (1) {            //Achizitie ADC            Tensiune = 0;            Curent = 0;                 for (ADCx=0; ADCx<10; ADCx++) {                 Tensiune += ADC_Read(0);                 Curent += ADC_Read(1);                 Delay_ms(10);                 }            //Afisare Tensiune            Tensiune = Tensiune/ADCx;            V = (long)Tensiune*3500;            V = V/1023;            ch = V/1000;               if (ch==0) {               Lcd_Chr(1,3,32);               }               else {               Lcd_Chr(1,3,48+ch);               }            ch = (V/100) % 10;            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('.');            ch = (V/10) % 10;            Lcd_Chr_CP(48+ch);            ch = V % 10;            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('V');            Delay_ms(10);            //Current            Curent = Curent/ADCx;            A = (long)Curent*500;            A = A/1023;            ch = A/100;            Lcd_Chr(2,4,48+ch);            Lcd_Chr_CP('.');            ch = (A/10) %10;            Lcd_Chr_CP(48+ch);            ch = A % 10;            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('A');            Delay_ms(10);            }     }

Am testat intai in simulator si apoi pe breadboard pentru a confirma functionalitatea codului si a fost ok:

post-15007-139829741336_thumb.jpg

 

Am pus totul intr-o schema si apoi am proiectat si un micut pcb:

post-15007-139829741346_thumb.png

post-15007-139829741349_thumb.png

 

Dupa ce voi avea placile facute le voi asambla si apoi voi include totul intr-o carcasa si evident voi reveni cu rezultatul final.

Link spre comentariu

Ok pai tre sa mentionez din start ca-s destul de novice in materie de programare, mai mult decat atat, cu ceva timp in urma ma uitam la astfel de coduri cum pisicul se uita in calendar :rade:

 

M-am apucat sa invat programare deoarece niste colegi binevoitori ( carora sa le deie Domnu multa sanatate ) mi-au donat niste PIC si LCD-uri, am inceput prin a studia limbajul C++ care mi s-a parut ceva mai intuitiv, apoi cu ajutor sustinut din partea colegilor mai destepti de pe la uC-uri am inceput sa inteleg cate ceva, totusi sunt departe de ceea ce as dori, dar trebuie sa ma multumesc si cu atat.

 

O sa incerc sa explic codul ( care de altfel este foarte simplu ) asa cum cred eu ca e mai util, pe sectiuni, deci:

//LCD Connectionssbit LCD_RS at RB0_bit;sbit LCD_EN at RB1_bit;sbit LCD_D4 at RB2_bit;sbit LCD_D5 at RB3_bit;sbit LCD_D6 at RB4_bit;sbit LCD_D7 at RB5_bit;sbit LCD_RS_Direction at TRISB0_bit;sbit LCD_EN_Direction at TRISB1_bit;sbit LCD_D4_Direction at TRISB2_bit;sbit LCD_D5_Direction at TRISB3_bit;sbit LCD_D6_Direction at TRISB4_bit;sbit LCD_D7_Direction at TRISB5_bit;
Aici se declara conexiunile la LCD, nu cunosc sa existe vre-o regula clara cat privesc pinii alesi, eu de obicei selectez un port mai "liber" si pe ala il sacrific pentru asta. Se folosesc 4 din cele 8 conexiuni de date cu scopul de a economisi biti, marturisesc ca asta este oricum unul din putinele conexiuni pe care il cunosc. Alegerea bitilor pentru conexiuni o fac tinand cont si de pozitia pinilor respectivi pentru a-mi usura munca la trasarea cablajului.

 

//Variabileunsigned char ch, ADCx;unsigned int Tensiune, Curent;unsigned long V, A;
O sectiune cred eu care se autoexplica, se declara variabilele cu ajutorul carora se executa functiile de interes, alegi tipul de variabila declarat in functie de nhumarul de operatiuni pe care il poate suporta tinand cont si de faptul ca variabilele "mai mari" ocupa memorie mai multa, in documentatia compiler-ului folosit ar trebui sa se poata gasi detalii despre tipul de variabile si numarul de operatii suportate de fiecare. Eu folosesc MikroC PRO, in documentatia sa exista tabelul la care m-am referit si care specifica spre exemplu ca unsigned char suporta 256 de operatii, unsigned int-65535, unsigned long-4294967295... etc.

 

Codul contine o singura functie, void main in care se executa toate operatiunile. Se incepe prin declararea starii initiale a diferitilor registrii, uC-ul asta e destul de mic si simplu, a fost deajuns INTCON = 0; care dezactiveaza intreruperile, dar la alte uC-uri cu care am mai lucrat se intampla sa fie nevoie a se declara starile registrilor TRIS, PORT, LAT... etc, in functie de portul folosit, apoi ANSEL si poate si ANSELH, ADCON... TRIS stabileste directia portului respectiv, 1 pentru intrare, 0 pentru iesire, LAT este un registru suplimentar folosit incepand cu uC-urile 18F, marturisesc ca nu l-am inteles niciodata prea bine spre rusinea mea; ANSEL si ANSELH se folosesc concomitent cu TRIS pentru portul respectiv si stabilesc daca intrarea respectiva este una digitala ANSEL = 1; sau analog ANSEL = 0; ADCON este registrul care activeaza sau dezactiveaza ADC-ul, in pdf-urile unor uC-uri mai mici asa cum este asta, de multe ori nu se gasesc acesti registrii, am observat ca in atare situatie se pot ignora, motive clare insa de ce se intampla asta din pacate nu pot specifica.

 

//Initializare LCD     Lcd_Init();     Lcd_Cmd(_LCD_CURSOR_OFF);     Lcd_Cmd(_LCD_CLEAR);
Aici se face initializarea LCD-ului in prima linie, urmata de 2 comenzi care dicteaza dezactivarea cursorului si stergerea ecranului. Imediat dupa ele in codul meu urmeaza mesajele initiale prin comanda Lcd_Out(A,B,"C"); unde A reprezinta linia pe care se doreste a se afisa mesajul, evident se pune cifra respectiva in loc de litera scrisa de mine, spre exemplu linia 1 se adreseaza scriind simplu, 1; B reprezinta coloana cu care se doreste a se incepe mesajul din linia respectiva, la fel ca si la linie, se foloseste cifra corepondenta coloanei dorita; iar C reprezinta mesajul dorit a se afisa, tot ce apare intre acele ghilimele va fi reprodus intocmai pe ecran, uneori caracterele dorite nu exista pe tastatura, se pot insa reproduce prin adresarea codurilor lor, coduri care se pot gasi in pdf-ul LCD-ului respectiv.

 

Dupa asta se incepe bucla propriu zisa care executa functia, in cazul de fata singura de altfel, while (1), uC-ul ramane in aceasta bucla permanent dupa initializare, evident pana la reset sau intreruperea alimentarii.

 

//Achizitie ADC            Tensiune = 0;            Curent = 0;                 for (ADCx=0; ADCx<10; ADCx++) {                 Tensiune += ADC_Read(0);                 Curent += ADC_Read(1);                 Delay_ms(10);                 }
Aici se face achizitia ADC pentru pentru ceea ce se doreste a se monitoriza, solutia de aici ii apartine lui @LiviuM, se executa 10 citiri intr-o singura bucla for si se foloseste media, intai se declara valorile initiale ale variabilelor Tensiune si Curent apoi se intra in bucla si se executa 10 citiri ale canalelor ADC alese ( in cazul meu AN0 si AN1 ) incrementandu-se la fiecare citire valorile la variabilele respective.

 

//Afisare Tensiune            Tensiune = Tensiune/ADCx;            V = (long)Tensiune*3500;            V = V/1023;            ch = V/1000;               if (ch==0) {               Lcd_Chr(1,3,32);               }               else {               Lcd_Chr(1,3,48+ch);               }            ch = (V/100) % 10;            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('.');            ch = (V/10) % 10;            Lcd_Chr_CP(48+ch);            ch = V % 10;            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('V');            Delay_ms(10);
Aici este bucata de cod care executa afisajul tensiunii, in p;rima linie se acorda valoarea variabilei Tensiune, apoi se alege gama de afisaj dorita declarandu-se valoarea variabilei de tip long, apoi extragerea caracterelor si afisarea propriu zisa, ch = V/1000 se extrag zecile, dupa ea bucla if-else faciliteaza afisarea unui spatiu liber in loc de "0", ch = (V/100) % 10; se extrag unitatile si se afiseaza cu ajutorul comenzii imediat urmatoare, Lcd_Chr_CP('.'); aici se afiseaza caracterul "." folosit pe post de virgula pe afisaj, evident ca se poate folosi virgula insasi, dar mie mai mult imi place asta. ch = (V/10) % 10; se extrag si apoi se afiseaza zecimile, si imediat dupa se extrag sutimile, si la final se afiseaza "V". Eviudent ca tine de preferintele fiecaruia cate cifre sa se afiseze inainte sau dupa virgula, mie 2 inainte si 2 dupa mi-au ajuns. Inutil sa explic ce face comanda "delay".

 

Si in final partea de cod pentru curent care functioneaza practic la fel ca la tensiune numai ca aici nu a mai fost nevoie de bucla if-else deoarece se foloseste 1 singura cifra inainte de virgula. ch = A/100; extrage unitatile, Lcd_Chr(2,4,48+ch); dicteaza unde anume se va afisa valoarea respectiva, in cazul de fata linia 2, coloana 4, apoi totul este de la sine inteles, se repeta extragerile valorilor si afisarea lor...

 

Sper ca s-a inteles ceva din micul meu pomelnic. :rade:

Link spre comentariu

Ok pai tre sa mentionez din start ca-s destul de novice in materie de programare, mai mult decat atat, cu ceva timp in urma ma uitam la astfel de coduri cum pisicul se uita in calendar :rade: M-am apucat sa invat programare deoarece niste colegi binevoitori ( carora sa le deie Domnu multa sanatate ) mi-au donat niste PIC si LCD-uri, am inceput prin a studia limbajul C++ care mi s-a parut ceva mai intuitiv, apoi cu ajutor sustinut din partea colegilor mai destepti de pe la uC-uri am inceput sa inteleg cate ceva, totusi sunt departe de ceea ce as dori, dar trebuie sa ma multumesc si cu atat......

N-o sa te multumesti cu atat! O sa inveti si programare! Asa cum ai invatat si amplificatoarele, si sursele, liniare sau in comutatie, si o sa explici incepatorilor lucrurile pe care tu le-ai inteles ajutat de anumiti colegi de pe Elforum. Si cum esti genul care nu se multumeste cu ce stie, din ce o sa faci programe mai complexe, o sa doresti mai mult!Succes!PS De unde esti din Dambovita? Si eu sunt din Crevedia si momentan locuiesc acolo.
Link spre comentariu

Multumesc. Pai cam ai dreptate, sunt foarte ambitios si nu ma multumesc sa reproduc ceva mecanic ci vreau sa inteleg si de ce este asa si nu altfel, o sa fac tot posibilul sa evoluez si in programare.Locuiesc in Fierbinti, un sat parte din cea mai sudica comuna a judetului, undeva pe la 30km de Gaesti.

Link spre comentariu

Super, ms!Aveam 2 nelamuriri: de ce apare in cod linia a 2-a a LCDului, cand tu ai folosit un LCD cu doar 1 liniesi acel 48+ch, care face conversia de la codul ASCII la cifre (48 in ASCII afiseaza 0) <- o chestie ce merita mentionata, altfel te iei cu mainile de cap la ce afiseaza LCDul :rade: Spor la treaba in continuare!

Link spre comentariu

Aaa, pai n-am stiut ce nu iti era clar boss... Desi LCD-ul este cu doar o singura linie am impresia ca este configurat in stilul celor cu 2 la soft-ul sau, adica este impartit in 2 linii de cate 8 coloane, am incercat initial ( mai demult ) modul de adresare pentru o singura linie, dar de la coloana 8 incolo nu se mai afisa nimic, apoi am gasit ceva info in pdf si am inteles ca tre adresat ca si o a 2-a linie de la coloana 9 in sus. Cat despre acel 48+, intr-adevar are treaba cu conversia in format ASCII, am scris asta in coduri mai vechi, de fapt am unele coduri care explica insele fiecare linie, aici asta e asa simplu incat n-am crezut ca mai este necesar, oricum nu sunt eu in masura sa dau lectii despre programare nimenui, am ajutat ce-i drept pe pa PIC pe alti colegi cu softuri personalizate dar nimic foarte complicat, sau oricum nu peste nivelul meu redus de cunostinta in materie de programare.

Link spre comentariu

am ajutat ce-i drept pe pa PIC pe alti colegi cu softuri personalizate dar nimic foarte complicat, sau oricum nu peste nivelul meu redus de cunostinta in materie de programare.

Marian, nu fii modest. Sunt unul din cei ce a beneficiat de ajutorul tau, in materie de programare. Iti multumesc si pe acesta cale.Si nu in ultimul rand, cred ca esti printre putinii, daca nu singurul, din punctul meu de vedere, ce a facut progrese remarcabile in materie de surse. Probabil exista colegi ce stiu sa dimensioneze de la A la Z, o sursa in comutatie, dar ei nu au inceput de la zero, pe acest forum. Tot respectul pentru ambitia si dorinta de autoperfectionare si de ce nu, pentru disponibilitatea de a impartasi si altora, din cunostintele tale!
Link spre comentariu

Imi permit sa pun un exemplu de afisare pe LCD un pic mai vizual (adica mai usor de inteles) dar bazat pe acelasi principiu folosit de Marian. Si cu mai putine linii de cod.

 

Nota: caracterul 2 (Capacitance[2] = . )

char Capacitance[] = "00.000 uF";void Display_Cap(unsigned int n){ Capacitance[0] = n/10000 + 48; Capacitance[1] = (n/1000)%10 + 48; Capacitance[3] = (n/100)%10 + 48; Capacitance[4] = (n/10)%10 + 48; Capacitance[5] = (T_Value*10)/153 + 48; Lcd_Cmd(_Lcd_Clear); Lcd_Out(1, 1, "C = "); Lcd_Out(1, 5, Capacitance);
Luat de aici: http://embedded-lab.com/blog/?p=4400
Link spre comentariu
  • 2 săptămâni mai târziu...
  • 4 săptămâni mai târziu...
  • 1 lună mai târziu...

Am zis in repetate randuri ca nu ma inteleg cu excell-ul, insa o chestie pe care colegul moderator @ratza a zis-o pe la alta sectiune mai demult mi-a ramas in minte, si anume ca foarte multe se pot face cu el, azi m-am decis sa iau taurul de coarne, am primit azi 2 exell-uri de la @maxente iar pe unul pentru a-l putea vizualiza a trebuit sa instalez o versiune mai noua de office ( aveam una antica si dedemult ), studiindu-l putin pe celalalt pe care il puteam deschide cu vechea versiune, am ajuns la concluzia ca vorba aia nu demonul chiar atat de negru deci mi-am zis sa experimentez putin si am ajuns la o chestie sper eu interesanta.

 

Motivatia si totodata initiativa a venit chiar din propria experienta, mai demult la un topik despre modificare ATX pentru alimentare amplificator pe cand nu aveam punte LC deci nici cu ce sa masor inductantele, tin minte cat chin a fost sa realizez inductanta serie pentru stabilizare, calculul valorii necesare nu a fost o problema dar habar nu aveam cate spire sa dau ca sa obtin inductanta ce-mi era necesara, in aceeasi situatie probabil se afla si altii, tin sa va impartasesc si voua modalitatea mea de calcul pentru numarul spirelor de dat pe un anumit tor atunci cand avem o inductanta necesara data/cunoscuta, pentru moment am inclus doar 2 toruri, 2 dintre cele mai des intalnite in sursele ATX, motivatia fiind ca din astea probabil are cam oricine, T90-26 si T106-26. Atasez excell-ul cu cele necesare ( am creeat fisierul cu office 2007 ):

[attachment=0]Inductanta serie.rar[/attachment]

 

Ideea este simpla, in fisier aveti cifre marcate cu albastru, acestea pot fi editate de voi introducand valorile de interes, cu rosu vor aparea automat rezultatele. De mentionat ar fi faptul ca am omis calculul pierderilor in miez din dorinta de a nu complica prea tare calculul, mi se pare mai importanta ferirea de saturatie, si in acest sens exista si calculul inductiei "B" in miez.

 

Daca ideea prezinta interes, voi mai adauga si alte toruri, eventual puteti lasa sugestii de toruri pe care doriti sa le introduc in excell-ul meu, precizand materialul sau culoarea/culorile torului si dimensiunile acestuia, de restul ma ocup eu.

 

PS; Comentarii, critici, observatii... etc... bagati mare. :da

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări