Popularny post kaminski-tomek Napisano Kwiecień 26, 2022 Popularny post Udostępnij Napisano Kwiecień 26, 2022 W tym wątku chciałbym przedstawić Wam schemat licznika cyfrowego, którego zadaniem jest zliczanie impulsów kontaktronu i wyświetlanie wyniku do maksymalnie czterech cyfr. Funkcjonalnie powinien umożliwiać również resetowanie wyniku, pauzę w zliczaniu (sygnalizowaną przez miganie liczby) oraz korekcję liczby (odejmowanie jedynki). Jako wyświetlacza użyłem najprostszego wyświetlacza 4-cyfrowego 7-segmentowego sterowanego multipleksowo (https://botland.com.pl/wyswietlacze-segmentowe-i-matryce-led/6449-wyswietlacz-8-segmentowy-x4-14mm-czerwony-wspanoda-5904422357672.html). Nie znalazłem nigdzie odpowiedniego elementu w bibliotece Eagle, więc narysowałem go sam (wzorując się na istniejących bibliotekach i dokumentacji elementu). Wątek odnośnie wyświetlacza tutaj. Do sterowania zdecydowałem się na ATmega88PA-PU ze względu na cenę i dostępność. Schemat wygląda następująco: Udało mi się również zbudować prototyp na płytce stykowej, który w miarę działa. Efekt poniżej: Program, jaki napisałem nie świeci na razie czytelnością, ale pewnie jeszcze go poprawię: #define SEG_C 4 #define SEG_E 21 #define SEG_D 20 #define SEG_B 0 #define SEG_G 3 #define SEG_A 2 #define SEG_F 1 #define DISP_4 19 #define DISP_3 18 #define DISP_2 17 #define DISP_1 16 #define NONE 10 #define RESET 9 #define PAUSE 10 #define INCREASE 8 #define DECREASE 14 byte digitSegments[11] = { //1gfedcba 0b01000000, //0 0b01111001, //1 0b00100100, //2 0b00110000, //3 0b00011001, //4 0b00010010, //5 0b00000010, //6 0b01111000, //7 0b00000000, //8 0b00010000, //9 0b01111111 //NONE }; byte segmentPin[7] = { SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G }; byte displayPin[4] = { DISP_4, DISP_3, DISP_2, DISP_1 }; volatile int counter = 0; volatile bool counterVisible = true; volatile bool pause = false; int resetLastState = HIGH; int pauseLastState = HIGH; int increaseLastState = HIGH; int decreaseLastState = HIGH; void setup() { for (int i = 0; i < 7; i++) { pinMode(segmentPin[i], OUTPUT); } for (int i = 0; i < 4; i++) { pinMode(displayPin[i], OUTPUT); } pinMode(RESET, INPUT_PULLUP); pinMode(PAUSE, INPUT_PULLUP); pinMode(INCREASE, INPUT_PULLUP); pinMode(DECREASE, INPUT_PULLUP); delay(500); } #define DIGIT_INTERVAL 2000 #define PAUSE_INTERVAL 200000 void loop() { showCounter(); int resetState = digitalRead(RESET); if (resetState == HIGH && resetLastState == LOW) { reset(); } resetLastState = resetState; int pauseState = digitalRead(PAUSE); if (pauseState == HIGH && pauseLastState == LOW) { togglePause(); } pauseLastState = pauseState; int increaseState = digitalRead(INCREASE); if (increaseState == HIGH && increaseLastState == LOW) { increase(); } increaseLastState = increaseState; int decreaseState = digitalRead(DECREASE); if (decreaseState == HIGH && decreaseLastState == LOW) { decrease(); } decreaseLastState = decreaseState; } void reset() { counter=0; pause=false; counterVisible=true; } void togglePause() { pause = !pause; if (!pause) counterVisible = true; } void increase() { if (pause) { return; } counter++; if (counter > 9999) { counter=0; } } void decrease() { if (pause) { return; } if (counter != 0) { counter--; } } void showCounter() { static int digitPosition = 1; static int tens = 1; static unsigned long previousTime; static unsigned long previousPauseTime; unsigned long currentTime = micros(); if (pause && (currentTime - previousPauseTime >= PAUSE_INTERVAL)) { previousPauseTime = currentTime; counterVisible = !counterVisible; if (!counterVisible) { showDigit(NONE); } } if (counterVisible && (currentTime - previousTime >= DIGIT_INTERVAL)) { previousTime = currentTime; showDigit(NONE); digitPosition ++; tens = tens * 10; if (digitPosition > 4) { digitPosition = 1; tens = 1; } setDigitPosition(digitPosition); if (counter >= tens || (tens == 1 && counter == 0)) { showDigit((counter / tens) % 10); } } } void setDigitPosition(int digitPosition) { digitalWrite(DISP_1, digitPosition != 1); digitalWrite(DISP_2, digitPosition != 2); digitalWrite(DISP_3, digitPosition != 3); digitalWrite(DISP_4, digitPosition != 4); } void showDigit( int digit) { byte segments = digitSegments[digit < 10? digit: NONE]; for (int i = 0; i < 7; i++) { digitalWrite(segmentPin[i], (segments >> i) & 1); } } Całość wgrałem przez platformę Arduino. Ustawiłem następujące parametry: Board: MiniCore/ATmega88 Clock: Internal 1MHz BOD: 2.7 V EEPROM: retained LTO enabled Variant: 88P / 88PA no bootloader Zanim zacznę projektować PCB chciałbym zwalidować z Wami ten układ i mam kilka pytań: Czy takie wykorzystanie pinów ATmegi jest Waszym zdaniem OK? Czy niczego tu nie brakuje (zgodnie ze sztuką)? Numery pinów użytych do sterowania wyświetlaczem i do wejścia (przyciski/kontraktron) są trochę losowe, bo kierowałem się głównie miejscem na płytce prototypowej i tym, żeby mieć wolne piny MISO/MOSI/SCK. Próbowałem oprogramować przerwania, które zmieniałyby wartość licznika, ale w ogóle nie chciały działać - czy to może być kwestia użytego mikrokontrolera? Dodam, że próbowałem z użyciem attachInterrupt(digitalPinToInterrupt(PIN), handler, RISING); Z tego względu wykrywam zbocze opadające w funkcji loop() i szczerze mówiąc, nie podoba mi się to Czy mogę używać pinów MISO/MOSI/SCK do swoich celów w czasie, gdy programator USBasp jest do nich podpięty? Czy będzie to miało wpływ na działanie mikrokontrolera? Zasilanie wybrałem najprostsze - kupiłem najtańszy zasilacz na 5V DC 5.5mm (https://botland.com.pl/zasilacze-dogniazdkowe/1364-zasilacz-impulsowy-5v-25a-wtyk-dc-55-21mm-5907621806552.html) i tym zasilam układ. Czy warto zamiast tego dodać do układu stabilizator i wyższe napięcie? Widziałem też na niektórych układach dławik przed zasilaniem - rozumiem, że wtedy niwelowałby skoki natężenia, ale czy przyda się on przy takim zasilaczu? Do zrobienia zostało mi tylko użycie wewnętrznej pamięci EEPROM, ale to już zostawię sobie na później. 3 Link do komentarza Share on other sites More sharing options...
_LM_ Kwiecień 27, 2022 Udostępnij Kwiecień 27, 2022 Możesz wykorzystać sprzętowy licznik. Vref, podłącz przez kondensator do masy, piny programatora można podłączyć jak chcesz byle nie robiło to zwarć, możesz dodać rezystory o małej wartości na tych liniach. Link do komentarza Share on other sites More sharing options...
kaminski-tomek Kwiecień 27, 2022 Autor tematu Udostępnij Kwiecień 27, 2022 6 godzin temu, _LM_ napisał: Możesz wykorzystać sprzętowy licznik. Vref, podłącz przez kondensator do masy, piny programatora można podłączyć jak chcesz byle nie robiło to zwarć, możesz dodać rezystory o małej wartości na tych liniach. Czy sprzętowy licznik można dowolnie ustawiać? (resetować, zmniejszać o jeden, itd.) Link do komentarza Share on other sites More sharing options...
_LM_ Kwiecień 27, 2022 Udostępnij Kwiecień 27, 2022 O faktycznie rozpędziłem się w AVR nie da się dekrementować wartości, resetować tak ale licznik liczy tylko w jednym kierunku Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
etet100 Kwiecień 27, 2022 Udostępnij Kwiecień 27, 2022 Z kodu MiniCore wynika, że przerwania zewnętrzne dostępne są dla pinów 2 i 3 #define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT)) Wszystkie inne zwracają NOT_AN_INTERRUPT Piny współdzielone z programatorem potrafią być problematyczne. Zależnie od sposobu użycia, czasami nie działa programowania lub ta druga funkcja, do której pinów użyjesz. 1 Link do komentarza Share on other sites More sharing options...
kaminski-tomek Maj 2, 2022 Autor tematu Udostępnij Maj 2, 2022 Wracam na wątek z poprawkami do schematu. Po uwzględnieniu sugestii zmieniłem kilka rzeczy: Dodałem kondensator do pinu AREF Zmieniłem rezystory segmentów na 1K (trochę jaśniej świecą) Dodałem stabilizator LM7805 Poprawiłem symbol linii zasilania (jakoś Vcc ze strzałką bardziej mi się podoba) Przeorganizowałem piny mikrokontrolera tak, aby wygodniej mi się projektowało w Eaglu Schemat wygląda teraz następująco: Na podstawie tego schematu zaprojektowałem też po raz pierwszy płytkę PCB. Oto ona: Mam kilka pytań: czy prowadzenie połączeń szyny zasilania pod rezystorami jest OK? jak blisko mikrokontrolera muszą być kondensatory? i czy nie przesadziłem z wylewaniem masy? Ogólnie to wszelkie uwagi mile widziane, to moje zupełne początki z projektowaniem PCB. Link do komentarza Share on other sites More sharing options...
Krawi92 Maj 2, 2022 Udostępnij Maj 2, 2022 (edytowany) Robiłem niedawno bardzo podobna płytkę z 2 ds18b20 i takim wyświetlaczem. Kondensatory umieściłbym jak najbliżej nóżek uC i stabilizatora. Myślę że poprowadzenie zasilania pod rezystorami, nie ma żadnego wpływu. Jaki isolate użyłeś do wyłania poligonu, 24? Ja czasem używam nawet 32. I polecam zacząć zabawę z smd, napewno zmniejszy to rozmiary plytek, a elementy 1206 czy 0805 spokojnie polutowac mozna zwykła stacja lutownicza. Rezystory 1k przy segmentach? Ja mam 470ohm i jak świeci słońce to czasem nie widzę co tam świeci na wyświetlaczu 😆 Edytowano Maj 2, 2022 przez Krawi92 1 1 Link do komentarza Share on other sites More sharing options...
H1M4W4R1 Maj 2, 2022 Udostępnij Maj 2, 2022 (edytowany) 19 minut temu, Krawi92 napisał: Myślę że poprowadzenie zasilania pod rezystorami, nie ma żadnego wpływu. W tym przypadku nie, ale czasami może mieć drastyczny wpływ, więc polecam już ćwiczyć, że po drugiej stronie ścieżki sygnałowej powinna być lita masa. W przypadku USB czy PCIE zrobienie inaczej zwykle kończy się przyciskiem do papieru. (Dla sygnałów niskich częstotliwości można zrobić wyjątek i przeciąć ścieżki pod kątem 90 stopni). 19 minut temu, Krawi92 napisał: I polecam zacząć zabawę z smd, napewno zmniejszy to rozmiary plytek, a elementy 1206 czy 0805 spokojnie polutowac mozna zwykła stacja lutownicza. 0402 i 0201 też 😉 Ale osobiście wolę THT, bo nie muszę się wtedy męczyć z dokładnością przyklejania folii światłoczułej do PCB. 1 godzinę temu, kaminski-tomek napisał: i czy nie przesadziłem z wylewaniem masy? Nie, nawet bym powiedział, że za mało... 😉 Tam gdzie nie ma ścieżek tam powinna być masa. 1 godzinę temu, kaminski-tomek napisał: jak blisko mikrokontrolera muszą być kondensatory? Najlepiej "w mikrokontrolerze" czyli im bliżej tym lepiej. W moich projektach zwykle są w odległości mniejszej niż 1mm. Edytowano Maj 2, 2022 przez H1M4W4R1 2 Link do komentarza Share on other sites More sharing options...
Krawi92 Maj 2, 2022 Udostępnij Maj 2, 2022 Ja na razie zszedłem do 0805, jeszcze ciężko mi idzie lutowanie pod mikroskopem, muszę się patrzeć na element 😆 1 Link do komentarza Share on other sites More sharing options...
kaminski-tomek Maj 2, 2022 Autor tematu Udostępnij Maj 2, 2022 Dzięki za odpowiedzi! Poprawiłem nieco projekt: przesunąłem kondensatory i zmniejszyłem isolate do 0.32mm: Jak poprawiacie rozlewanie masy? Ja znalazłem takie polecenie: ripup <nazwa_poligonu>, potem robię jeszcze raz nowy poligon i rozlewam masę z nowym isolate - może jest inny, szybszy sposób? Link do komentarza Share on other sites More sharing options...
kaminski-tomek Maj 2, 2022 Autor tematu Udostępnij Maj 2, 2022 O, teraz zmniejszyłem width do 0.508 i przy tym samym isolate (0.32) wyszło mi z kolei tak: Link do komentarza Share on other sites More sharing options...
Krawi92 Maj 2, 2022 Udostępnij Maj 2, 2022 (edytowany) No teraz to trochę chyba przegiąłeś z tym poligonem, aż się zwarcia do masy porobiły xd ja isolate ustawiam w milsach, 24, góra 32. Wiesz wszystko zależy jaka metoda robisz płytkę, nie wszystko zrobisz żelazkiem. Jeśli chodzi o poprawianie isolate to też tak robię, po prostu kasuje polygon i rysuje nowy. Chociaż jakby się zastanowić to powinno być info poligonu i tam jego parametry też pewnie mozna z ręki zmienić. Edytowano Maj 2, 2022 przez Krawi92 Link do komentarza Share on other sites More sharing options...
kaminski-tomek Maj 2, 2022 Autor tematu Udostępnij Maj 2, 2022 @Krawi92 teraz ustawiłem w milsach: isolate na 32, width na 1 i spacing na 12. (Nie rozumiem do końca parametru spacing jeszcze). Efekt: Width - rozumiem jako szerokość linii poligonu (nie wiem jeszcze, jaki ma to wpływ na rozlewanie go). Isolate - jaki odstęp od innych ścieżek. Link do komentarza Share on other sites More sharing options...
Krawi92 Maj 2, 2022 Udostępnij Maj 2, 2022 Jaka metoda będziesz wykonywał płytkę? Link do komentarza Share on other sites More sharing options...
kaminski-tomek Maj 2, 2022 Autor tematu Udostępnij Maj 2, 2022 Chciałem spróbować termotransferem - czyli tradycyjnie żelazkiem Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »