luni, 24 octombrie 2011

Fan controller with PWM and PIC12F675

Cum spuneam in postul anterior am re-inceput cu PIC12F675. Este un microcontroler foarte bun pentru inceput, care are un oscilator intern astfel ca nu ai nevoie neaparat de un cuartz extern. Apoi fata de fratele lui mai mic PIC12F629 are si ADC pe patru dintre pini  săi, deci e ideal pentru tot felul de aplicatii care necesita un numar mic de pini.
Va dezamagesc dar nu o sa incep cu un montaj de tip flasher/blinker. O sa incep cu un controler de ventilator. De ce? pentru ca aveam nevoie de unul prin cutiile diferitelor mele montaje. Desigur puteam face unul mai simplu cu operationale, dar daca tot incep sa re-invat am zis sa il fac cu acest microcontroler(caci pe acesta il aveam achizitionat la momentul de start al proiectului).

Aveti schema facuta in Protel 99SE, un soft mai vechi dar care m-a slujit cu credinta ani de zile. Paranteza la paranteza: am incercat Eagle dar curba de invatare a fost prea lunga , asa ca am folosit ce stiam, desi la partea de Placer aceasta versiune nu prea exceleaza - adevarul ca nu stiu celelalte softuri cit de bune sunt, dar la Protel prefer sa nici nu lansez Auto Placer-ul ca e pierdere de timp.
Sa comentez un pic despre schema. Deoarece nu am nici un buton am puc MCLR-ul la Vcc printr-o rezistenta de 10K si ii fac disable in configuratie. De ce? Deoarece am incercat sa il folosesc la un alt proiect ca un simplu buton , si isi tragea microcontrolerul niste reseturi de mai mare dragul. Asa ca am devenit paranoia- daca se poate mai mult decit sunt - si prefer sa il tin la Vcc chiar si la microcontrolerele care au un pull-up intern. Paranoia, deh ......
Alta componenta importanta este condensatorul de 100nF C_IC. Acesta il pun NEAPARAT intre pini de Vcc si Vss. Initial nu il puneam si cind iti era lumea mai draga se reseta microcontrolerul. Pina m-am prins am crezut ca nu facusem softul bine , ca nu am facut cablajul bine, si alte motive. Dupa un pic de reserch pe Google, am atasat primul condensator si dintr-o data totul a inceput de functioneze.
REPET, nu uitati sa puneti un condensator , cit mai aproape de pini de alimentare ai microcontrolerului. Pe net unii recomanda si un condensator electrolitic dar pina acum cu un simplu ceramic totul pare sa functioneze bine. El am cumparat niste condensatoare SMD si cind fac cablajul incerc sa fac pozitionarea lui chiar dedesubtul microcontrolerului. Daca nu pot atunci il pun pe soclul de la microcontroler- prefer sa folosesc socluri gold ca sunt mai inalte si pot lipi un condensator normal intre pini de tensiune fara sa afecteze.
Revenim la schema. Ca senzor de temperatura am folosit un DS18B20 pe principiul "asta am". Nu o sa ii fac o prezentare aici caci nu are rost. Daca doriti informatii mai multe despre el gasiti la producator acasa MAXIM . Daca preferati ceva in romaneste va recomand un site foarte bun, de unde sa intelegeti modul lui de functionare, realizat de Catalin-Mihael Bojescu. Nu am cerut voie autorului sa il citez, sper sa nu se supere.
Pentru controlul bunei functionari folosesc un led conectat la GP1 si pe GP2 il folosesc pentru seriala. De asta apare si in schema si conectorul RS232_POWER de unde i-ai tensiunea pentru un modul extern- un montaj cu un MAX232 pentru a avea nivelele de tensiune/semnal pentru co conexiune seriala.
Comanda ventilatorului o fac cu un IFR540. Am ales acest tranzistor datorita caderi mici de tensiune de pe el. Puteam folosi un 2Nxxxx sau un BDxxx dar caderea de tensiune era prea mare, asftel incit daca alimentam de la 12V nu aveam sa obtin turatia maxima a ventilatorului.
Alimentarea microcontrolerului o fac cu un 7805 in capsula TO92. La cit consuma este ultra suficient.
C-am atit despre schema.
Acum sa vorbesc despre "chinurile facerii" la nivel de software.
Sa incepem cu un ...

STATEMENT: URĂSC LIMBAJUL DE ASMBLARE

Acuma ca am lamurit asta, va spun ca am facut softul in HI TECH C, versiunea optimizata - am activat perioada de 45 de zile de trial ca sa imi iasa codul mai mic, caci cu partea de seriala incepea sa nu incapă in memoria microcontrolerului.
Initial codul de baza arata asa



  1. while(1){ //looping

  2. get_temp();
  3. digit=temp_lsb>>4;
  4. digit|=(temp_msb&0x7)<<4;

  5. //FAN_ON = 0;
  6. if(digit>=25 && digit<30){ duty=50; FAN_ON=1;};
  7. if(digit>=30 && digit<35){ duty=100; FAN_ON=1;};
  8. if(digit>=35 && digit<40){ duty=150; FAN_ON=1;};
  9. if(digit>=40){ duty=254;  FAN_ON=1;};

  10. for(i=0; i<300;i=i++)soft_pwm_led_fan(1,5,duty);


  11. } //loping


Functia get_temp() citeste temperatura in doi octetii temp_lsb si temp_msb. Codul din liniile 4 si 5 extrage intregul pe care apoi il verific si stabilesc valoarea pentru PWM. Totul era ok doar ca nu am tinut cont de un simplu lucru: timpul necesar circuitului pentru realizarea conversiei(vezi tabelul de mai jos).


R1R0ResolutionMax Conversion Time
009-bit93,75 mstCONV/8
0110-bit187,5 mstCONV/4
1011-bit375 mstCONV/2
1112-bit750 ms
tCONV




La initializare DS18B20 este in modul 12 bit rezolutie DAR ii ia minim 750ms ca sa poata face conversia. In perioada de conversie ventilatorul nu primeste alimentare, ledul martor se stinge si asa mai departe. 
Deci ori se mareste foarte mult perioada intre citiri succesive ale temperaturi ori .....
Am redus rezolutia la 9 bit, timpul de conversie devenind 93.75ms dar tot este sesizabila oprirea, mai ales daca ventilatorul e la turatie ridicata - un duty mare.
O solutie ar fi fost sa incerc sa fac un executiv de timp reala (care sincer nu stiu daca ar rezolva, cel putin in teorie ar trebui dar la cit de putina memorie are acest microcontroler si tind cont de faptul ca cel mai mic executiv care l-am vazut ocupa 1k de memorie .....), ceea ce e mult prea mult, sau sa gasesc o metoda alternativa-de exemplu sa caut alt circuit dar asta ar insemna alti bani cheltuitii, deci neacceptabil.
Asa ca solutia a fost inglobarea functiei de citire a temperaturi in corpul principal al lui main().
Astfel bucla principala a devenit:

  1. while(1){ //looping

  2. //din motive de timp-timpul de steptare pina se face converisa ca sa aflam temperatura
  3. //modific functia si in loc sa stau fac pwm
  4. //sper sa dispara caderea de viteaza a ventilatorului

  5. DQ_HIGH();
  6. reset();                                 //reset,wait for  18b20 responsion
  7. write_byte(0XCC);                        //ignore ROM matching
  8. write_byte(0X44);                        //send  temperature convert command

  9. if(FAN_ON == 1)for(i=0; i<100;i=i++)soft_pwm_led_fan(1,5,duty);

  10. reset();                                 //reset again,wait for 18b20 responsion
  11. write_byte(0XCC);                        //ignore ROM matching 
  12. write_byte(0XBE);                        //send read temperature command
  13. temp_lsb=read_byte();                         //read temperature low byte
  14. temp_msb=read_byte();                         //read temperature high byte
  15. DQ_HIGH();                               //release general line 

  16. //Store temperature integer digits and decimal digits in 12 bits
  17. digit=temp_lsb>>4;
  18. digit|=(temp_msb&0x7)<<4;

  19. FAN_ON = 0;
  20. if(digit>=20 && digit<25){ duty=50; FAN_ON=1;};
  21. if(digit>=25 && digit<30){ duty=100; FAN_ON=1;};
  22. if(digit>=30 && digit<35){ duty=150; FAN_ON=1;};
  23. if(digit>=35 && digit<40){ duty=200; FAN_ON=1;};
  24. if(digit>=40){ duty=254;  FAN_ON=1;};

  25. for(i=0; i<500;i=i++)soft_pwm_led_fan(1,5,duty);

  26. } //loping



Astfel in loc sa astept fara sa fac nimic, mai trec prin functia de PWM. Pe ventilator nu se sesizeaza perioadele moarte ramase (de la resetul lui DS18B20 si de la celelalte operatiuni necesare pentru functionarea lui) doar ledul clipeste usor. Nu pot aprecia corect cit tine un ciclu PWM-si nici nu am timp de fineturi de acest tip- dar s-ar putea elimina si aceasta clipire, inserind cicluri PWM peste tot unde avem functii de tip delay.
O alta metoda ar renuntarea la PWM pe led,  eventual atasarea unui condensator electrolitic care sa se descarce pe led, dar asta ramiine pe alta data.
Atasat codul functional(cu clipit cu tot).


Update: am vazut astazi o schema in care cineva punea inclusiv o inductanta   intre tensiunea de alimentare si pinul de Vcc, iar condensatorul era inlocuit cu doua condensatoare (pe Vcc si pe Vss cite unul). Banuiesc ca autorul schemei folosea montajele in zone foarte "zgomotoase". Ce e important e faptul ca el spunea ca merge foarte bine. Ca idee de testat pe viitor daca mediul de lucru ar fi cu probleme.














Niciun comentariu:

Trimiteți un comentariu