Vlad Mihai Postat Septembrie 1, 2013 Partajează Postat Septembrie 1, 2013 eu a folosit transformator de 6-9v, am redresat si filtrat cu un condensator de 100uF, am pus sarcina mica, dar am pus condensatori de ceramici de 100nF pe portul adc, fix langa pinul uC, si a mers ok. Mai era parca o solutie sa te joci cu divizor rezistiv si optocuplor dar e cam nasol..... Link spre comentariu
Marian Postat Septembrie 1, 2013 Autor Partajează Postat Septembrie 1, 2013 M-am gandit acum la o posibila solutie, dezvoltand ideea cu traf mic si redresare fara filtrare, redresare in punte, deci semialternante la 10mS, setez ADC-ul sa faca mai multe citiri intr-un timp de 50mS ( spre exemplu ), el va citi ca si extreme 0V si respectiv varful semisinuosidei atat cat este reteaua in momentul respectiv, sa zicem ca intre 0 si 4Vca, extrag o variabila ca fiind media dintre varfurile citite, deci in cazul de fata 2V, apoi setez alta variabila care sa redea valoarea efectiva inmultind acesti 2V cu raportul dintre RMS-ul pentru varful dat si media citita de variabila anterioara, adica varful de 4V are un RMS de 2,836V, raportul dintre rms si medie 2,836/2/1,418, deci valoarea redata catre afisare ar fi media inmultita cu 1,41 ( am facut niste calcule la mai multe valori si acest 1,41 se pastreaza ). Ce ziceti este ok ideea mea? Gandesc ca atat precizia cat si timpul de raspuns ar fi maxim in acest fel. Link spre comentariu
Mircea Postat Septembrie 1, 2013 Partajează Postat Septembrie 1, 2013 Marian, daca iti contruiesti un peak detector/zero crossing detector ca sa-ti fie trigger pentru achizitionare si faci un sampling (cate masuratori vrei tu) pe o durata de 5ms (jumatate de semi-alternanta). Reduci timpul de citire si-ti raman 15ms pentru alte operatii in PIC. Evident, ar trebui ca sinusoida sa fie cat de cat sinusoidala.Deci, o sa fie mai mult matematica decat electronica in proiectul tau.PS: ce am zis nu difera de ce ai scris tu, doar iti micsoreaza durata achizitiei. Link spre comentariu
Marian Postat Septembrie 1, 2013 Autor Partajează Postat Septembrie 1, 2013 O sa imi cer scuze in avans daca ce zic eu suna cel putin amuzant... Acuma din cate inteleg eu despre peak detector acesta ofera o tensiune relativ constanta la varful sinusoidei, asta face si banala redresare cu electrolitic dupa ea, dar eu am nevoie ca nivelul tensiunii de pe iesire sa scada cat mai rapid in ritm cu nivelul retelei, acel peak detector are nevoie de un anumit condensator, necesar sa mentina nivelul tensiunii la varf si tocmai asta e baiul, timpul de descarcare relativ lent... sau sunt eu pe langa subiect, situatie in care cer scuze pentru aberatii si solicit ceva lamuriri suplimentare... Link spre comentariu
Marian Postat Septembrie 1, 2013 Autor Partajează Postat Septembrie 1, 2013 Am scris si testat acum codul pentru ideea mea cu redresare cu punte fara condensator, 10 citiri la un interval de 5mS fiecare, deci 50mS in total, extragerea mediei de la achizitia ADC intr-o variabila ( care achizitie se face pe impulsuri intre 0 si 5V la interval de 10mS ) apoi convertirea acestei medii in cea rms pe o alta variabila, si intr-un final setarea si afisarea rezultatului final pe LCD, iata codul pentru o gama de test de 0-50Vca ( Microcontroller PIC16F877A la care voi avea cristal de 4Mhz, LCD 2x16 ): //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 VcaMed, VcaRms, Rms;unsigned long Vca;void main() { INTCON = 0; // Dezactivare intreruperi TRISA = 0xFF; // Port A setat ca intrare 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,4,"Afisaj UPS"); // Mesaj initial 1, prima linie Lcd_Out(2,6,"Marian"); // Mesaj initial 1 linia 2 Delay_ms(3000); Lcd_Cmd(_LCD_CLEAR); while (1) { //Achizitie ADC VcaMed = 0; for (ADCx=0; ADCx<10; ADCx++) { VcaMed += ADC_Read(0); Delay_ms(5); } //Vca Rms = 1,4142; VcaMed = VcaMed/ADCx; VcaRms = VcaMed*Rms; Vca = (long)VcaRms*5000; // Converteste rezultat in milivolti Vca = Vca/1023; // 0...1023 => 0...5000mV ch = Vca/1000; // Extrage zeci 10.00 Lcd_Chr(1,1,48+ch); // Afisare rezultat in format ASCII ch = (Vca/100) % 10; // Extrage unitati 01.00 Lcd_Chr_CP(48+ch); // Afiseaza rezultat in format ASCII Lcd_Chr_CP('.'); // Afiseaza caracter '.' ch = (Vca/10) % 10; // Extrage sutimi 00.10 Lcd_Chr_CP(48+ch); ch = Vca % 10; // Extrage zecimi 00.01 Lcd_Chr_CP(48+ch); LCD_Chr_CP('V'); // Afiseaza caracter 'V' Delay_ms(10); } } Testul a fost facut in proteus si rezultatul este destul de ok, a fost totusi nevoie de un cond de 10n pus pe intrarea uC pentru a stabiliza rezultatul, acuma ideea pare a fi functionala, evident ar urma zilele astea si testul practic la care voi rescrie codul cel mai probabil pentru o gama de 0-260 ( la mine reteaua ajunge si pe la 245, uneori chiar aproape de 250 ), o problema ar putea fi reprezentata de catre imprecizia cauzata de vf la diodele cu care se va face redresarea, problema fiind mai ales variatia acestui Vf in functie de temperatura, curent, etc... am vazut o redresare mai precisa cu AO si dioda pe iesire dar impulsurile asa ar fi la 20mS si ar trebui sa maresc timpul de achizitie ADC, nu ma incanta prea tare chestia asta avand in vedere ca tot acest uC va trebui sa mai indeplineasca si alte functii ( probabil inca vre-o 5 functii, sau ceva de genul ), apoi ar fi necesara alimentare dubla pentru acel AO, iarasi nu ma incanta treaba asta... in fine o sa testez cu niste diode skhottky mici care au un Vf mai mic, poate si eroarea ar fi mai mica... Daca aveti alte sugestii nu ezitati. Link spre comentariu
GeoMar Postat Septembrie 1, 2013 Partajează Postat Septembrie 1, 2013 Interesant proiect de UPS @marian. Sa inteleg ca "Inima" UPS-ului v-a fi PIC 16F877A? Nu de alta dar as fi interesat de proiect, am PIC-ul (urile)si chiar este util, pe la mine se intrerupe destul de des energia de la CEZ. Succes in continuare. Link spre comentariu
Marian Postat Septembrie 1, 2013 Autor Partajează Postat Septembrie 1, 2013 Salutari @GeoMar si multumiri pentru interes. Tocmai faptul ca si la mine pica reteaua enervant de des face necesara neaparat prezenta unui UPS, detin unul luat acum vreo cativa ani de pe la magazinul din Alexandria dar in ultimele luni randamentul foarte mic al acestuia m-a convins ca tre sa iau masuri, initial vroiam sa-i schimb doar convertorul ( unul cu traf de retea, deci frecventa retelei ), dar apoi mi-am zis ca nu are rost sa ma mai complic si ca cel mai bine este sa fac un altul de la zero. Voi avea un convertor Push-Pull la aproximativ 35Khz, partea de control va fi cu TL494 ( imi place simplitatea utilizarii si flexibilitatea ) si driver pentru mosfeti unul dedicat din gama TC. Totul se axeaza pe randament cat mai bun, de aceea am ales si mosfeti cu Rds cat mai mic mi-am permis ( cam 6m Ohm ), si tot pentru acest considerent ( plus simplitatea aferenta ) am renuntat la puntea H, in schimb voi avea redresare cu niste diode cu Vf mai mic si un mic electrolitic dupa, consumatorii intotdeuna vor fi unitatea PC-ului si monitorul acestuia, ambele alimentate de surse in comutatie, astfel incat nu vor protesta la prezenta Vcc pe alimentare ( deja am testat asta ). Voi redresa deasemenea si reteaua si o voi filtra cu un electrolitic relativ mic, comutarea se va face cu un releu cu bobina alimentata de la retea direct, redresez ambele surse de alimentare ( reteaua si convertorul ) pentru securitatea contactelor releului, am testat deasemenea ( totul practic evident ) si ideea asta si releul pare a face fata cu brio regimului de lucru ( arc electric aproape inexistent ) iar PC-ul nu este afectat, adica nu se opreste. Ar mai fi cateva detalii de pus la punct, inca lucrez la schema cu ajutorul lui @Smilex, cand va fi gata ma voi apuca si de proiectarea cablajului si ti le voi inainta pe PM ( pe forum voi pune totul la proiecte cand va fi finalizat ). Microcontroller-ul va juca rol de monitorizare in principiu, va citi si afisa tensiunea acumulatorului, curentul de incarcare al acestuia, tensiunea retelei, si a iesirii convertorului, se vor afisa fiecare in functie de ce alimenteaza PC-ul la momentul respectiv, adica daca reteaua este prezenta LCD-ul va afisa asta si valoarea tensiunii de la retea, daca reteaua nu este prezenta atunci LCD-ul va afisa faptul ca si anume convertorul este activ si totodata valoarea tensiunii acestuia, tot pentru aceasta situatie de lipsa a retelei voi mai avea si un buzzer care sa avertizeze sonor despre acest lucru. Microcontroller-ul totodata va proteja si acumulatorul de descarcare profunda ( acumulator auto la 44Ah achizitionat zilele trecute ), prin blocarea convertorului la atingerea unui prag minim anume ales al tensiunii pe acesta, inca nu m-am decis care va fi acel prag, asta va fi dupa ceva teste practice si ceva documentare specifica. In fine, mai sunt multe detalii de pus la punct, maine sper sa am timp sa testez practic codul de mai sus si apoi sa mai finisez schema convertorului si restul codului pentru uC... e destul de lucru asadar. Link spre comentariu
Mircea Postat Septembrie 1, 2013 Partajează Postat Septembrie 1, 2013 solicit ceva lamuriri suplimentare...Acuma citind toate intrebarile tale nu mai este asa clar cum era... Nu vei avea nevoie sa redresezi semnalul cu punte si condensator. Uite care era ideea.1. iei un transfo cu secundarul max 10Vpp2. treci cei 10V printr-un repetor rail-to-rail (sa zicem) alimentat numai pozitiv, deci redresezi monoalternanta3. aplici acest semnal la PIC si tot masori semnalul pana cand detectezi varful sinusiodei, aici incepi achizitia pentru masura propriu zisa pana detectezi iar un zero4. transformi masuratorile in valoarea medie5. deja stii frecventa deci te re-intorci la masurare peste 14-14,5ms sa detectezi iar un peak6. revii la punctul 4. repeti la infinit 4,5,6.N-am folosit un astfel de sistem de masurare, dar asta era baza ideii de mai sus.Partea cu zero crossing cade din cauza zgomotului, dar poate fi implementata de asemenea, tot pentru un sfert de perioada. Link spre comentariu
Marian Postat Septembrie 2, 2013 Autor Partajează Postat Septembrie 2, 2013 Cred ca am inteles ideea, insa o problema ar fi acel zero care trebuie detectat ca media sa fie una corecta, cu alimentare simpla greu gasesti AO sa redea pana la 0, exista acea saturatie inevitabila a iesirii, la o variatie 0-5V maxim admisa pe intrarea uC, cateva zeci de mV eroare la citirea zeroului poate fi semnificativ... apoi redresarea monoalternanta presupune impulsuri la 20mS, si pentru mai multe citiri ar presupune un timp prea mare dedicat doar acestei operatii pentru uC, ori n-am inteles eu prea bine... oricum voi testa si practic azi ( sper ) metoda testata ieri in proteus cu succes, sa vad ce si cum rezolv, daca comportamentul este ok atunci e bine. Link spre comentariu
Marian Postat Septembrie 2, 2013 Autor Partajează Postat Septembrie 2, 2013 Am testat acum practic ideea care ieri in proteus mergea ok, si in realitate nu e la fel ( un alt exemplu al faptului ca simularea nu coincide intotdeauna cu realitatea ), rezultatul pe LCD nu doar ca nu era deloc stabil asta in ciuda decuplarii pinului RA0, dar nici nu era nici pe departe pe langa valoarea retelei, am renunta la complicatii si am ales sugestia lui @Vlad, adica redresare, cond de 100uF ( a dat cele mai bune rezultate ) plus 100n pe pinul RA0, si un semireglabil multitura de 20k al carui cursor este conectat la RA0, iar capetele pe electroliticul de filtrare, avand ca scop calibrarea indicatorului, in felul asta nu este necesar un traf cu o tensiune precisa, deci o mai mare flexibilitate, si in uC bucata asta de cod: while (1) { //Achizitie ADC Retea = 0; for (ADCx=0; ADCx<10; ADCx++) { Retea += ADC_Read(0); Delay_ms(5); } //Vca Retea = Retea/ADCx; Vca = (long)Retea*2600; // Converteste rezultat in milivolti Vca = Vca/1023; // 0...1023 => 0...2600mV ch = Vca/1000; // Extrage sute 100.00 Lcd_Chr(1,2,48+ch); ch = (Vca/100) % 10; // Extrage zeci 010.00 Lcd_Chr_CP(48+ch); ch = (Vca/10) % 10; // Extrage unitati 001.00 Lcd_Chr_CP(48+ch); Lcd_Chr_CP('V'); Delay_ms(10); } Avand in vedere ca de precizia indicatiei/masuratorii, nu depinde nimic important ci are doar rol informativ n-am pentru ce sa ma mai complic, oricum raspunsul vad ca este destul de bun, tot din acest motiv renunt la orice zecimale, si ca bonus economisesc caractere la LCD. In fine, ideea este ca ar merge asa, ( probabil si cealalta solutie ar putea fi optimizata dar nu am experienta necesara sa o fac ) si asa ramane, evident o sa mai finisez eu codul in functie de preferinte si voi adauga si celelalte functii, deci voi reveni. Toate cele bune. Link spre comentariu
Marian Postat Septembrie 2, 2013 Autor Partajează Postat Septembrie 2, 2013 Nu mai pot edita anterior astfel incat postez in continuare, si er scuze pentru post multiplu. M-am tot gandit la motivul pentru care solutia la care ma gandisem initial ( redresare fara condensator, medierea mai multor citiri si calculul rms apoi ) nu functiona corect si mi-am amintit de ce am citit intr-un document care m-a initiat in limbajul C++, si anume trunchierea unui numar, pentru calculul valorii finale declaram o variabila pe nume Rms sub forma de Integer, tocmai aici era baiul penca acest tip de variabila elimina zecimalele, deci media se inmultea doar cu 1, @thunderer ( caruia ii multumesc si pe aceasta cale ) mi-a sugerat sa declar acea variabila ca si float, am facut-o si problema a fost rezolvata, rezultatul acum este cel corect, am mai modificat eu citirile, initial se facea pe o perioada de 50mS, cate 1 citire la fiecare 5mS, m-am gandit ca in felul asta extremele pot fi pur si simplu "sarite" de acea pauza devreme ce cifra 5 este un subdivizor direct al perioadei retelei, am ales un numar ( mai mult arbitrar ) de 36 de citiri la cate 1mS fiecare, rezultatul este codul asta: //Declarare variabileunsigned char ch, ADCx;unsigned int VcaMed, VcaRms ;unsigned long Vca;float Rms;void main() { INTCON = 0; // Dezactivare intreruperi TRISA = 0xFF; // Port A setat ca intrare 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,4,"Afisaj UPS"); // Mesaj initial 1, prima linie Lcd_Out(2,6,"Marian"); // Mesaj initial 1 linia 2 Delay_ms(3000); Lcd_Cmd(_LCD_CLEAR); while (1) { //Achizitie ADC VcaMed = 0; for (ADCx=0; ADCx<36; ADCx++) { VcaMed += ADC_Read(0); Delay_ms(1); } //Vca Rms = 1.4142; VcaMed = VcaMed/ADCx; VcaRms = VcaMed*Rms; Vca = (long)VcaRms*2600; Vca = Vca/1023; ch = Vca/1000; Lcd_Chr(1,1,48+ch); ch = (Vca/100) % 10; Lcd_Chr_CP(48+ch); ch = (Vca/10) % 10; Lcd_Chr_CP(48+ch); LCD_Chr_CP('V'); Delay_ms(10); }}Se afiseaza rezultatul corect si raspunsul este foarte rapid, insa cifra unitatilor este foarte instabila, ce-i drept si reteaua variaza in mod relativ constant, as dori sa gasesc o metoda care sa mai "linisteasca" unitatile chiar daca ar intarzia putin raspunsul ca asa e greu de citit... Link spre comentariu
Kreator Postat Septembrie 2, 2013 Partajează Postat Septembrie 2, 2013 As face altfel: Divizez rezistiv 220V la 5V. Un Optocuplor MOC care "simte" trecerea prin zero a retelei, si care comanda RB0/INT. Asta e T0. Apoi stau pana aproape de T/4 = 5 ms si fac trei citiri: una la 4.99 ms si citesc valoarea U-1, apoi la 5.00 ms iar citesc U si la 5.01ms U+1 (de ex cu cat le citesc mai apropiate cu atat am valoarea mai precisa). Daca U-1 < U > U+1 atunci U este varful sinusoidei, daca U-1 > U atunci micsorez baza de timp daca U+1>U maresc baza de timp. Reiau procesul pana se indeplineste conditia U-1 < U > U+1. Asa se face doar trei citiri intr-o perioada, restul timpului ramanand pt bunadispozitie a uC Link spre comentariu
Marian Postat Septembrie 2, 2013 Autor Partajează Postat Septembrie 2, 2013 Cred ca am inteles logica, insa mi se par complicatii prea mari pentru citirea cu rol pur informativ/aproximativ a retelei, am testat cu ceva conzi pe intrarea uC si am observat ca se poate obtine o stabilitate satisfacatoare a afisarii, prin tatonari am ajuns la 2,2u electrolitic, motivul ar putea fi fi din cate vad un anumit zgomot la punctul de 0V ( extrem de scurt dar oarecum zgomotos ), electroliticul acopera acel zgomot, ce-i drept valoarea indicatiei creste dar doar cu cateva unitati, si semireglabilul dinaintea sa poate compensa reducand amplitudinea varfurilor, se obtine practic cam acelasi raport, afisajul este mult mai stabil, modificarile sunt practic identice cu ale multimetrului pus direct la priza ceea ce gasesc a fi un rezultat suficient de satisfacator, si cel mai probabil asa va ramane, o sa mai testez maine sa fiu sigur ca sunt multimit de rezultat si apoi mai vedem.Multumiri tuturor pentru interes. Link spre comentariu
Mircea Postat Septembrie 3, 2013 Partajează Postat Septembrie 3, 2013 ... cifra unitatilor este foarte instabila...Daca te deranjeaza cifra care "joaca", atunci fa si tu afisarea pe LCD la secunda, sa zicem, nu instantaneu. Link spre comentariu
Marian Postat Septembrie 3, 2013 Autor Partajează Postat Septembrie 3, 2013 Am progresat ceva cu codul ( atat cat am avut timp de el ), insa m-am cam impotmolit o tzara, eu vreau ca uC sa sesizeze cand reteaua este prezenta si sa afiseze asta pe display printr-un text "Retea" si dedesubt sa se afiseze tensiunea, cand reteaua pica textul sa se schimbe cu "Smps" si dedesubt sa se afiseze tensiunea de la convertor ( iesirea lui ), sesizarea prezentei retelei o fac cu un releu care se alimenteaza la 220V, care comanda o intrare a uC, cand reteaua este prezenta releul pune intrarea la masa ( deci pe 0 logic ) si se executa codul respectiv atribuit, cand reteaua pica, releul declanseaza si intrarea este pusa la +Vcc de catre un rezistor deci trecuta pe 1 logic, fac asta cu bucla if/else: TRISD = 0xFF; if (PORTD.F1=0) { Lcd_Out(1,9,"RETEA"); //Retea //Rms = 1.4142; //VcaMed = VcaMed/ADCx; //VcaRms = VcaMed*Rms; //VR = (long)VcaRms*2600; //VR = VR/1023; //ch = VR/1000; //Lcd_Chr(2,9,48+ch); //ch = (VR/100) % 10; //Lcd_Chr_CP(48+ch); //ch = (VR/10) % 10; //Lcd_Chr_CP(48+ch); //LCD_Chr_CP('V'); //Delay_ms(10); } else { Lcd_Out(1,9,"SMPS "); //Convertor //VccSMPS = VccSMPS/ADCx; //VS = (long)VccSMPS*3500; //VS = VS/1023; //ch = VS/1000; //Lcd_Chr(2,9,48+ch); //ch = (VS/100) % 10; //Lcd_Chr_CP(48+ch); //ch = (VS/10) % 10; //Lcd_Chr_CP(48+ch); //LCD_Chr_CP('V'); //Delay_ms(10); } Partile comentate sunt scoase temporar de mine penca gresisem ceva si aveam eroare pe afisaj ( se tot reseta ), am eu timp de ele, acuma problema este alta, conform buclei daca RD1 este 0 logic atunci ar trebui sa se afiseze textul ala "retea" in locul atribuit pe display, daca nu este 0 logic ( deci implicit nu poate fi decat 1 logic ) atunci sa se schimbe textul asa cum e acolo. La mine textul se schimba dar exact invers, adica atunci cand RD1 este 0 apare SMPS, cand este 1 apare RETEA, am schimbat comanda de la if si am pus in loc de 0, 1 dar aceeasi chestie, nu pricep unde am gresit... ma puteti lamuri? Link spre comentariu
Postări Recomandate
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 contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum