Witam, jest to mój pierwszy większy projekt który udało mi się w pełni zrealizować a że jest dość praktyczny to postanowiłem się nim pochwalić i w miarę dokładnie opisać jak to zrobić.
Prototyp projektu powstał na platformie arduino UNO. Wyświetlacze są sterowane przez rejestr przesuwny m74hc595b1 i działają na zasadzie multipleksowania. Pierwsze trzy segmenty wyświetlacza pokazują obroty w procentach a ostatnie dwa temperaturę w °C znajdującą się w komputerze. Za pomocą przycisku przełączamy tryby pracy. W sterowaniu ręcznym obroty wentylatorów są regulowane za pomocą potencjometru:
W trybie automatycznym obroty zależą od temperatury panującej wewnątrz komputera:
Do zrealizowania projektu potrzebowałem:
- Komputera z wentylatorami w obudowie.
- Płytka uniwersalna.
- Potencjometr 50 kΩ.
- Przycisk NO (normalnie otwarty).
- 7x rezystor 220 Ω.
- 1x rezystor 10 kΩ.
- 1x kwarc 16 MHz.
- 2x kondensator ceramiczny 22pF.
- Kondensator elektrolityczny 100uF (do swojego projektu nie wiedzieć czemu musiałem dać jeszcze kondensator 220uF , czujnik temperatury mi wariował i dziwnym trafem to pomogło)
- Tranzystor c2500 (lub zamiennik o podobnych parametrach)
- Czujnik temperatury MCP9700A-E/TO
- Rejestr przesuwny m74hc595b1.
- Mikrokontroler ATmega328P.
- 5x Wyświetlacz 7-segmentowy z kropką (ja wykorzystałem wyświetlacz ze starego wskaźnika temperatury dlatego też na końcu jest kostka z podświetlonym °C).
- Wtyk typu molex męski.
Schemat:
Sam układ “od środka” nie prezentuje się najlepiej ale przecież nie o to chodzi żeby to ładnie wyglądało :)
Zasilanie idzie z wtyczki molex, mamy tam 5V (czerwony przewód) jak i 12V (żółty przewód) które zasila wentylatory:
Kod źródłowy postarałem się odpowiednio skomentować tak aby stało się jasne co za co odpowiada i co czyni aby projekt działał jak należy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
const int latchPin = 5; // Pin podpięty do Pin 12 układu 74HC595 (Latch) const int dataPin = 6; // Pin podpięty do Pin 14 układu 74HC595 (Data) const int clockPin = 7; // Pin podpięty do Pin 11 układu 74HC595 (Clock) int reg = 1; // Pin do którego podpięty jest potencjometr float valr ; // wartości odczytywane z potencjometru boolean buttonPin = 13; // Pin do którego podpięty jest przycisk int val = LOW; // Część dotycząca działania przycisku int prev = LOW; #define ST_OFF 0 #define ST_ON 1 int status = ST_OFF; float temp_o; float temp; // zmienne temperatury int temp1; int temp2; // pierwsza i druga cyfra temperatury byte obr; // wartość obrotów w bitach (max 255) int obr_p; // obroty zamienione z bitów na procenty (max 100) int obr_p1; int obr_p2; int obr_p3; //poszczególne cyfry wartości obrotów unsigned long temp_o_time = millis()+300; // czas (0.3s) sprawdzania temperatury od której są regulowane wentylatory unsigned long temp_time = millis()+1000; // czas (1s) odświeżania temperatury na wyświetlaczu unsigned long button_time = millis()+50; // czas (0.05s) co który sprawdzania czy przycisk został wciśnięty) //int i = 0; const byte numbers[12] = {0b11111100, //0 0b01100000, //1 0b11011010, //2 0b11110010, //3 0b01100110, //4 0b10110110, //5 0b10111110, //6 0b11100000, //7 0b11111110, //8 0b11100110, //9 0b10000001, //kropka 0b00000010 //krecha }; void show( byte number) { for(int j = 0; j <= 7; j++) { byte toWrite = number & (0b10000000 >> j); if(!toWrite) { continue; } shiftIt(toWrite); delayMicroseconds(150); } } void shiftIt (byte data) { digitalWrite(latchPin, LOW); for (int k=0; k <= 7; k++) { digitalWrite(clockPin, LOW); if ( data & (1 << k) ) { digitalWrite(dataPin, HIGH); } else { digitalWrite(dataPin, LOW); } digitalWrite(clockPin, HIGH); } digitalWrite(clockPin, LOW); digitalWrite(latchPin, HIGH); } // ta górna część kodu bez komentarza dotyczy wyświetlania cyfr za pomocą rejestru przesuwnego m74hc595b1 void setPwmFrequency(int pin, int divisor) { byte mode; if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 64: mode = 0x03; break; case 256: mode = 0x04; break; case 1024: mode = 0x05; break; default: return; } if(pin == 5 || pin == 6) { TCCR0B = TCCR0B & 0b11111000 | mode; } else { TCCR1B = TCCR1B & 0b11111000 | mode; } } } // Z kolei ta dotyczy zmiany częstotliwości sygnału PWM, musiałem ją zmienić bo na normalnej wentylatory strasznie piszczały. void setup() { pinMode(reg, INPUT); pinMode(buttonPin, INPUT); pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(2, OUTPUT); // pinMode(3, OUTPUT); // pinMode(4, OUTPUT); // pinMode(8, OUTPUT); // pinMode(9, OUTPUT); // te piny idą na wyświetlacze które działają na zasadzie multiplexowania pinMode(10, OUTPUT); // z tego pinu idzie syg na tranzystor który kręci wentylatorami Serial.begin(57600); } void display_status() { switch (status) { case ST_OFF: // w tej części jest opisane co następuje po przyciśnięciu przycisku valr = analogRead(reg); // wartość odczytana z potencjometru obr=map(valr, 0, 1023, 0, 255); // jest to sterowanie ręczne, widać to po tym że dla wartości maksymalnej odczytanej z potencjometru (1023) obroty wentylatora mają mieć obroty 255 czyli też max if(valr >1024 ) // w kodzie jest pełno takich udziwnień jak to ale niestety inaczej nie chciało to działać jak należy { obr = 255; } setPwmFrequency(10, 1); // tutaj jest ustawiana częstotliwość sygnału PWM oraz wybierany jest pin, czyli na pin 10 dajemy 1 jako dzielnik częstotliwości sygnału PWM (patrz funkcja dotycząca tego sygnału) analogWrite(10, obr); if(valr<=0) // jeżeli potencjometr wykaże wartość 0 to na wyświetlaczu mają się pokazywać kreseczki { digitalWrite(4, LOW); show(numbers[11]); digitalWrite(4, HIGH); show(numbers[11]); //pierwszy wyświetlacz digitalWrite(8, LOW); show(numbers[11]); digitalWrite(8, HIGH); show(numbers[11]); //drugi wyświetlacz digitalWrite(9, LOW); show(numbers[11]); digitalWrite(9, HIGH); show(numbers[temp1]); // trzeci wyswietlacz, } break; case ST_ON: // kolejne wciśnięcie przycisku czyli tryb auto obr=map(temp_o, 34, 45, 80, 255); // dla temperatury od 34 do 45 obroty proporcjonalnie od 80 do 255. Od 80 bo od około takiej wartości wentylatory startują if(temp_o <=33 ) { obr = 0; } if(temp_o >45 ) { obr = 255; } // warunki, czyli żeby nie wyskakiwały dziwne kwiatki. setPwmFrequency(10, 1); analogWrite(10, obr); break; } } void next_status() { switch (status) { case ST_OFF: status = ST_ON; break; case ST_ON: status = ST_OFF; break; //znowu przycisk } } void loop() { unsigned long time = millis(); if (time>=button_time) { val = digitalRead(buttonPin); if (val == HIGH && prev == LOW) { next_status(); } prev = val; display_status(); button_time=time+50; // i znów kawałek kodu dotyczącego przycisku, tutaj jest sprawdzane czy jest wciśnięty czy nie i czy ma przełączać następną instrukcję czyli tryb auto i tryb ręczny } analogRead(0); if (time>=temp_o_time) { temp_o = analogRead(0)*5/1024.0; temp_o = temp_o - 0.5; temp_o = temp_o / 0.01; // pobieranie wartości z czujnika i przetwarzanie tego na st. Celsjusza temp_o_time=time+300; // czas co jaki jest to robione } if (time>=temp_time) { temp=temp_o; temp_time=time+1000; // czas co jaki będzie odświeżany wyświetlacz z temperaturą } // no i dalej jest Mexyk czyt. burdel :P ta część kodu odpowiada za wyświetlanie prawidłowo cyfr temp1=temp/10; // temperatura jest dzielona przez 10 by wyłuskać pierwszą cyfrę (cyfra dziesiątek) digitalWrite(2, LOW); show(numbers[temp1]); // wyświetla tę cyferkę digitalWrite(2, HIGH); show(numbers[temp2]); temp2=temp-temp1*10; // cyfra jedności temperatury digitalWrite(3, LOW); show(numbers[temp2]); digitalWrite(3, HIGH); show(numbers[10]); // tutaj jest kropka if (obr>0 && obr<255 ) // teraz czas na obroty, cyfry do wyświetlania są "wyłuskiwane" analogicznie jak przy temperaturze { obr_p=(obr*100)/255; obr_p1=obr_p-obr_p2*10; digitalWrite(4, LOW); show(numbers[obr_p1]); digitalWrite(4, HIGH); show(numbers[obr_p2]); obr_p2=obr_p/10; digitalWrite(8, LOW); show(numbers[obr_p2]); digitalWrite(8, HIGH); show(numbers[obr_p3]); obr_p3=obr_p/100; digitalWrite(9, LOW); show(numbers[obr_p3]); digitalWrite(9, HIGH); show(numbers[temp1]); } if (obr>254 ) // miałem problemy z cyfrą 100 więc wklepałem ją na chama { digitalWrite(4, LOW); show(numbers[0]); digitalWrite(4, HIGH); show(numbers[0]); digitalWrite(8, LOW); show(numbers[0]); digitalWrite(8, HIGH); show(numbers[1]); digitalWrite(9, LOW); show(numbers[1]); digitalWrite(9, HIGH); show(numbers[temp1]); } if(obr<=0) // tutaj kreseczki po raz drugi { digitalWrite(4, LOW); show(numbers[11]); digitalWrite(4, HIGH); show(numbers[11]); digitalWrite(8, LOW); show(numbers[11]); digitalWrite(8, HIGH); show(numbers[11]); digitalWrite(9, LOW); show(numbers[11]); digitalWrite(9, HIGH); show(numbers[temp1]); } } |
Mam nadzieję że podałem wystarczająco dużo informacji na temat “jak to jest zrobione” i jak ktoś jest zainteresowany to powinien zrealizować ten projekt bez większych problemów a jeśli są jakieś wątpliwości pytajcie :)
edit: juz poprawiłem te wiatraczki :P
Szkoda że nie zadbałeś o ładniejsze wykończenie panelu przedniego. Mogłeś poświęcić trochę czasu na zeszlifowanie tych paskudnych zadziorów z blachy.
Aby poprawić widoczność cyfr, przysłoń wszystkie wyświetlacze arkuszem półprzezroczystego ciemno brązowego lub czerwonego tworzywa.
Plus za normalny schemat.
Chciałem całość zakryć jakimś przyciemnianym plexiglas ale odkładałem to i już tak zostało.
Daję 4, bo średnio mi się podoba wykonanie panelu przedniego, mogłeś się postarać lepiej wpasować te wyświetlacze w tę kratownicę :/
a gdzie tranzystory zasilające wyswietlacz 7seg? Bezposrednio z portu procka jest niedopuszczalne.
One są zasilane z rejestru, z procka idą zwykłe sygnały załączające i wyłączające te 5 wyświetlaczy. Działa mi to już ponad pół roku a komputer pracuje średnio 9h dziennie.
Bardzo fajny projekt , trochę skomplikowany fajnie by wyglądało gdybyś przed wyświetlaczem dał kawałek przyciemnianego plastiku żeby nie było tak widać wyświetlacza gdy komp jest wyłączony ode mnie 5/5
Fajny projekt. Ale oczywiście muszę się przyczepić: nie lepiej użyć formy “wentylator” zamiast “wiatraczek”?
Gdzie wpiąłeś ten dodatkowy kondensator? Bo w shemacie go nie widzę
Już poprawione te wiatraczki :), dodatkowy kondensator jest w tym samym miejscu co 100uF, nie mam pojęcia jak to może pomagać. Zastąpienie tych dwóch na jeden o większej pojemności nie dało żadnego efektu.
Prawdopodobnie dwa kondensatory po sobie lepiej filtrują sygnał niż jeden większy. Jeśli chodzi o czujniki to może mieć to duże znaczenie
Wiatraki to masz na Polu:) A twoja obudowa to i tak piekarnik szkoda kasy.
Nie podoba mi się jak włącza się wentylator w trybie automatycznym. Włącza się i od razu wyłącza i tak parę razy. Nie wiem czy jest to szkodliwe dla samego wentylatora czy innych komponentów, ale na pewno nie wygląda dobrze :)
Nie zwróciłem na to uwagi ale masz rację, postaram się to naprawić.
Jak wy narzekacie, normalnie masakra. To be, a to brzydko, a to źle. Projekt zrobiny w kilimacie industarall, bardzo fajny. Założenie filtru czerwonego na wyświetlacz jest dobrym pomysłem i tak powinieneś zrobić. Tak przy okazji jak się wstawia takie piękne listingi ?? Daje -5 za brak filtra na wyświetlaczu oraz za asymetryczne ustawienie cyfr wzgledem okienka.
Jeśli ci chodzi o dodawanie listingu w artykule to tutaj masz odpowiedź http://scr.hu/0tu/nkkby
Nic mi nie powiedział ten screen. Ja nic takiego nie mam. Gdy piszę post nie mam takiego menu.
Mógłbyś jeszcze zrobić wersję z wyświetlaczem LCD ?
Jeśli na wyświetlaczu tego rodzaju http://nettigo.pl/products/362 to pewnie, powinno to być nawet prostsze.
Dobry projekt szukam coś podobnego tylko do silnika 12w 100w
Powinieneś wprowadzić histerezę, żeby po ochłodzeniu wnętrza do zadanej wartości wentylatory popracowały jeszcze przez jakiś czas. Zapobiegnie to takiemu włączaniu i wyłączani wentylatora jak w 50 sekundzie drugiego filmiku.
Czy mógłbyś mi pomóc z ową histerezą ? zrobiłem sobie właśnie ten projekt ale na wyświetlaczu LCD i paroma innymi zmiankami. Męczę się już od jakiegoś czasu i nie mogę wymyśleć jak zastosować histerezę w tym przypadku… a faktycznie strasznie denerwuje to “mruganie” przy granicznych wartościach.