Ca o prima postare am ales un proiect mai “aratos”: un ceas cu afisaj VFD
Pentru afisaj am folosit un tub IV-18:
Caracteristicile tubului sunt:
- 9 digiti, 8 cu 7 segmente si virgula, 1 cu simboluri speciale.
- tensiune de filament : 5V la 85mA
- tensiune anodica: 20-30V
- curent de grila: 11mA per digit
- curent anodic: 8mA per digit, cu toti anozii aprinsi
Mai multe informatii puteti gasi aici
Design
- Microcontroller: un CORTEX-M3
- Real time clock: de preferat integrat in microcontroller
- Sursa de tensiune anodica: cat mai simpla folosind un integrat dedicat
- Dimensiunea pcb-ului: pe latura lunga sa nu depaseasca lungimea tubului
Microcontroller
Cerintele de baza ale microcontroller-ului au fost costul, RTC-ul si battery backed-up RAM integrate, prezenta interfetei JTAG si utilizarea unui integrat dintr-o serie neutilizata in alte proiecte.
Am ales STM32F100R6T6, un chip fabricat de ST, capsula TQFP64, 8K ram si 32K flash.
Frecventa maxima este de 24Mhz.
In jurul procesorului am folosit componentele minime pentru a-l utiliza, conform manualului: quartz-uri pentru system clock si RTC clock, condensatori de decuplare pe liniile de alimentare si de reset si rezistente de pull-down pe pinii de boot mode select.
Conectorul de JTAG este unul clasic, header 2×10 pini, 2.54mm.
Microcontroller-ul are incluse rezistentele de pull-up / pull- down pe toate liniile si nu a mai fost nevoie de rezistente suplimentare. Am pastrat doar cele 3 rezistente de pull-down pe liniile neutilizare ( R20, R21 si R22 10K) si R34 pentru limitare de curent.
Sunt utilizati aproape toti pinii de I/O disponibili. Am lasat un port serial cu un header de 2.54mm ( UART2 ) si doua semnale analogice ( AMB_IN si TEMP_IN ) pentru o extensie ulterioara.
Bateria de back-up este de tip CR2032, cu un conector SMD lipit pe PCB.
Tensiunea pentru anozii tubului este generata cu un BOOST clasic, comandat de procesor. Am ales un tranzistor MOSFET cu Vth mic ce poate fi direct comandat de un canal de PWM. Rezistenta R3 de 10 ohmi are doua roluri: formeaza un filtru RC cu C5, C6 si condensatorii de filtrare de pe linia de alimentare ( VCC_RAW ) si are rolul de limitare a curentului / siguranta fuzibila in cazul in care tranzistorul Q1 ramane deschis. Tensiunea de feed-back este preluata printr-un divizor rezistiv format din R6,R4 si filtrata apoi cu R5 si C7
Cateva forme de unda:
Frecventa de comanda este de aproximativ 93.75KHz – PWM clock este 24Mhz, 8 biti rezolutie. Factorul de umplere este de ~ 40% pentru luminozitate 5/10, ce se traduce in aproape 30V la iesire. |
|
Aici se vede forma de unda in nodul de comutatie: tensiunea de fly-back si oscilatia libera in perioada in care tranzistorul este deschis | |
Datorita curentului mic de comanda se pot vedea efectele capacitatiilor parazite: panta fronturilor crescatoare / descrescatoare si oscilatiile parazite transmise prin capacitatea drena – poarta | |
Tensiunea de iesire are un riplu destul de mare datorita numarului redus de pasi de PWM ( 256 ) si a vitezei mici a buclei de reactie |
Driverele
Dupa mai multe variante am ales driverele integrate ULN2803 – 8 canale open collector. Dezavantajul principal este dat de consumul inutil de energie: in cazul in care tubul este complet stins irosesc ~ 19x(50/100K) : 10mA sau ~ 0.5W. In functionarea normala se intalnesc rar astfel de cazuri.
Driverele open-emitter ar fi fost ideale, dar nu am gasit nimic pentru tensiunea respectiva, si suprafata necesara realizarii cu componente discrete ar fi fost mult mai mare. Alaturi de cele 2 drivere integrate ce imi asigura 16 canale mai exista un driver discret pentru canalul 17 – grila simbolurilor speciale.
Alimentare
Alimentarea consta in 2 regulatoare lineare inseriate.
Primul coboara tensiunea de intrare la 5V ce ajunge la filament printr-o rezistenta de limitare si la stabilizatorul de 3.3V pentru microcontroller.
Din linia de 3.3V este alimentat si blocul analogic printr-un filtru RC.
PCB
PCB-ul este realizat la un producator dedicat si are 100x50mm. Materialul este FR4 de 1.6mm grosime, cupru de 35 microni. Via-urile sunt metalizate. Toata placa a primit un tratament HAL ( probabil stanare ).
Pentru a reduce costurile am renuntat la silkscreen si soldermask.
Se poate observa planul de masa continuu ce are si rolul de radiator pentru stabilizatorul de 5V.
PCB-ul a fost impartit in 4 “sectiuni”:
- Alimentare de joasa tensiune: conectorul de alimentare, condensatorii de decuplare, stabilizatorul de 5 si 3.3V
- Microcontroller-ul si ridicatorul de tensiune
- Driverele pentru tub si conectorul acestuia
- Butoanele interfetei cu utilizatorul
Impartirea a fost facuta tinand cont de componentele ce disipa multa caldura – stabilizatoarele liniare izolate in partea de sus a imaginii, de regulile de lay-out pentru sursele in comutatie – traseele ce poata curenti mari au dimensiuni foarte mici, cu exceptia planului de racire conectat la radiatorul lui Q1.
Asamblarea a fost facuta de mana, cu ajutorul unui microscop.
Lipsa solder mask-ului a pus probleme – cositorul avand tendinta sa se intinda pe planul de masa.
Firmware
Firmware-ul este scris exclusiv in C, folosind compilatorul gcc si un toolchain bazat pe Eclipse si OpenOCD.
Codul este alcatuit din patru bucle:
- ADC ISR ce face medierea tensiunii de feedback si controleaza duty cycle-ul regulatorului boost
- TIM6 ISR : multiplexarea segmentele de afisaz
- TIM7 ISR : citirea tastelor si debounce
- bucla infinita in main, ce controleaza interfata cu utilizatorul
ADC
Controller-ul ADC este configurat sa citeasca succesiv 3 canale – tensiunea de feedback si cele 2 intrari libere.
La fiecare conversie valorile citite sunt mediate cu valorile precedente apoi se stabileste noul duty cycle printr-un comparator simplu.
Duty cycle-ul este updatat la cateva mii de valori citite, pentru a reduce viteza buclei de reactie
if ( 1000 == adcISRState) { adcISRState = 0; /* update the duty cycle */ if ( adcDCDCMed > adcDCDCSetPoint ) { adcDCDCPwmDuty --; } else { adcDCDCPwmDuty ++; } pwmSetDutyDCDC(adcDCDCPwmDuty); } else { adcDCDCMed = (adcDCDCMed + adcDCDC) >> 1 ; }
Zgomotul din poza “Vnoise” se datoreaza in mare parte acestui algoritm simplificat.
TIM6
Timer-ul TIM6 este configurat sa genereze o intrerupere cu o perioada de ~ 1mS.
La fiecare “tick” este aprinsa urmatoarea grila din afisaj. Comutarea este de genul “break before make” penrtru a reduce efectul de “ghosting”: sinbolul curent este stins inainte de a se trece la urmatorul.
void __attribute__((__interrupt__)) timer6ISR(void) { unsigned int status = TIM6->SR; TIM6->SR = ~ status; /* clear bits set to 1 */ if ( (TIM_SR_UIF&status) != 0 ) { /* my isr */ /* time to display character * */ /* grids start from PA4 - PA12 */ /* segments from PC4 to PC11 */ /* set all grids and lines to 1 - display off */ GPIOA->BSRR = GPIO_BSRR_BS4 | GPIO_BSRR_BS5 | GPIO_BSRR_BS6 | GPIO_BSRR_BS7 | GPIO_BSRR_BS8 | GPIO_BSRR_BS9 | GPIO_BSRR_BS10 | GPIO_BSRR_BS11 | GPIO_BSRR_BS12; GPIOC->BSRR = GPIO_BSRR_BS4 | GPIO_BSRR_BS5 | GPIO_BSRR_BS6 | GPIO_BSRR_BS7 | GPIO_BSRR_BS8 | GPIO_BSRR_BS9 | GPIO_BSRR_BS10 | GPIO_BSRR_BS11 ; /* enable the segment */ GPIOC->BSRR = displayBuffer[currentChar] << 20; /* enable the grid */ GPIOA->BSRR = GPIO_BSRR_BR4 << currentChar; /* next char */ currentChar ++; if ( currentChar > 8 ) currentChar = 0; } }
Codul de control al afisajului mai contine si functii ajutatoare ce mapeaza caracterele ascii pe font-ul intern, aprinde virgula fiecarui segment si controleaza simbolurile speciale.
TIM7
Timer-ul TIM7 se ocupa cu scanarea tastaturii, filtrarea apasarilor prea scurte si notificarea apasarii unui buton.
Filtrarea este simpla si eficienta: la fiecare tick se verifica daca tasta este apasata. Daca da, contorul de debounce se incrementeaza cu 1 pana cand atinge valoare de prag ce genereaza o notificare. Daca tasta nu este apasata contorul de debounce se duce in 0.
if ( (keys & (1<<12 )) == 0 ) { if ( UI_DEBOUNCE_CONSTANT != keyDebounce[0]) keyDebounce[0] += 1; } else { keyDebounce[0] = 0; } .... if ( UI_DEBOUNCE_CONSTANT == keyDebounce[0]) { keyCodes |= UI_KEY_UP; keyDebounce[0]=0; }
Bucla din main
Bucla principala de program controleaza interfata cu utilizator: ce informatii se afiseaza pe display si navigarea prin meniurile de configurare / functii auxiliare.
TO DO
Urmatoarele functii sunt in continuare in lucru:
- Salvarea datelor de configurare in back-up RAM
- Alarma – configurare si afisare alarme
- Count down timer
- Infrastructura de control a unor viitoare periferice atasate pe UART2
- Imbunatatire algoritm de control pentru sursa in comutatie
- Corectie PCB – 2-3 footprint-uri gresite
Galerie foto:
[imagebrowser id=1]