Sari la conținut
ELFORUM - Forumul electronistilor

Exemple si notiuni de baza => Incepator


Marian

Postări Recomandate

Se poate si cu else, se poate si fara. :rade: Numai ca bucata de cod postata e prea mica, trebuie vazut si restul (partea de functionare normala).Scrie-l cum ti se pare tie bine, testeaza si daca nu-ti merge cum vrei ne mai sfatuim.

Link spre comentariu
  • Răspunsuri 102
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Marian

    53

  • Liviu M

    24

  • Mircea

    10

  • Vlad Mihai

    4

Top autori în acest subiect

Salutari.

 

Revin proiectul despre care vorbeam in pagina anterioara, asa cum am spus sunt in lucru la o sursa simetrica de laborator pentru mine, dat fiind faptul ca am LCD 2x24 la dispozitie si un microcontroller destul de permisiv mi-am dorit ca sursa sa fie dotata cu un afisaj digital multiplu, voi avea Tensiune pe sarcina, Curentul de sarcina, Puterea livrata catre sarcina si temperatura radiatorului regulatoarelor de putere. Gama de masurare este 0-35Vcc, 0-6A si 0-100*C. Am dotat dispozitivul cu avertizari sonore si vizuale cu LED pentru atingerea pragurilor maxime de tensiune, respectiv curent, iar la atingerea unui prag presetat de temperatura pe radiator ( momentan 90*C dar valoarea finala va fi setata in urma testelor suplimentare pe sursa finalizata ) microcontroller-ul va decupla alimentarea trafului de putere prin intermediul unui BD139-16 ( terminatia 16 vine de la factor de amplificare mare ) si un releu cu bobina de 3V, totodata se va bloca rularea normala a programului dupa afisarea unui avertisment pe ecran, sursa nemaiputand fi folosita decat dupa resetarea uC de la intrerupatorul din pinul MCLR ( nu am prevazut debounce in soft ca nu stiu cum, sper sa nu fie necesar ca este nevoie doar de un impuls pentru o simpla resetare ).

 

Asa cum probabil se subantelege, alimentarea partii digitale de control se face printr-un traf separat mai mic, vor fi de fapt 2 alimentari Vca separate galvanic intre ele, se va vedea in schema motivul, e un compromis usor de rezolvat ( pentru mine ) necesar datorita lipsei unui senzor de temperatura, pentru asta ma voi folosi de un BD139 in configuratie dioda ( baza legata la colector ) care va fi fixat pe radiator si alimentat de un generator de curent constant ( undeva pe la 13mA ), Vbe variaza in functie de temperatura carcasei si testele au relevat o variatie destul de liniara deci sunt multumit, el va comanda un AO inversor cu amplificare reglabila si referinta ajustabila la neinversoare, care AO va asigura variatia 0-5V necesara uC pentru variatia Vbe in functie de temperatura, am testat-o practic azi si sunt satisfacut de rezultate, calibrarea se poate face destul de usor ajustand amplificarea si eventual referinta, toata ideea partii de temperatura ii apartine lui @Smilex ( de fapt si partea de curent tot a lui este ) caruia ii multumesc mult si pe aceasta cale. Aceasta este schema:

http://img713.imageshack.us/img713/2369/h2p.png

 

Am modificat conexiunile la LCD in beneficiul proiectarii cablajului, tot in acest scop am ales si pinii unde se vor conecta ledurile, buzzer-ul si BD-ul pentru releu, si nu in ultimul rand si pinii unde se fac citirile V, A, si respectiv T, tot in beneficiul cablajului deoarece am ales dinainte o pozitionare pe placa pentru fiecare bloc din schema. Pentru protejarea intrarilor uC voi folosi zennere, am testat niste BZX si-si fac treaba foarte bine, fara a influenta masuratoarea/afisajul.

 

Codul sursa pe care tocmai ce l-am scris si testat in proteus cu succes ar fi asta:

/* Descriere: * Afisaj Digital Multiplu pentru Sursa de Laborator. * Afisare Tensiune 0-35Vcc; Curent 0-6A; Temperatura 0-100*C si Putere. * Protectii: * Avertizare sonora prin Buzzer si vizuala prin LED,   la atingerea pragurilor limita Tensiune sau Curent. * Blocare sursa prin decuplarea alimentarii trafului   principal de catre un releu, si afisare avertisment   pe ecran la atingerea unui prag ales de temperatura. * Configuratie: * Microcontroller PIC16F876 * Oscilator XT 4.000 Mhz * LCD Alfanumeric 2x24 caractere * Autor: Marian. * Iul-2013*///Conexiuni LCDsbit LCD_RS at RB7_bit;sbit LCD_EN at RB6_bit;sbit LCD_D4 at RB5_bit;sbit LCD_D5 at RB4_bit;sbit LCD_D6 at RB3_bit;sbit LCD_D7 at RB2_bit;sbit LCD_RS_Direction at TRISB7_bit;sbit LCD_EN_Direction at TRISB6_bit;sbit LCD_D4_Direction at TRISB5_bit;sbit LCD_D5_Direction at TRISB4_bit;sbit LCD_D6_Direction at TRISB3_bit;sbit LCD_D7_Direction at TRISB2_bit;//Declarare variabileunsigned char ch, ADCx;unsigned int Tensiune, Curent, Temp, ProtU, ProtI, ProtT;unsigned long V, A, Pw, T;//Functie principalavoid main() {     INTCON = 0;                             // Dezactivare intreruperi     TRISA = 0x07;                           // RA0, RA1 si RA2 setate ca intrari     TRISC = 0;                              // Portul C setat ca iesire     PORTC = 0;                              // Resetare port C          Lcd_Init();                             // Initializare LCD     Lcd_Cmd(_LCD_CURSOR_OFF);               // Dezactivare cursor     Lcd_Cmd(_LCD_CLEAR);                    // Stergere Ecran     Delay_ms(1000);                         // Delay 1 secunda     Lcd_Out(1,1,"SursaSimetricaLaborator"); // Mesaj initial 1, prima linie     Lcd_Out(2,1,"Afisaj Digital Multiplu"); // Mesaj initial 1 linia 2     Delay_ms(3000);     Lcd_Cmd(_LCD_CLEAR);                    // Stergere ecran     Lcd_Out(1,4,"0-35V; 0-6A; 0-100C");     // Mesaj initial 2, prima linie     Lcd_Out(2,8,"<By Marian>");             // Mesaj initial 2, linia 2     Delay_ms(3000);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"U:");                      // Afiseaza caracter "U" in prima linie, coloana 1     Lcd_Out(1,10,"T:");                     // Afiseaza caracter "T", prima linie, coloana 10     Lcd_Out(1,19,"C");                      // Afiseaza caracter "C", linia 1, coloana 19     Lcd_Out(2,1,"I:");                      // Afiseaza caracter "I", linia 2, coloana 1     Lcd_Out(2,10,"P:");                     // Afiseaza caracter "P", linia 2, coloana 10           while (1) {            //Achizitie ADC            Tensiune = 0;            Curent = 0;            Temp = 0;            for (ADCx=0; ADCx<10; ADCx++) {            Tensiune += ADC_Read(2);         // Achizitie ADC pentru tensiune            Curent += ADC_Read(1);           // Achizitie ADC pentru curent            Temp += ADC_Read(0);             // Achizitie ADC pentru temperatura            Delay_ms(10);            }                        //Tensiune            Tensiune = Tensiune/ADCx;        // Alocare valoare tensiune            V = (long)Tensiune*3500;         // Converteste rezultat in milivolti            V = V/1023;                      // 0...1023 => 0...3500mV            ch = V/1000;                     // Extrage zeci 10.00            Lcd_Chr(1,3,48+ch);              // Afisare rezultat in format ASCII            ch = (V/100) % 10;               // Extrage unitati 01.00            Lcd_Chr_CP(48+ch);               // Afiseaza rezultat in format ASCII            Lcd_Chr_CP('.');                 // Afiseaza caracter '.'            ch = (V/10) % 10;                // Extrage sutimi  00.10            Lcd_Chr_CP(48+ch);            ch = V % 10;                     // Extrage zecimi  00.01            Lcd_Chr_CP(48+ch);            LCD_Chr_CP('V');                 // Afiseaza caracter 'V'            Delay_ms(10);                        //Curent            Curent = Curent/ADCx;            // Alocare valoare curent            A = (long)Curent*600;            // Convertire rezultat in milivolti            A = A/1023;                      // 0..1023 => 0-600mV            ch = A/1000;                     // Extragere zeci            Lcd_Chr(2,3,48+ch);              // Scrie rezultatul in format ASCII            ch = (A/100) % 10;               // Extragere unitati            Lcd_Chr_CP(48+ch);               // Scrie rezultatul in format ASCII            Lcd_Chr_CP('.');            ch = (A/10) %10;                 // Extragere sutimi            Lcd_Chr_CP(48+ch);               // Scrie rezultatul in format ASCII            ch = A % 10;                     // Extragere zecimi            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('A');                 // Afisare caracter 'A' la final            Delay_ms(10);                        //Temperatura            Temp = Temp/ADCx;                // Alocare valoare temperatura            T = (long)Temp*1000;             // Converteste rezultat in milivolti            T = T/1023;                      // 0...1023 => 0...1000mV            ch = T/1000;                     // Extrage sute 100.00            Lcd_Chr(1,12,48+ch);            ch = (T/100) % 10;               // Extrage zeci 010.00            Lcd_Chr_CP(48+ch);            ch = (T/10) % 10;                // Extrage unitati 001.00            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('.');            ch = (T/1) % 10;                 // Extrage sutimi 000.10            Lcd_Chr_CP(48+ch);            ch = T % 10;                     // Extrage zecimi 000.01            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP(223);                 // Afisare caracter "Grad"            Delay_ms(10);                        //Putere            Pw = V*A/1000;                   // Seteaza valoare Putere            ch = Pw/1000;                    // Extrage sute            Lcd_Chr(2,12,48+ch);            ch = (Pw/100) % 10;              // Extrage zeci            Lcd_Chr_CP(48+ch);            ch = (Pw/10) %10;                // Extrage unitati            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('.');            ch = (Pw/1) % 10;                // Extrage sutimi            Lcd_Chr_CP(48+ch);            ch = Pw % 10;                    // Extrage zecimi            Lcd_Chr_CP(48+ch);            Lcd_Chr_CP('W');                 // Afiseaza "W" la sfarsit            Delay_ms(10);                        //Protectii            ProtU = ADC_Read(2);             // Achizitie ADC pentru protectie Tensiune            if (ProtU == 1023) {            PORTC.F4 = 1;                    // Aprinde LED daca tensiunea este 35V            Sound_Init(&PORTC, 3);           // Initializare buzzer,            Sound_Play(500, 1000);           // si activare avertisment 500Hz, 1 secunda            }            else {            PORTC.F4 = 0;                    // Resetare RC4            }                        ProtI = ADC_Read(1);             // Ahizitie ADC pentru protectie Curent            if (ProtI == 1023) {            PORTC.F5 = 1;                    // Aprinde LED daca curentul este 6A            Sound_Init(&PORTC, 3);           // Initializare buzzer,            Sound_Play(600, 500);            // si activare avertisment 600Hz, 0,5 secunde            }            else {            PORTC.F5 = 0;                    // Resetare RC5            }                        ProtT = ADC_Read(0);             // Achizitie ADC pentru protectie temperatura            if (ProtT > 920) {            PORTC.F2 = 1;                    // Activeaza releu daca temperatura este 90*C            Lcd_Cmd(_LCD_CLEAR);            Lcd_Out(1,8,"PROTECTIE!");       // Afiseaza avertisment pe ecran            Lcd_Out(2,5,"SUPRATEMPERATURA");            break;                           // Blocheaza rularea programului            }            else {            PORTC.F2 = 0;                    // Resetare RC2            }      }}
Si aici link cu simularea:

 

In principiu sunt multumit de rezultate, codul isi face treaba bine ( cel putin in simulator ), ramane sa-l testez si practic cand timpul o va permite, configuratia mi se pare ok deci per ansamblu un dispozitiv util zic eu.

 

Orice comentarii sunt binevenite.

Toate cele bune.

Marian.

Link spre comentariu

            break;                           // Blocheaza rularea programului
Atentie, break nu are in cazul de fata nici o influenta.break se foloseste pentru intreruperea prematura a unei bucle. Cu alte cuvinte, in loc sa scrii
for(i=0; i<10; i++){   if(n>5)  //o conditie ipotetica in cazul careia ar trebui sa intrerupi bucla   {      i=10; //fortezi terminarea buclei   }   else  //fara else programul continua cu ce e dupa blocul if pana se termina blocul for, dupa care retesteaza i   {      // ce aveai de facut in bucla   }}
poti scriefor(i=0; i<10; i++){ if(n>5) { break; //iese imediat din for, nu mai executa nimic din bucla, asa ca nu mai e nevoie de else } // ce aveai de facut in bucla}[/code]Acum sincer n-am idee daca si ce influenta ar putea avea break ala asupra buclei "mari" (while(1)). PS Pana la urma ai lasat protectia in forma originala, n-ai "comasat-o" cu masuratorile.
Link spre comentariu

Pai break am observat ca opreste rularea normala, in sensul ca blocheaza softul in acea pozitie, este adevarat ca else de dupa este inutil si abea acum mi-am dat seama si va fi scos, dar fara break gandesc ca s-ar reveni la inceputul buclei, sau ma insel? o sa simulez si fara el sa vad ce se intampla ca eu doresc ca la detectarea acelui prag softul sa "inghete" in acel loc dupa comenzile alea, si momentan vad ca asta face...PS: Da, am lasat protectiile asa atat pentru ca spatiul total ocupat este oricum sub 50% cat si pentru ca nu am nici pe departe experienta ta, nu inteleg la fel de bine ca tine fineturile asa ca am preferat sa merg pe ceea ce inteleg...LE: am testat acuma si fara break, nu merge, ecranul arata ba acel avertisment ba masuratorile aternant si rapid, deci "break" ramane.

Link spre comentariu

break nu trebuie sa ramana asa. Nu stiu cum e cu simulatorul, da' ma astept ca in montajul fizic sa ai tot felul de efecte ciudate.

Chiar si in simulator, faptul ca ti se blocheaza softul inseamna ca dupa un scurt trebuie sa resetezi scula.

Daca asta e OK pentru tine, atunci lasa-l asa, da' eu ma gandeam ca programul trebuie sa ramana intr-o bucla in care sa aprinda led-uri si sa scrie mesaje de avertizare cat timp sunt probleme, urmand ca atunci cand ai inlaturat problema sa functioneze mai departe.

 

            //Protectii            ProtU = ADC_Read(2);             // Achizitie ADC pentru protectie Tensiune            if (ProtU == 1023) {               PORTC.F4 = 1;                    // Aprinde LED daca tensiunea este 35V               Sound_Init(&PORTC, 3);           // Initializare buzzer,               Sound_Play(500, 1000);           // si activare avertisment 500Hz, 1 secunda               do {                  // asteapta pana se remediaza problema               } while  (ProtU == 1023);                PORTC.F4 = 0;                    // Resetare RC4            }  
Link spre comentariu

LE: Am incercat cu do-while dar nu functioneaza asa cum mi-as dori, asa cum am zis eu vreau ca softul sa se blocheze unde pusesem acel break si in configuratia ce am postat-o exact asta face, ramane sa testez practic ca sa ma lamuresc daca e bine sau nu.PS: Protectia de curent sau tensiune nu influenteaza bucla unde se afla acel break, sunt separate, cand 1 din cele 2 intervin apar si avertizarile sonore si se aprind ledurile, dar functionarea programului nu este afectata, doar la detectarea pragului de temperatura intervine afisarea avertismentului pe ecran si blocarea rularii programului si vad ca exact asta face...

Link spre comentariu

Codul postat anterior era pe post de exemplu.Bineinteles ca daca-ti trebuie doar la temperatura il folosesti doar acolo.Ma rog, pana la urma fa programul cum iti functioneaza mai bine. Daca merge asa cum zici, foarte bine, foloseste-l asa. Numai ca daca se va comporta ciudat sa stii ca se pot trage si de la break-ul ala.

Link spre comentariu

Ai avut dreptate ( mi se pare normal pana la urma ), break-ul nu avea ce sa caute acolo, am testat acum montajul si practic pe breadboard si cu "break" ecranul nici macar nu se initializa ( habar n-am de ce ), prin teste am ajuns la rezolvarea asta care vad ca face fix ce doresc eu:

ProtT = ADC_Read(0);             // Achizitie ADC pentru protectie temperatura            if (ProtT > 920) {            PORTC.F2 = 1;                    // Activeaza releu daca temperatura este mai mare de 90*C            Lcd_Cmd(_LCD_CLEAR);             // Sterge ecran            Lcd_Out(1,8,"PROTECTIE!");       // Afisare mesaj avertisment,            Lcd_Out(2,5,"SUPRATEMPERATURA"); // "protectie supratemperatura"                do {                }                            // Endless loop               while (1);            }            else {            PORTC.F2 = 0;            }

Am ceva dubii in privinta acelui 'else' dar nu cred ca mai modific ceva, nu de alta dar am tot sters si rescris uC-ul si nu vreau sa am surprize neplacute ca la 12F675, ar fi pur si simplu o tragedie sa pierd uC-ul asta, altul n-am de unde...

 

Si un scurt filmulet cu testul ( scuze pentru calitatea foarte slaba dar este facut cu mobilul ), am micsorat putin pragurile de avertizare la tensiune la 34V si curent 5,8A.

 

PS: Multumesc pentru observatii, fara interventia ta n-as fi corectat codul. :aplauze

Link spre comentariu

Multumesc, si multumesc si pentru apreciere dar mai e tare mult pana sa pot afirma ca stiu sa scriu coduri... momentan nu pot spune decat ca am inteles, cu ajutorul tau evident, unele chestii elementare.Acum urmeaza sa proiectez un cablaj pe masura, si nu ma grabesc, vreau sa iasa ceva frumos si cat mai compact, cand va fi gata il voi atasa aici dimpreuna cu toate fisierele necesare oricui ar mai fi interesat.

Link spre comentariu

Revin si cu cablajul pe care tocmai l-am finalizat, zilele urmatoare il voi verifica din nou pentru a fi sigur ca nu sunt greseli apoi urmeaza realizarea sa si dupa finalizarea proiectului voi posta totul la "Proiectul meu"/

Posted Image

 

Toate cele bune.

Link spre comentariu

Frumos pana aici, felicitarile mele, atat pentru soft, cat si pentru cablaj. :da :aplauze :aplauze Am reusit si eu adaptarea/modificarea softului pentru 16F877A.Urmeaza, in functie de timpul liber si terminarea unor proiecte deja demarate, realizarea/testarea LIVE, eventual ceva mici modificari soft/hardware, adaptate cerintelor/necesitatilor mele.Multumesc pentru soft. :da

Link spre comentariu

Multumesc si eu pentru aprecieri, conteaza mult pentru mine.Saptamana asta o sa am si restul componentelor necesare pentru realizarea proiectului meu de sursa ( afisajul fiind evident doar o parte componenta a intregului ), problema o sa fie la realizarea practica a placilor, nu am ce-mi trebuie pentru motoda foto, iar la transfer ar trebui finisaje destul de pretentioase avand in vedere metoda de care ma folosesc, deci ramane de vazut ce fac si cum le fac...

Link spre comentariu

... problema o sa fie la realizarea practica a placilor, nu am ce-mi trebuie pentru motoda foto, iar la transfer ar trebui finisaje destul de pretentioase avand in vedere metoda de care ma folosesc, deci ramane de vazut ce fac si cum le fac...

Sincer, metoda foto este pretentioasa, dar si cea mai buna in regim DIY, se pot realiza cablaje aproximativ calitativ ca cele foto si cu transfer de toner.Momentan nu mai am solutiile necesare, te ajutam cu realizarea cablajelor. :jytuiyuDar pana sosesc componentele tale, poate procur si cele necesare pentru cablaje (nu promit) si incerc sa te ajut.
Link spre comentariu

Revin cu cateva mici rectificari sugerate de @Smilex cu scopul de a renunta la unele strapuri ( erau cam multe ce-i drept ):

Posted Image

 

Acum cred ca este ok si cel mai probabil asa va ramane.

 

PS: Multumesc @GeoMar pentru oferta.

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