Sari la conținut
ELFORUM - Forumul electronistilor

Numarator cu PIC16F628A


Lonerider

Postări Recomandate

Insist ( chiar cu riscul de a greși )  , problema nu e schema numărătorului - cu PIC, cu MMC , etc . Integratele trebuie bine decuplate , alimentările trebuie să fie curate , firele trebuie să fie cât mai scurte , cablajele corect proiectate și executate ( în special ca trasee de masă ) , eventuale surse de paraziți ( contacte , relee, etc ) snubber-ite , etc.

Faptul că s-a făcut ”fix ca pe net ” nu e un argument . Nu știm cum i-a mers ăluia de-a postat-o . De multe ori , în euforia reușitei ( de înțeles, de altfel ) autorii sar multe verificări și postează rezultate netestate  temeinic. 

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

Top autori în acest subiect

  • Lonerider

    18

  • Liviu M

    9

  • Florian Ciobanu

    5

  • UDAR

    4

Top autori în acest subiect

Salut! Un banal numarator pentru o masina de bobinat era parca prin revistele tehnium. Pe vremea aceeia nu se lucra cu microcontroller era facut cu un banal calculator de buzunar se lipeau doua fire la butonul = unde se conecta un intrerupator cuplat la masina de bobinat si cand facea o tura se inchidea circuitul. Se tasta la calculator 1+1= si  dadeam la manivela  :rade: . Am expus ideea fiindca  poate  sunt persoane care vor sa faca un numarator mai repede si fara prea multe materiale.

 

ca idee, mai exista si MMC22925, numerator cu 4 digiti, simple si efficient

Salut.

De multe ori (de cele mai multe ori) avansul tehnologiei ne depărtează de lucrurile simple (şi aici nu ma scuz nici pe mine), însă unele componente electronice, înglobând mai multe funcţii sau funcţiuni, ne ajută (sau ar trebui), prin simplificarea schemei, doar, (şi implict al numărului de componente active/pasive), la executarea unor montaje, teoretic, mai simple în regim diy, mai ales că unele componente "de altădată" e posibil/probabil să nu mai fie de actualitate sau de găsit... Ce vremuri, când veneam la Micro Electronica după integrate, pentru echipamente folosite la fostul/fosta CFR...

 

@UDAR, nu mă lasă forumul să postez şi citatul tău de aici: http://www.elforum.info/topic/114502-numarator-cu-pic16f628a/?p=1356098, dar...

 

Aici e o poză aproximativă a locului unde va fi amplasată cutia din plastic cu numărătorul...

Neştiind exact funcţionarea, vis-a-vis de decuplări, pot să spun, doar, că motorul folosit pentru numărătorul respectiv este unul alimentat în ca [motor pentru maşină de cusut, cu pedală "reostat", (de fapt un număr de rezistenţe fixe şuntate printtr-o serie de contacţi)], având doi condensatori de 100nF/350Vca, înseriaţi între perii, cu borna comună legată la şasiul motorului. Montajul numărătorului se află în proximitatea motorului (unde este display-ul), într-o altă cutie, din plastic, la 5-7 cm faţă de motor. Dacă asta influenţează, atunci e bai, tre' să mut numărătorul altundeva.

 

http://s20.postimg.org/ntfqyj8f1/IMG_20160326_191540.jpg

Editat de Lonerider
Link spre comentariu

incearca prima data sa bagi numaratorul intr-o carcasa din tabla (de otel) legata la masa "utilajului", dupa stabilizator , pe tensiunea de 5 volti,  pune musai un condesator electrolitic de 100 micro si unul de 100n. (ma omoara autocorectura forumului si sunt obligat mereu sa editez continutul)

Editat de Florian Ciobanu
Link spre comentariu

Insist ( chiar cu riscul de a greși )  , problema nu e schema numărătorului - cu PIC, cu MMC , etc . Integratele trebuie bine decuplate , alimentările trebuie să fie curate , firele trebuie să fie cât mai scurte , cablajele corect proiectate și executate ( în special ca trasee de masă ) , eventuale surse de paraziți ( contacte , relee, etc ) snubber-ite , etc.

Faptul că s-a făcut ”fix ca pe net ” nu e un argument . Nu știm cum i-a mers ăluia de-a postat-o . De multe ori , în euforia reușitei ( de înțeles, de altfel ) autorii sar multe verificări și postează rezultate netestate  temeinic. 

 

 Prima schema postata are intrarea de impuls pe un simplu I/O , adica se face verificare daca pin-ul este High/Low, daca impulsul vine cand PIC-ul e ocupat de randarea digitului x atunci a si pierdut impulsul respectiv. Deci acea schema e de la inceput ori prost gandita ori nu a fost conceput pentru viteza mare, de acea am zis ca la 22impulsuri/s trebuie facut cu pin IOC si intrerupere de soft pentru numarare. 

 

Eu am un senzor hall pe un cablu lung de 10+ metrii si merge fara probleme pe un pin IOC intr-adevar ca este alimentat de o baterie auto incarcata de panou solar deci nu am probleme de zgomot, eu l-am folosit la un anemometru, la detectarea a x rotatii / 5s da un semnal. 

Editat de bandi12
Link spre comentariu

Păi ceea ce spui tu întărește ce am spus eu . Trebuie lucrat cu grijă - atât soft cât și hard . Apropo de soft , recunosc că nu mi-am bătut capul să mă uit peste el , principiile sunt însă aceleași . 

 

PS Rămânând la hard . Așa, după poză , firele ale sunt cam lungi și nu văd nici măcar un condensator pe placă . Plus ce a spus @bandi12 mai sus... 

Editat de UDAR
Link spre comentariu

 de acea am zis ca la 22impulsuri/s trebuie facut cu pin IOC

 

 

Four of PORTB’s pins, RB<7:4>, have an interrupt-on-change feature.

Link spre comentariu

Am caut pe acest forum o sectiune cu scheme realizate cu circuite logice: porti logice, numaratoare, decodificatoare, multiplexoare,... pt ca, de la aceste circuite s-a ajuns la memorii, microcontrolere, procesoare,... 

 

Daca exista si nu am vazut eu, dati-mi un link, iar daca nu exista, poate se va face si o sectiune pt aeste componente.

 

Am incercat sa fac un numarator cu pic16f628, dar la o frecventa mai mare de 10Hz (adica 10 impulsuri pe secunda), are abatere in minus la numarare.

 

Am cautat un MMC22925, dar se gaseste mai greu.

 

Un CD4033 se gaseste, si lucreaza la o frecventa maxima de 6MHz.

Am facut simulare in PROTEUS la o frecventa de 1000Hz si pare in regula.

Editat de Vizitator
Link spre comentariu

Daca semnalul de numarat e curat, cred ca cel mai simplu e sa folosesti TMR0 cu clock extern. Legi semnalul de numarat la intrarea de clock pentru TMR0 si numeri.

Multa lume foloseste varianta asta cu un oscilator de 32 de kHz ca sa faca ceasuri, nu vad de ce n-ar merge la un semnal mai lent.

 

Counter mode is selected by setting the T0CS bit. In this mode Timer0 will increment either on every rising or falling edge of pin RA4/T0CKI. The incrementing edge is determined by the source edge (T0SE) controlbit (OPTION<4>). Clearing the T0SE bit selects the rising edge. Restrictions on the external clock input are discussed in detail in Section 6.2. 

Link spre comentariu

 Am aest cod pentru numarator, este functional (testat la 100Hz, chiar 1000Hz) dar cu doua probleme.

1 - la punerea sub tensiune afisajul afiseaza 8888, desi number = 0;

2 - la resetarea microcontrollerului (MCRL), ramane numarul la care s-a oprit numararea;

   - la o noua apasare pe butonul UP numaratorul numara corespunzator.

 

Ajutorul vostru este binevenit si pentru Lonerider.

#define UP  portb.f7unsigned short mask(unsigned short num){/*switch (num)      //Catod Comun {  case 0 : return 0x3F;  case 1 : return 0x06;  case 2 : return 0x5B;  case 3 : return 0x4F;  case 4 : return 0x66;  case 5 : return 0x6D;  case 6 : return 0x7D;  case 7 : return 0x07;  case 8 : return 0x7F;  case 9 : return 0x6F;  }*/    switch (num)      //Anod Comun    (utilizeaza DotMatrix3 din programe) {  case 0 : return 0xC0;  case 1 : return 0xF9;  case 2 : return 0xA4;  case 3 : return 0xB0;  case 4 : return 0x99;  case 5 : return 0x92;  case 6 : return 0x82;  case 7 : return 0xf8;  case 8 : return 0x80;  case 9 : return 0x90;  }}/*******Endless mask***********/unsigned short shifter, portb_index;unsigned int digit, number;unsigned short portb_array[4];void interrupt(){ PORTA = 0;                           // Turn off all 7seg. displays; PORTB = portb_array[portb_index];    // Bring appropriate value to PORTB; PORTA = shifter;                     // Turn on appropriate 7seg. display; //move shifter to next digit; shifter <<= 1; if(shifter > 15u) shifter = 1; //increment portb_index; portb_index ++ ; if (portb_index > 3u) portb_index = 0;                     //turn on 1st, turn off 2nd 7 seg.; TMR0 = 0;                            //reset TIMER0 value; INTCON = 0x20;                       //clear T0IF, Bit T0IF=0, T0IE=1; }void main(){ number = 0;                          //initial value;  CMCON |= 7;                          // Set AN pins to Digital I/O; OPTION_REG = 0x80;                   // Set timer TMR0; digit = 0; portb_index = 0; shifter = 1; TMR0 = 0; INTCON = 0xA0;                  // Disable interrupt PEIE,INTE,RBIE,T0IE  TRISA = 0x20;                      // All port A pins are configured as outputs PORTA = 0;                      // Turn off displays TRISB = 0x80;                           // All port D pins are configured as outputs PORTB = 0;                           // Turn off all display segments TRISB7_bit = 1;       do {     if(!UP == 0){     number++;              Delay_ms(2);              while(UP);              {              PORTB = number;              }     }     digit = number % 10u;            //extract ones digit;     portb_array[0] = mask(digit);    //and store it to PORTB array;     digit = (number / 10u) % 10u;    //extract tens digit;     portb_array[1] = mask(digit);    //and store it to PORTB array;     digit = (number / 100u) % 10u;   //extract hundreds digit;     portb_array[2] = mask(digit);    //and store it to PORTB array;     digit = number / 1000u;          //extract thousands digit;     portb_array[3] = mask(digit);    //and store it to PORTB array;     } while(1);                      //Endless loop;}                                     

 

Editat de Vizitator
Link spre comentariu

Salut,

dupa parerea mea nu e nevoie de functia mask, e suficient un array si economisesti niste apeluri de functii. Apelurile mask(numar) le inlocuiesti cu mask[numar]. Probabil nu schimba prea multe, da' poate va fi o idee mai rapid.

 

A, si in functia interrupt() faci INTCON = 0x20. Asta inseamna ca dezactivezi intreruperile (GIE = 0). Esti sigur ca mai functioneaza afisarea?

Ar trebui sa folosesti aceeasi valoare ca la inceputul lui main() - 0xA0.

 

In rest, habar n-am de ce afiseaza aiurea la inceput si dupa reset.

#define UP  portb.f7#define ANOD_COMUN#ifdef ANOD_COMUNunsigned char mask[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; //anod comun#elseunsigned char mask[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; //catod comun#endifunsigned short shifter, portb_index;unsigned int digit, number;unsigned short portb_array[4];void interrupt(){ PORTA = 0;                           // Turn off all 7seg. displays; PORTB = portb_array[portb_index];    // Bring appropriate value to PORTB; PORTA = shifter;                     // Turn on appropriate 7seg. display; //move shifter to next digit; shifter <<= 1; if(shifter > 15u) shifter = 1; //increment portb_index; portb_index ++ ; if (portb_index > 3u) portb_index = 0;                     //turn on 1st, turn off 2nd 7 seg.; TMR0 = 0;                            //reset TIMER0 value; INTCON = 0xA0;                       //clear T0IF, Bit T0IF=0, T0IE=1; GIE=1 }void main(){ number = 0;                          //initial value;  CMCON |= 7;                          // Set AN pins to Digital I/O; OPTION_REG = 0x80;                   // Set timer TMR0; digit = 0; portb_index = 0; shifter = 1; TMR0 = 0; INTCON = 0xA0;                  // Disable interrupt PEIE,INTE,RBIE,T0IE  PORTA = 0;                      // Turn off displays TRISA = 0x20;                      // All port A pins are configured as outputs PORTB = mask[portb_index];     // afiseaza 0 TRISB = 0x80;                  // All port D pins are configured as outputs// TRISB7_bit = 1;       do {    if(UP){       number++;       Delay_ms(2);       while(UP){ //mie imi place sa scriu explicit buclele astea goale           ;       }       PORTB = number;     }     digit = number % 10u;            //extract ones digit;     portb_array[0] = mask[digit];    //and store it to PORTB array;     digit = (number / 10u) % 10u;    //extract tens digit;     portb_array[1] = mask[digit];    //and store it to PORTB array;     digit = (number / 100u) % 10u;   //extract hundreds digit;     portb_array[2] = mask[digit];    //and store it to PORTB array;     digit = number / 1000u;          //extract thousands digit;     portb_array[3] = mask[digit];    //and store it to PORTB array;  } while(1);                      //Endless loop;}                                     

LE Ce frecventa de ceas folosesti?

Link spre comentariu

M-am jucat putin cu functia interrupt, am rearanjat ordinea operatiilor si mi-a iesit:

void interrupt(){ PORTA = 0;                           // Turn off all 7seg. displays; PORTB = portb_array[portb_index];    // Bring appropriate value to PORTB; PORTA = shifter;                     // Turn on appropriate 7seg. display; //increment portb_index; portb_index = (portb_index++)%4 ;    //ne intereseaza doar valorile 0..3 => restul impartirii cu 4 //move shifter to next digit; shifter = 1 << portb_index; TMR0 = 0;                            //reset TIMER0 value; INTCON = 0xA0;                       //clear T0IF, Bit T0IF=0, T0IE=1; GIE=1}
Link spre comentariu

Va salut. Am gasit si aceasta schema impreuna cu fisierul .hex: http://scopionz.blogspot.com/2014/04/4-digit-ssd-up-counter-pic16f628a.html. Este mai buna sau mai eficienta decat cea postata la inceputul topicului? Se poate adapta pentru anod comun?

Am testat acest proiect si merge foarte greu.

La o frecventa de 10Hz nici nu numara.

 

 

Ai un pic rabdare ca ce am testat si postat mai sus merge si la 200Hz (200 impulsuri pe secunda), dar am ceva modificari de facut dupa modificarile postate de Liviu.

 

Am incercat modificarile propuse de Liviu dar tot la fel face: Afiseaza 8888 la initializare, nu reseteaza numaratorul decat la o noua apasare pe butonul UP.

 

Liviu, am testat programul cu 4MHz dar am observat ca, cu 8MHz merge mai bine.

 

Stiu Liviu ca tie iti place sa comentezi liniile si te apreciez pt asta. Am vazut multe postari de ale tale si chiar mai ajutat in unele postari de ale mele. Eu inca invat  asta.

Editat de Vizitator
Link spre comentariu

Am incercat modificarile propuse de Liviu dar tot la fel face: Afiseaza 8888 la initializare, nu reseteaza numaratorul decat la o noua apasare pe butonul UP.

Pai am zis de la inceput ca nu stiu de la ce poate fi.

Modificarile mele sunt mai mult vizuale. Singura imbunatatire ar putea veni de la inlocuirea functiei mask cu matricea mask, ca renunti la apeluri de functii.

Pe de alta parte, in main ai:

Delay_ms(2). Numai asta si-ti limiteaza frecventa de numarare la maxim 1/0.002 = 500 Hz. Incearca fara linia respectiva.

Link spre comentariu

Pai am zis ...

Gata, am facut o modificare de care ma doare capul si n-am sa o inteleg. Poate se putea mai simplu, dar functioneaza.

Oricum Loneridar a scris in postul#6 ca :... iar eu o voi folosi undeva la maxim 7 impulsuri  .

//***********Header*************/#define UP  porta.f4unsigned short mask(unsigned short num){/*switch (num)      //Catod Comun {  case 0 : return 0x3F;  case 1 : return 0x06;  case 2 : return 0x5B;  case 3 : return 0x4F;  case 4 : return 0x66;  case 5 : return 0x6D;  case 6 : return 0x7D;  case 7 : return 0x07;  case 8 : return 0x7F;  case 9 : return 0x6F;  }*/  switch (num)      //Anod Comun    (utilizeaza DotMatrix3 din programe) {  case 0 : return 0xC0;  case 1 : return 0xF9;  case 2 : return 0xA4;  case 3 : return 0xB0;  case 4 : return 0x99;  case 5 : return 0x92;  case 6 : return 0x82;  case 7 : return 0xf8;  case 8 : return 0x80;  case 9 : return 0x90;  }}/*******Endless mask***********/unsigned short shifter, portb_index;unsigned int digit, number;unsigned short portb_array[4];void interrupt(){ PORTA = 0;                           // Turn off all 7seg. displays; PORTB = portb_array[portb_index];    // Bring appropriate value to PORTB; PORTA = shifter;                     // Turn on appropriate 7seg. display; //move shifter to next digit; shifter <<= 1; if(shifter > 15u) shifter = 1; //increment portb_index; portb_index ++ ; if (portb_index > 3u) portb_index = 0;                     //turn on 1st, turn off 2nd 7 seg.; TMR0 = 0;                            //reset TIMER0 value; INTCON = 0xA0;                       //clear T0IF, Bit T0IF=0, T0IE=1; }void main(){ CMCON |= 7;                          // Set AN pins to Digital I/O; OPTION_REG = 0x80;                   // Set timer TMR0; digit = 0; portb_index = 0; shifter = 1; TMR0 = 0; INTCON = 0xA0;                  // Disable interrupt PEIE,INTE,RBIE,T0IE TRISA = 0xF0;                   // All port A pins are configured as outputs PORTA = 0;                      // Turn off displays TRISB = 0;                        // All port D pins are configured as outputs PORTB = 0;                           // Turn off all display segments                           // Turn off all display segments number = 0;                          //initial value;     digit = number % 10u;            //extract ones digit;     portb_array[0] = mask(digit);    //and store it to PORTB array;     digit = (number / 10u) % 10u;    //extract tens digit;     portb_array[1] = mask(digit);    //and store it to PORTB array;     digit = (number / 100u) % 10u;   //extract hundreds digit;     portb_array[2] = mask(digit);    //and store it to PORTB array;     digit = number / 1000u;          //extract thousands digit;     portb_array[3] = mask(digit);    //and store it to PORTB array; do {     if(!UP == 0){     number++;              Delay_ms(2);              while(UP);              {              PORTB = number;              }     }     digit = number % 10u;            //extract ones digit;     portb_array[0] = mask(digit);    //and store it to PORTB array;     digit = (number / 10u) % 10u;    //extract tens digit;     portb_array[1] = mask(digit);    //and store it to PORTB array;     digit = (number / 100u) % 10u;   //extract hundreds digit;     portb_array[2] = mask(digit);    //and store it to PORTB array;     digit = number / 1000u;          //extract thousands digit;     portb_array[3] = mask(digit);    //and store it to PORTB array;     } while(1);                      //Endless loop;     }

Acuma pentru Lonerider :

PIC16F628A, este?

Cristal de quartz sau filtru de 8MHz, este?

Afisaj cu Anod Comun, este?

4 tranzistori BC547, sunt?

7 x rezistor de 0,33k, sunt?

4 x rezistor de 1k, sunt?

2 x rezistor de 10k, sunt?

Mai ai nevoi de hex si gata.

Editat de Vizitator
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