// Rizeni ventilatoru pomoci PWM // (Jednoducha verze s ATtiny13) //=================================== // 22.10.2016 // Velikost prelozeneho kodu: 544 B // // POPIS: //============= // Sirka PWM, doba rozbehu a doba dobehu je nastavitelna pomoci trimru. // Spousteni a vypinani ventilatoru se provadi pomoci jednoho logickeho vstupu. // Po dobu rozbehu je do motoru posilan 100% PWM vykon kvuli prekonani setrvacnosti. // Cas dobehu umoznuje beh ventilatoru jeste nejakou dobu po prepnuti ovladaciho pinu do stavu "STOP". // // http://www.astromik.org/raspi/ventilator // // ZAPOJENI: //============= // ATtiny13 // +-\_/-+ // nezapojeno (RESET) - PB5 1| |8 Vcc 3,3V - Raspberry Pi 3,3V // Nastaveni casu rozbehu (ADC3) - PB3 2| |7 PB2 - (ADC1) - Nastaveni sirky PWM pomoci napeti // Nastaveni casu dobehu (ADC2) - PB4 3| |6 PB1 - (RUN/STOP) - Spusteni("0"), nebo zastaveni("1") PWM generatoru // Raspberry Pi GND - GND 4| |5 PB0 - (OC0A) - PWM signal pro ventilator - spinany pres N-FET // +-----+ // //====================================================================================================================================== byte stav; // Globalni promenna pro aktualni stav ventilatoru: // 0 = ventilator stoji // 1 = ventilator je v rezimu rozbehu - jede po nastavenou dobu (0 az 5,1 sekundy) na 100% vykonu PWM // 2 = ventilator normalne bezi podle nastaveneho PWM vykonu // 3 = ventilator po prepnuti ovladaciho pinu do "STOP" jeste po nastaveny cas (0 az 51 sekund) dobiha normalnim PWM vykonem a pak se vypne. int odpocet = 0; // Pomocne pocitadlo desetin sekundy. byte const STOP = 2; // Jen pro prehlednost kodu (stav ovladaciho pinu PB1) .... PINB = 0bxxxxxx1x byte const RUN = 0; // Jen pro prehlednost kodu (stav ovladaciho pinu PB1) .... PINB = 0bxxxxxx0x // Cteni analogove hodnoty z nastaveneho kanalu A/D prevodniku. byte adc_read (byte kanal) { ADMUX = 0b00100000 | kanal; // Zakladni nastaveni A/D prevodniku - ADLAR na "1" (=nejvyssich 8 bitu je pohromade) a nastaveni prislusneho vstupu. ADCSRA |= 0b01000000; // Start bit se nastavi do "1". while (ADCSRA & 0b01000000); // Cekani na ukonceni prevodu (bit ADSC v registru ADSRA padne do "0"). return ADCH; // V ADCH je 8 nejvyssich bitu z namerene hodnoty (2 nejnizsi bity jsou v ADCL, ale tady nejsou vyuzity) } void setup(void) { DDRB = 0b00000001; // Nastaveni smeru signalu na portu B( PB0=PWM vystup; ostatni vstupy). PORTB = 0b00000010; // Na spousteci pin (PB1) Pull-Up, ostatni vstupy jsou analogove bez Pull-Upu. ADCSRA = 0b10000111; // ADC enable bit na "1" a nastaveni delice frekvence pro ADC na 1:128 (=75kHz). // Zakladni nastaveni PWM na kanalu OC0A. TCCR0A = 0b11000011; // Rezim FAST PWM; vystup se nastavi do '0' pri dosazeni pozadovaneho cisla. TCCR0B = 0b00000001; // FAST PWM, delic zakladni frekvence na 36kHz (pro prescaler='001b'). OCR0A = 255; // Pri startu programu nastavit PWM na sirku 0% (zastavit ventilator). stav = 0; // Znacka, ze ventilator po zapnuti napajeni do ATtiny stoji. } //============================================================================================== // Hlavni smycka je nastavena tak, aby jeden prubeh trval asi desetinu sekundy. void loop(void) { // Blok pro otestovani trimru. byte pwm = adc_read(1) ; // Zjisteni nastastaveni trimru pro sirku signalu PWM. byte rozbeh = adc_read(3) / 50 ; // Zjisteni nastastaveni trimru pro cas rozbehu (0 az 5.1 sekundy). byte dobeh = adc_read(2) / 5 ; // Zjisteni nastastaveni trimru pro cas dobehu (0 az 51 sekund ). /* // Pokud nejsou zapojene trimry, je mozne nastavit parametry napevno. V tom pripade se musi zakomentovat predchozi blok. byte pwm = 64; // cislo 64 znamena PWM 75% byte rozbeh = 50; // cislo 50 znamena rozbeh 1 sekunda byte dobeh = 50; // cislo 50 znamena dobeh 10 sekund */ byte stop_run = PINB & 0b00000010; // Stav spousteciho pinu (2 = STOP; 0 = RUN). // -------------------- if (stav == 0 && stop_run == RUN) // Ventilator je ted zasatveny a ovladaci pin se prave prepnul do stavu "RUN". { odpocet = rozbeh * 10 ; // Nastavit odpocet rozbehu v desetinach sekundy. OCR0A = 0 ; // Pri rozbehu nastavit 100% vykonu. stav = 1 ; // Znacka stavu se nastavi na "rozbeh" } // -------------------- if (stav == 1) // Kdyz se ventilator rozbiha, musi probehnout cela doba trvani rozbehu (nezavisle na ovladacim pinu) { // - aby se nestalo, ze se ventilator nestaci roztocit if (odpocet == 0) // Kdyz tento cas uplyne ... { OCR0A = pwm ; // ... zacne se generovat PWM signal podle pozadovane sirky stav = 2 ; // a znacka stavu se nastavi na "normalni beh". } odpocet -- ; // Odpocet desetiny sekundy od nastaveneho casu. } // -------------------- if (stav == 2 && stop_run == STOP) // Ventilator se ted normalne toci a ovladaci pin byl prave prepnuty do stavu "STOP". { odpocet = dobeh * 10 ; // Nastavit odpocet dobehu v desetinach sekundy. stav = 3 ; // Prepnout znacku stavu na "dobeh". } // -------------------- if (stav == 2 && stop_run == RUN) // Ventilator se ted normalne toci a ovladaci pin je prepnuty do stavu "RUN". { OCR0A = pwm ; // Pri normalnim behu je mozne ovladat vykon PWM pomoci trimru. } // -------------------- if (stav == 3 && stop_run == STOP) // Ventilator je prave ve fazi dobihani a ovladaci pin je ve stavu "STOP". { // Po nastavenou dobu dobehu jede ventilator podle pozadovaneho PWM. OCR0A = pwm ; // Pri dobehu je mozne ridit aktualni vykon PWM pomoci trimru. if (odpocet == 0) // Kdyz tato doba uplyne ... { OCR0A = 255 ; // ... vypne PWM (0% vykonu) stav = 0 ; // a prepne znacku stavu na "ventilator stoji". } odpocet -- ; // Odpocet desetiny sekundy od casu dobehu. } // -------------------- if (stav == 3 && stop_run == RUN) // Pri dotaceni ventilatoru byl ovladaci pin prepnuty do stavu "RUN". { OCR0A = pwm ; // PWM prepne do pozadovaneho vykonu (tentokrat uz neni treba spoustet ventilator na 100%, protoze uz se toci). stav = 2 ; // a znacku stavu nastavi na "normalni beh" } // -------------------- (Jen pro uplnost - posledni mozny stav.) // if (stav == 0 && stop_run == STOP) // Ventilator stoji a ovladaci pin je ve stavu "STOP". // { // // Nic se nedeje - ventilator furt stoji - nezavisle na nastavenem PWM. // } delay(75); // Casovani, aby cela jedna smycka (vcetne mereni napeti a podminek) trvala asi desetinu sekundy. }