Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'poradnik'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona

Znaleziono 4 wyniki

  1. Wstęp Ten artykuł jest skierowany do użytkowników, którzy chcieliby połączyć kilka zasilaczy razem, aczkolwiek zastanawiają się jak to zrobić bezpiecznie. Autor nie ponosi odpowiedzialności za wszelkie usterki i szkody wynikające ze stosowania zamieszczonych tu treści. Fotografia 1: Zdjęcie poglądowe zasilacza typu SMPS (Flickr, Marco Verch, CC BY 2.0) Rodzaje połączeń Zasilacze możemy łączyć szeregowo i równolegle – i zanim ktokolwiek powie, że to niebezpieczne: jest to bezpieczne o ile zachowa się pewne środki ostrożności. Wyróżniamy trzy główne rodzaje połączeń: PP (Parallel Power) – równoległe połączenie w celu zwiększenia mocy wyjściowej PR (Parallel Redundancy) – równoległe połączenie w celu zabezpieczenia układu w przypadku uszkodzenia jednego (lub większej ilości) zasilaczy SC (Series Connection) – połączenie szeregowe w celu zwiększenia napięcia wyjściowego. Parallel Power Rysunek 2: połączenie równoległe zasilaczy W teorii możemy wykorzystać ten rodzaj połączenia z każdym zasilaczem, aczkolwiek rezultaty mogą nie być satysfakcjonujące. Niektórzy dostawcy oznaczają zasilacze jako kompatybilne z PP, aczkolwiek tak zdecydowanie nie jest (pozdrawiamy przyjaciół z Chin). Problemem w tym trybie jest to, by prąd między zasilaczami był dzielony jak najrówniej – co innymi słowy przekłada się na identyczną impedancję i napięcie wyjściowe obu zasilaczy w danej chwili. Znając nasz świat możesz łatwo się domyślić, że nie jest to proste zadanie – wpływ na te czynniki ma np. tempratura czy wiek zasilacza. Dodatkowo w czasie rozruchu i przeciążenia zasilacze mogą zachowywać się nieprzewidywalnie. Niezbalansowany pobór prądu może spowodować przedwczesne starzenie się niektórych zasilaczy w układzie, a co za tym idzie zmniejszyć niezawodność systemu. Producenci wprowadzili wiele różnych technik, by zapobiec takim efektom np. LSB (Load Share Bus) – zasilacze komunikują się między sobą (dostępne najczęściej w najbardziej zaawansowanych modelach) – np. NPS2400 SRA (Specific Regulation Algorithms) – tanie rozwiązanie, które pozwala na dopasowanie parametrów wyjściowych na bazie algorytmów, co przekłada się na naturalny podział prądu między jednostkami – np. NPST501 ARM (Active Redundancy Module) – zewnętrzny moduł redundancyjny pozwala na zbalansowanie impedancji wyjściowej zasilaczy – każdy zasilacz powinien móc być zastosowany z tym rozwiązaniem, aczkolwiek najlepiej to przetestować Zasady implementacji połączenia PP: Uwzględnij dostępną moc systemu (nie powinieneś sumować mocy wyjściowej zasilaczy, ale sumę pomnożyć przez 0.75-0.8 – nie ma idealnych połączeń). Używaj identycznych modeli zasilaczy – najlepiej z tej samej serii fabrycznej Używaj tylko zasilaczy z trybem Constant Current (inne mogą powodować problemy) Niektóre zasilacze posiadają opcję CC, która jest wyłączona. Zalecane jest jej włączenie. Ogranicz ilość zasilaczy w układzie (najlepiej < 4) Umieść zasilacze możliwie blisko siebie (w takich samych warunkach wilgotności / temperatury, by zredukować wpływ otoczenia) Przed połączeniem ustaw napięcie wyjściowe zasilaczy – podłącz je do obciążenia w wysokości ok. 10% nominalnego. Napięcia powinny być ustawione z dokładnością +/- 20mV. Użyj takich samych przewodów (długość i grubość) między każdą jednostką i obciążeniem. Przewody powinny skupiać się przy obciążeniu, a nie przy zasilaczach – to poprawia symetrię obciążenia. NIE STOSUJ TOPOLOGII DAISY-CHAIN! Po 30 minutach działania zweryfikuj obciążenie prądowe i dostosuj napięcia, by je zbalansować. Parallel Redundancy Rysunek 3: połączenie redundancyjne zasilaczy z diodami Rysunek 4: połączenie redundancyjne zasilaczy z modułem ORing Redundancja jest istotna w przypadku urządzeń krytycznych dla danej architektury. Zabezpiecza ona przed niezapowiedzianą awarią modułu, który może spowodować zagrożenie – zarówno dla ludzi jak i dla maszyn. Dzięki tej technice połączenia maksymalny prąd jest dostępny nawet po wystąpieniu awarii zasilacza, co zapobiega ewentualnym wyłączeniom sprzętu – co za tym idzie należy wykorzystać w tym celu kilka zasilaczy. Oprócz tych zasilaczy należy dodać też zasilacze "nadmiarowe" (redundancyjne) – przynajmniej jeden. Im więcej ich użyjemy tym większe będzie nasze zabezpieczenie przed awariami. By osiągnąć niezawodny system redundancyjny wyprowadzenia zasilaczy powinny być odseparowane modułem ORing (redundancji) lub odpowiednimi obwodami (diodami / tranzystorami MOSFET). Jeżeli jeden z zasilaczy ulegnie uszkodzeniu i zacznie stanowić zwarcie, to obwody te zabezpieczą przed przepływem prądu do uszkodzonego zasilacza, a co za tym idzie spadkowi napięcia i maksymalnej mocy układu. Zasady implementacji połączenia "PR": Ustal ile potrzebujesz nadmiarowych zasilaczy, by osiągnąć zadowalający poziom redundancji. Uwzględnij, iż w danym momencie tylko jeden zasilacz może przyjąć na siebie całe obciążenie (jest to istotne w przypadku modułów Oring, które posiadają określone limity natężenia i napięcia). Zawsze używaj identycznych zasilaczy (najlepiej z tej samej serii). Postaraj się zbalansować napięcie wyjściowe zasilaczy do +/- 20mV – wydłuży to żywotność systemu. Umieść wszystkie zasilacze w tych samych warunkach środowiskowych (temperatura, wilgotność etc.) Użyj identycznych przewodów (długość / grubość), które skupiają się przy obciążeniu – to poprawia symetrię obciążenia. Series Connection Rysunek 5: Połączenie szeregowe zasilaczy Niektóre zastosowania jak np. moduły EuroRack mogą wymagać zastosowania połączenia szeregowego zasilaczy. Takie połączenie pozwala uzyskać napięcie, bądź moc niedostępną dla pojedynczego modułu. Warto mieć na uwadze: Największy dostępny prąd jest równy najmniejszemu prądowi nominalnemu zasilacza w układzie Maksymalna moc jest efektem iloczynu sumy napięć i najmniejszego prądu nominalnego zasilaczy. Jednostki o różnej impedancji / źródłach zasilania / napięciach wyjściowych / mocy mogą być połączone szeregowo. Zasady implementacji połączenia SC: Postaraj się użyć identycznych jednostek (najlepiej z tego samego źródła) Zwróć uwagę na niezbędne dostępne natężenie prądu (by zapobiec przeciążeniu zasilaczy) Niektóre jednostki mogą mieć inny czas rozruchu. By zapobiec odwrotnej polaryzacji należy zastosować diody zabezpieczające (maksymalne napięcie diody powinno być większe niż suma napięć zasilaczy, a maksymalny prąd impulsowy diody powinien być większy niż największe nominalne natężenie zasilacza w układzie). Uważaj, gdy pracujesz z napięciami >60V, które mogą być niebezpieczne dla człowieka. Dopasuj przewody do parametrów układu i połącz je w topologię DAISY-CHAIN w stronę obciążenia. Unikaj używania zbyt dużej ilości zasilaczy (aka. > 4). Inne uwagi Warto sprawdzić, czy zasilacze są odizolowane (czy uziemienie i linia neutralna nie są połączone z masą napięcia DC) – czasami zdarzają się zasilacze, które nie spełniają tych wymogów (mimo, iż naruszają tym przepisy bezpieczeństwa) - jeżeli nie są, to nie należy ich stosować w żadnym z powyższych połączeń! O ile to możliwe unikaj konfiguracji PP, gdyż potrafi ona być bardzo nieprzewidywalna. Jeżeli tworzysz systemy, których działanie jest istotne zastosuj układ redundancyjny.
  2. Wstęp Ten artykuł porusza tematykę doboru mikrokontrolerów do Twojego projektu. Nie jest istotne czy tworzysz prosty sterownik LED, narzędzie do pracy, czy zaawansowane urządzenie pomiarowe. Z tymi wskazówkami bez problemu znajdziesz odpowiedni komponent dla siebie. Artykuł jest kierowany do osób stawiających swoje pierwsze kroki w projektowaniu własnych systemów, które potrzebują podstawowych informacji "na co zwrócić uwagę" podczas wyboru elementu do potrzeb projektowych oraz listy potencjalnych alternatyw. Mikroprocesor, mikrokontroler, FPGA Zanim zgłębimy detale, warto zrozumieć główne rodzaje komponentów, które są kluczowymi jednostkami obliczeniowymi w projektach. Mikroprocesory: To stosunkowo złożone komponenty, które nie posiadają wbudowanej pamięci RAM ani ROM (w kontekście pamięci programu). Były popularne w komputerach domowych, takich jak Commodore 64 czy Atari 2600 pod koniec XX wieku. Charakterystyczne dla nich jest posiadanie magistrali równoległej do podłączenia pamięci i innych układów pomocniczych – nie posiadają wbudowanych peryferiów. Mikrokontrolery: To podzespoły elektroniczne, które zawierają wbudowaną pamięć RAM, a często także pamięć programu (ROM). Istnieją również wersje bez wbudowanej pamięci ROM, takie jak RP2040 lub ESP32D0/ESP32S0. W przypadku braku pamięci programu użytkownik musi dołączyć zewnętrzną pamięć, zazwyczaj wykorzystując interfejs QSPI. FPGA (Field-Programmable Gate Array): To zaawansowane układy do równoległego przetwarzania danych i prototypowania układów scalonych. W projektach hobbystycznych są powszechnie wykorzystywane przy obsłudze wyświetlaczy o dużej rozdzielczości lub w konstrukcji urządzeń diagnostycznych. Ich charakterystyczną cechą jest zdolność do wykonywania wielu operacji jednocześnie, co przewyższa możliwości mikrokontrolerów i mikroprocesorów. SoC (System on a Chip): To samodzielne układy zawierające pamięć RAM i ROM. Nie zawsze możliwe jest zapisywanie w pamięci ROM (czasem zawiera tylko instrukcje bootloadera, a program wgrywamy na kartę SD lub pamięć EMMC). Mimo, że niektóre mikrokontrolery można określić jako SoC, ten termin zazwyczaj odnosi się do zaawansowanych układów, które spotykamy w minikomputerach SBC (Single-Board Computers). Poniższa fotografia 1 przedstawia przykładowy mikrokontroler w obudowie TQFP: Fotografia 1 (Wikipedia, Public Domain) Podstawowe cechy mikrokontrolerów Przed wyborem układu właściwego dla naszego projektu, warto zwrócić uwagę na kilka kluczowych cech. Nie ma tu sztywnej hierarchii, ponieważ ich istotność zależy od konkretnych potrzeb projektowych: Rodzina / architektura: Określa używane środowisko programistyczne oraz narzędzia, takie jak kompilatory i debuggery. Często producenci mikrokontrolerów prześcigają się w udostępnianiu coraz bardziej zaawansowanych narzędzi dla projektantów urządzeń i programistów. Package / Obudowa: Określa liczbę wyprowadzeń i sposób montażu (w tym jak bardzo przy tym będziemy się denerwować) Peryferia: Lista wewnętrznych podzespołów mikrokontrolera, takie jak dostępne magistrale, wsparcie dla protokołów, zegary, DMA czy przetworniki ADC/DAC. RAM i ROM (Flash): Określają dostępną przestrzeń dla programu i zmiennych. Niektóre układy wymagają zewnętrznej pamięci Flash (np. RP2040, ESP32, ESP8266) ADC / DAC: Wbudowane peryferia do obsługi sygnałów analogowych – ADC dla wejść analogowych, a DAC dla wyjść analogowych. Zasługują na osobną sekcję, gdyż często wpływają na wybór układu. Taktowanie i zestaw instrukcji: Określa szybkość działania mikrokontrolera. Niektóre nowsze rdzenie mogą być wydajniejsze, nawet przy niższym taktowaniu, dzięki nowszym zestawom instrukcji. Napięcie zasilania: Definiuje pobór prądu mikrokontrolera, a również konieczność zastosowania konwerterów poziomów logicznych między układem, a zewnętrznymi peryferiami. Architektury mikrokontrolerów Obecnie na rynku wyróżnia się cztery główne „rodziny” mikrokontrolerów: ARM: Te mikrokontrolery, zasilane głównie napięciem 3,3V, są niezwykle wszechstronne i popularne. Bez względu na projekt z pewnością znajdziesz odpowiedni model dla siebie. AVR: Starsza rodzina mikrokontrolerów, wykorzystywana głównie tam, gdzie kluczowa jest niezawodność. Osiągają pełną wydajność przy zasilaniu 5V. Xtensa (ESPressif ESP32/ESP8266): Chińska rodzina mikrokontrolerów na bazie architektury Xtensa, zaprojektowana głównie dla aplikacji IoT. Warto zauważyć, że nie wszystko, co pochodzi z Chin, jest złej jakości, co udowadnia ten układ. RISC-V: To dość nowa otwarta architektura, wykorzystywana do tworzenia zarówno mikrokontrolerów, jak i procesorów. Układy oparte na tej architekturze są podobne do ARM, ale znajdują się w niższym przedziale cenowym ze względu na brak opłat licencyjnych. Jak dokonać wyboru? Często warto zacząć od tego, co już znamy. Jeśli mieliśmy do czynienia z mikrokontrolerami STM32, sensownym krokiem będzie znalezienie w tej rodzinie układu spełniającego nasze potrzeby, a jeżeli go nie znajdziemy to poszukiwanie innego mikrokontrolera na bazie architektury ARM. Jeżeli używaliśmy Arduino Uno to bliżej nam może być do AVR. W innym przypadku, dobieramy układ z dowolnej rodziny, która odpowiada nam pod względem pozostałych kryteriów. Package / Obudowa Mikrokontrolery występują w różnych rodzajach obudów, od tradycyjnych do montażu przewlekanego po nowoczesne, przeznaczone wyłącznie dla montażu powierzchniowego. Wybór obudowy najczęściej zależy od umiejętności lutowniczych. DIP – obudowy przewlekane, najprostsze do przylutowania (wystarczy lutownica transformatorowa, aczkolwiek znacznie wygodniej jest pracować z lutownicą kolbową) SOP, QFP, TQFP, LQFP – obudowy SMT z wyprowadzonymi nóżkami, proste do lutowania z wykorzystaniem grotu typu „minifala” QFN – obudowy SMT z wyprowadzeniami na boku obudowy (bez nóżek) – dość skomplikowane do lutowania grotem minifala (wykonalne, lecz czasochłonne). Najlepiej lutować je gorącym powietrzem lub w specjalistycznym piecu do lutowania rozpływowego. BGA – obudowy SMT z kulkami pod układem. Bardzo trudne do lutowania amatorskiego (wymagają wprawy). Układy te należy lutować wyłącznie z użyciem gorącego powietrza lub pieca do lutowania rozpływowego. Weryfikacja jakości spoin jest praktycznie niemożliwa. Istnieją również gotowe moduły np. ESP32 WROOM czy Arduino Nano, aczkolwiek w tym zestawieniu omawiamy wyłącznie tematykę mikrokontrolerów jako układów scalonych, a powyższe moduły do takich nie należą, ale warto ich używać w fazie prototypowania, gdyż znacząco skracają czas lutowania. Fotografia 2 przedstawia układy logiczne w obudowach DIP, a fotografia 3 zaś pamięć RAM z układami scalonymi w obudowach BGA. Fotografia 2 (Wikipedia, Public Domain) Fotografia 3 (Wikipedia, Smial, CC BY-SA 2.0) Dobrą praktyką jest wybór obudowy z większą liczbą wyprowadzeń niż potrzebujemy (czasem w trakcie projektu okazuje się, że ich brakuje). W bardziej optymistycznym scenariuszu, większa ilość nóżek ułatwi nam wyprowadzenie ścieżek z układu podczas projektowania płytki PCB, jednakowoż należy mieć na uwadze, iż ze wzrostem ilości wyprowadzeń znacząco wzrasta cena układu. Peryferia? Rozważenie potrzebnych peryferii jest kluczowe. Na przykład, jeśli chcesz stworzyć kontroler PID do sterowania grzałkami, potrzebujesz interfejsu do termopary - to może być wejście analogowe albo magistrala, jak np. SPI do podłączenia wzmacniacza MAX6675. Dodatkowo będziesz potrzebować licznika sprzętowego do generowania sygnałów sterujących grzałką. Na powyższym przykładzie widać, iż to, czego potrzebujesz, zależy od konkretnego projektu. W prostych projektach jak ten wymieniony wyżej wystarczy zwykły, najprostszy mikrokontroler - np. CH32V003. Jeśli zaś marzysz o stworzeniu konsoli do gier, potrzebne będzie coś znacznie bardziej potężnego, np. STM32H7*, który ma większą moc obliczeniową i bardziej zaawansowane funkcje, jak wbudowany układ graficzny czy obsługa pamięci zewnętrznej SDRAM. Jakie peryferia i parametry warto mieć na uwadze? Ilość pinów/wyprowadzeń mikrokontrolera (GPIO): Związana z potrzebnymi wyprowadzeniami, jak i zajętymi pinami przez magistrale (I2C, SPI itp.). Magistrale komunikacyjne (I2C, SPI, UART/USART/LIN, CAN, USB): Pomagają w sprzętowej obsłudze komunikacji z innymi modułami, oszczędzając moc obliczeniową mikrokontrolera. Przetworniki ADC: Potrzebne, gdy chcesz mierzyć sygnały analogowe, np. temperaturę na termistorze. I2S/SAI: Jeśli chcesz, by twoje urządzenie miało wbudowany dźwięk (warto zauważyć, że potrzebny będzie zewnętrzny układ do obsługi dźwięku – tzw. „kodek”). Przetworniki DAC: Wbudowany przetwornik cyfrowo-analogowy, który pozwala generować sygnały analogowe bez zewnętrznych układów. DMA – służy do sprzętowego przesyłania danych z pamięci RAM do konkretnego rejestru (nie musi tego robić program), co jest znacznie szybsze, a zarazem oszczędza moc obliczeniową RTC(C) – niektóre mikrokontrolery posiadają wbudowany zegar czasu rzeczywistego i kalendarz, które w przypadku zasilania bateryjnego są w stanie określić aktualną datę. Przydatne w projektach automatycznych zraszaczy czy lampek zapalanych o konkretnej godzinie. To tylko fragment listy, aczkolwiek pokazuje, jak duży wpływ na projekt ma wybór odpowiednich peryferii. Jak widać na 11 stronie niniejszego dokumentu niektóre mikrokontrolery posiadają naprawdę rozbudowane peryferia, a to jest układ „z niższej półki”. Dobrą praktyką jest stworzenie projektu systemu (w formie diagramu funkcjonalności urządzenia), który następnie określi nam jakie elementy sprzętowe będą nam niezbędne (również pozwoli określić pomocnicze układy scalone, lecz jest to temat na inny artykuł). Pomocne mogą być również podobne projekty zrealizowane przez inne osoby oraz dokumentacja układów w nich zastosowanych. Przykładowy projekt systemu ukazuje rysunek 4. Rysunek 4 (źródło własne) RAM/ROM Każdy mikrokontroler ma swoje ograniczenia, szczególnie jeśli chodzi o pamięć programu. Z reguły, tańsze mikrokontrolery mają mniej pamięci programu lub w ogóle jej nie posiadają, wymagając zewnętrznego układu. Dla większości projektów, minimalna ilość pamięci ROM wystarcza. Jednak w bardziej skomplikowanych projektach, jak wspomniana wcześniej konsola do gier, może okazać się, że standardowa pamięć nie wystarczy. Wybór odpowiedniej ilości pamięci ROM jest często kwestią doświadczenia - po prostu nabiera się wprawy. Tu sprawa jest jeszcze trudniejsza. Wiele zmiennych można przenieść poza pamięć RAM, co może znacząco ułatwić życie. Zazwyczaj ilość pamięci RAM rośnie wraz z ilością peryferii w mikrokontrolerze. Oczywiście, jeśli wybraliśmy mikrokontroler bazując tylko na peryferiach, bez uwzględnienia pamięci, to może okazać się, że tej pamięci nam zabraknie (szczególnie w rodzinie AVR, gdzie jest jej mniej), aczkolwiek jest to bardzo rzadko spotykane zjawisko. Warto mieć na uwadze, że bardziej zaawansowane mikrokontrolery posiadają możliwość rozbudowania pamięci RAM za pomocą zewnętrznego układu scalonego (np. W25Q128 lub MT48LC4M32B2B5). Sygnały analogowe – DAC/ADC Czasem chcemy zbudować proste urządzenie diagnostyczne bez używania zewnętrznych przetworników. Tutaj pomocne są peryferia analogowe (o których już wspomnieliśmy). Istotne w ich przypadku są dwa parametry: Rozdzielczość: To, jak dokładnie jest przekształcany sygnał cyfrowy na analogowy. Na przykład, przetwornik 8-bitowy z napięciem referencyjnym 1V ma skok równy 0,0039V między kolejnymi wartościami, zaś przetwornik 16-bitowy o identycznym napięciu referencyjnym ma znacznie dokładniejszy skok w wysokości 0,000015V. Istnieją również przetworniki o wyższej dokładności (24bit, 32bit), które są dedykowane głównie systemom audio. Sample Rate (SPS): To, jak często przetwornik dokonuje odczytów lub zmiany. Przykładowo, 1MSPS oznacza, że przetwornik może odczytywać lub zmieniać swój stan około milion razy na sekundę. W diagnostyce sygnałów o wysokiej częstotliwości (np. w oscyloskopach) potrzebujemy około 10-krotnie większego Sample Rate'a niż częstotliwość sygnału. Innymi słowy, dla sygnału 100MHz potrzebujemy około 1GSPS, aby był wyraźnie widoczny na ekranie urządzenia i nie był nadmiernie przekłamany – przykładowo na jeden okres sinusoidy 100MHz powyższy przetwornik dokona maksymalnie 10 pomiarów, co może spowodować znaczne zniekształcenie sygnału. Staramy się wybierać przetworniki o jak najwyższych parametrach zachowując jednocześnie umiar kosztowy, chyba że budujemy urządzenie do pracy z wysokimi częstotliwościami, jednakowoż wtedy często potrzebny jest sprzęt specjalistyczny – FPGA czy dedykowane przetworniki różnicowe. Dobrym wyborem na start jest układ z przetwornikiem 12-bitowym z szybkością 1MSPS, który spełnia większość potrzeb w projektach hobbystycznych, aczkolwiek w wielu przypadkach 10bit z szybkością liczoną w SPS lub kSPS też wystarczy (np. do odczytywania wartości potencjometru). Inne istotne cechy Jak już zauważyłeś ten artykuł opisuje wyłącznie najbardziej podstawowe parametry wpływające na wybór mikrokontrolera. W rzeczywistości należy brać pod uwagę również te bardziej złożone – np. w przypadku architektury ARM uwzględnić rodzaj rdzenia – np. rdzeń M3 nie posiada wbudowanej sprzętowej akceleracji obliczeń na liczbach zmiennoprzecinkowych (FPU), co już występuje w przypadku rdzenia M4. Tak samo rdzenie o niższej numeracji posiadają np. wolniejsze zestawy instrukcji względem tych o numeracji wyższej. W wielu przypadkach taktowanie mikrokontrolera nie ma znaczenia, aczkolwiek w przypadku systemów, które działają „w czasie rzeczywistym” należy brać pod uwagę czas reakcji takiego mikrokontrolera na określone zdarzenie, który definiowany jest przez ilość cykli od wystąpienia zdarzenia do reakcji oraz właśnie wspomniane taktowanie rdzenia – jeżeli ilość cykli będzie identyczna to mikrokontroler o wyższym taktowaniu szybciej je przetworzy. Oprócz tego są też inne parametry: temperatura pracy, standard wykonania (automotive – przeznaczony dla branży samochodowej, mil-spec – standard wojskowy, industrial – standard przemysłowy), pobór prądu, dostępność stanów uśpienia, to czy mikrokontroler posiada wbudowany moduł RF czy nawet niezbędne komponenty pasywne lub interfejs debuggera (JTAG, SWD, SWIO, ISP...). Dobór mikrokontrolera nie jest wbrew pozorom taki łatwy, a jest to jeden z najbardziej istotnych komponentów, które wpływają na pracę całego urządzenia, więc warto poświęcić na niego dość dużo czasu. Appendix Jeżeli masz problem z doborem mikrokontrolera do projektu przedstaw schemat poglądowy (lub opis) założeń w osobnym wątku, a bardziej doświadczeni użytkownicy forum chętnie podzielą się swoimi opiniami i propozycjami.
  3. Słowem wstępu Niniejszy poradnik jest przeznaczony dla osób, które nie miały dotąd styczności z programowaniem aplikacji wizualno-obiektowych przy użyciu języka C# oraz platformy .NET (czytane jako dotnet). Skupimy się tu na podstawach języka oraz na tym, jak krok po kroku napisać wybrane aplikacje. Na początek trochę teorii Język C# jest odpowiedzą firmy Microsoft na obiektowy język Java. Struktura obu języków jest podobna, a więc osoba programująca do tej pory w Javie szybko będzie mogła stosować w C# znane już sobie mechanizmy. Platforma .NET pozwala na pisanie programów nie tylko w C#, ale także w F#, C++, Visual Basic'u, Pythonie, HTML-u, Javascript’cie czy Node.js - .NET zakłada, że wszystkie języki programowania są równe, jednak to, że Microsoft stworzył język C# oraz platformę .NET sprawiło, że programowanie w tym środowisku przy użyciu języka C# jest najbardziej wydajne. C# oraz platforma .NET pozwala także na pisanie aplikacji sieciowych, jednak ten temat nie zostanie tutaj poruszony. Ten artykuł bierze udział w naszym konkursie! 🔥 Na zwycięzców czekają karty podarunkowe Allegro, m.in.: 2000 zł, 1000 zł i 500 zł. Potrafisz napisać podobny poradnik? Opublikuj go na forum i zgłoś się do konkursu! Czekamy na ciekawe teksty związane z elektroniką i programowaniem. Sprawdź szczegóły » Podstawowa wiedza Zakładam, że część osób czytająca ten poradnik miała już w swoim życiu styczność z jakimś językiem programowania wysokiego poziomu, mimo to zachęcam do zapoznania się z tą częścią poradnika, a także wracania do niej w razie potrzeb. Informacje na temat środowiska oraz zapoznania się z nim będą w oddzielnej części, przeznaczonej tworzeniu aplikacji wizualno-obiektowej. Osobom, które nie wiedzą jednak czym jest język wysokiego poziomu spróbuję wyjaśnić za pomocą skrótu myślowego i odpowiedniego rysunku: W dużym skrócie: istnieją języki wysokiego i niskiego poziomu. Język wysokiego poziomu to ten zrozumiały dla człowieka, mający postać zmiennych, ich nazw, pętli, instrukcji warunkowych itd. Natomiast język niskiego poziomu to ten najbliższy komputerowi, mający postać zer i jedynek, operacji na pamięci itd. Dawno temu ludzie programowali maszyny za pomocą kart perforowanych z wyciętymi dziurami. Było to swoistym językiem niskiego poziomu, dochodziło do błędów i było nieprzystępne dla ludzi. To właśnie było powodem powstania języków wysokiego poziomu oraz kompilatorów/interpreterów tłumaczących je na kod maszynowy. Język C# pozwala nam pracować z poniższymi typami danych byte – przyjmuje wartości od 0 do 255 char – znaki w Unicode bool – prawda / fałsz sbyte – wartości od -128 do 127 short – wartości od -32,765 do 32,767 ushort – wartości od 0 65,535 int – wartości od -2,147,483,648 do 2,147,483,647 uint – wartości od 0 do 4,294,967,295 long – wartości od 18,446,744,073,709,551,615 ulong – wartości od 0 do 18,446,744,073,709,551,615 float – wartości od -3.402823e38 do 3.402823e38 double – wartości od -1.79769313486232e308 do 1.79769313486232e308 decimal – wartości +/- od 1.0 x 10e-28 do 7.9 x 10e28 string – sekwencja znaków Unicode DateTime – format daty i czasu (0:00:00am 1/1/01 do 11:59:59pm 12/31/9999) Oprócz tych typów danych są także typy skalarne enum oraz struct, jednak ich temat nie będzie teraz rozwijany. W wymienionych powyżej typach danych, niektóre posiadają przedrostek u- i oznacza on, że typ jest unsigned czyli nieprzypisany. To z kolei oznacza, że wartości ujemne zostały przeniesione na plus w celu zwiększenia pojemności typu. Środowisko programistyczne W tej części zajmiemy się pobieraniem środowiska oraz jego wstępną konfiguracją. Pobieranie środowiska Środowisko, w którym będziemy programować to Visual Studio Community 2019 i można je pobrać na stronie https://visualstudio.microsoft.com/pl/vs/community/, to środowisko jest darmowe. Wejdź pod podany przed chwilą adres, pobierz instalator i uruchom go na swoim komputerze. Instalacja środowiska jest prosta, więc poruszymy tylko niektóre aspekty z nią związane. Ekran instalatora Visual Studio Installer W tym poradniku potrzebne będzie nam pobranie dodatku Programowanie aplikacji klasycznych dla platformy .NET, znajduje się on w części Komputery i urządzenia przenośne. Instalator powinien sam zaznaczyć wymagane pakiety opcjonalne, jednak dla pewności sprawdź, czy w prawym okienku Szczegóły instalacji są zaznaczone opcje jak na powyższym zdjęciu. W przyszłości oczywiście możesz doinstalować kolejne pakiety przy użyciu programu, który instaluje się razem z Visual Studio (jest to Visual Studio Installer), jednak teraz potrzebne nam będą tylko te domyślnie zaznaczone. Po zaznaczeniu wciskamy przycisk Instaluj znajdujący się w prawym dolnym rogu. Po instalacji może być wymagane zalogowania się do konta Microsoft. Tworzenie projektu Po uruchomieniu Środowiska wybieramy opcję Utwórz nowy projekt. Ekran użytkownika po uruchomieniu środowiska Najpierw skupimy się na aplikacji konsolowej. Znajdź szablon "Aplikacja Konsolowa", upewnij się że wybrana opcja ma tag C# Nadajmy projektowi nazwę np. Hello World. W informacjach dodatkowych na razie nic nie zmieniamy. Wybieramy Utwórz i naszym oczom powinno pokazać się środowisko, w którym będziemy pracować. Domyślnie wygenerowana aplikacja konsolowa będzie miała już napisany kod programu Hello World, skupimy się więc na jego analizie oraz dodatkowych informacjach, które mogą się przydać. using System; namespace Hello_World { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } } Na początek zaczniemy od funkcji Main. Znajdująca się w niej metoda WriteLine może odstraszać początkującego programistę, jednak spokojnie. Pracujemy z aplikacją konsolową, a co za tym idzie, jeśli chcemy wypisać coś w konsoli, musimy odwołać się do metody wypisz linie (WriteLine). Metoda ta należy do klasy konsola (Console). Metody oraz klasy można zrozumieć skrótem myślowym, w tym wypadku będzie to Konsola wypisz linie „Hello World!” class Program (klasa Program) jest klasą wygenerowaną, więc możemy napisać dla niej metodę, do której później będziemy mogli się odwołać, podobnie jak przy użyciu Console.WriteLine(); namespace Hello_World może wyglądać znajomo osobom, które pisały już w C++, gdzie dla ułatwienia stosowały using namespace std; w C# namespace deklaruje zakres (proste wytłumaczenie, czym jest zakres znajdzie się na końcu poradnika) jednak ten temat rozwiniemy za chwilę przy użyciu przykładu. W celu zademonstrowania i ułatwienia zrozumienia wiedzy zdobytej do tej pory, napisałem poniższy kod: using System; namespace Hello_World { class Klasa_HelloWorld { public static void Hello() { Console.WriteLine("Hello World!"); } } } namespace wypisywanie { class Klasa_Wypisywanie { static void Main(string[] args) { Hello_World.Klasa_HelloWorld.Hello(); } } } Aby uruchomić program klikamy przycisk oznaczony zielonym trójkątem Działanie kodu wygląda następująco: Wyjaśnię więc, co dzieje się po uruchomieniu programu. Funkcja Main znajdująca się w klasie Wypisywanie z namespace wypisywanie ma w sobie odwołanie do Metody Hello() klasy o nazwie Klasa_HelloWorld zakresu Hello_World. Sama klasa metoda jest publiczna (public static void). Z kolei metoda Hello() nie należy to klasy, w której jest wywoływana, jednak modyfikator dostępu public pozwala na jej wykorzystanie. Instrukcje wejścia/wyjścia Zanim przejdziemy dalej, trzeba wspomnieć o tym jak wyglądają instrukcje wejścia/wyjścia w C#. namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { String input = Console.ReadLine(); Console.WriteLine(input); } } } Dwa podstawowe polecenia wejścia i wyjścia to Console.ReadLine() oraz znane nam już Console.WriteLine(), w tym wypadku utworzyłem zmienną input, która jest ciągiem znaków (String) i przekazałem programowi, że zawiera w sobie to, co użytkownik wpisze w konsoli. Wykonywanie działań w języku C# Jak pewnie się domyślasz, w języku C# można wykonywać działania arytmetyczne, operatory arytmetyczne. Wyniki ich działań pokazuje poniższy kod. namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { double a = 10; double b = 4; Console.WriteLine(a + b); //dodawanie wynikiem będzie 14 Console.WriteLine(a - b); //odejmowanie wynikiem będzie 6 Console.WriteLine(a * b); //mnożenie wynikiem będzie 40 Console.WriteLine(a / b); //dzielenie wynikiem będzie 2,5 Console.WriteLine(a % b); //reszta z dzielenie wynikiem będzie 2 } } } Dla ułatwienia przekazu posłużyłem się zdefiniowanymi wartościami a oraz b, by w komentarzu (czym jest komentarz, wyjaśnię na końcu poradnika) pokazać przykładowe wyniki działań. W swoim kodzie możesz oczywiście wpisywać te zmienne przy użyciu polecenia Console.ReadLine(). Instrukcje warunkowe Pierwszą instrukcją warunkową, której działaniu się przyjrzymy jest if. Instrukcja warunkowa if przyjmuje jeden argument i wykonuje odpowiedni kod, jeśli argument jest spełniony. Warto także wspomnieć o słowie kluczowym else, które wykonuje inny kod, jeśli warunek nie został spełniony. Z połączenia obu tych poleceń wychodzi else if, który pozwala na doprecyzowanie kolejnego warunku. namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { String input = Console.ReadLine(); if(input == "hello") { Console.WriteLine("Hello World!"); } else if (input == "poradnik") { Console.WriteLine("Witamy w poradniku programowania w C#"); } else { Console.WriteLine("podano błędną wartość"); } } } } Powyższy kod sprawdza, czy użytkownik wpisał w konsoli słowo hello lub poradnik, i wykonuje odpowiednie polecenia. Jeśli zaś użytkownik wpisał coś innego, kod wyświetli komunikat o podaniu błędnej wartości. Drugą instrukcją warunkową, którą poznamy jest switch. Słowa kluczowe switch oraz case działają na podobnej (lecz nie identycznej) zasadzie co if i else. Różnica polega na wygodzie pisania oraz czasie wykonywania instrukcji (nie będzie tu poruszana szczegółowa analiza różnic w działaniu obu instrukcji). namespace Hello_World { class Program { static void Main(string[] args) { String input = Console.WriteLine(); switch (input) { case "hello": Console.WriteLine("Hello World!"); break; case "poradnik": Console.WriteLine("Poradnik programowania w C#"); break; default: Console.WriteLine("podano błędną wartość"); break; } } } } Powyższy kod działa identycznie jak ten z wykorzystaniem if oraz else. Słowo kluczowe break przerywa działanie funkcji oraz pętli. Pętle w języku C# Teraz spróbujmy wypisać w konsoli napis „Hello World!” 10 razy, można oczywiście w tym celu skopiować fragment kodu odpowiedzialny za to 10 razy. Jednak co w wypadku, gdy stwierdzimy, że 10 razy to za mało? Wtedy kopiowanie kodu nie ma sensu. Do uproszczenia tego procesu posłużą nam pętle. Osobom, które są już zapoznane z pętlami, ten fragment nie wniesie nic nowego, można więc go pominąć. Osobom, które chcą sobie powtórzyć lub nie wiedzą nic o pętlach warto powiedzieć że istnieją cztery różne pętle: for foreach while do while Pętla for namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { for(int i = 0; i<10; i++) { Console.WriteLine( i + " Hello World!"); } } } } Pętla for przyjmuję trzy argumenty, na obrazku są to kolejno: int i = 0 - ten argument wykonuje się tylko raz na początku wykonywania pętli; jest to zmienna, z którą pętla rozpoczyna swoje działanie; i<10 - to warunek pętli, w tym wypadku pętla będzie się wykonywała tak długo, aż wartość zdefiniowanej przed chwilą zmiennej będzie mniejsza od 10; i++ - to inkrementacja zmiennej czyli podniesienie jej wartości o 1 z każdym wykonaniem pętli. Pętla foreach namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { int[] tablica = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; foreach(int i in tablica) { Console.WriteLine( i + " Hello World!"); } } } } Pętla foreach wykonuje się dla każdego elementu tablicy. W tym wypadku zdefiniowałem tablicę liczb całkowitych int[], jako tablicę zawierającą 10 elementów. Pętla foreach przyjmuje dwa argumenty w tym wypadku int i inny, będący dowolnym elementem tablicy oraz in tablica, będący wskazaniem tablicy. While i do while namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { int i = 0; while (i < 10) { Console.Write(i + " Hello World!"); i++; } } } } Pętla while przyjmuje jeden warunek i będzie się wykonywać do momentu, kiedy warunek zostanie spełniony. namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { int i = 0; do { Console.Write(i + " Hello World!"); i++; }while (i < 10); } } } Pętla do while jest podobna do pętlu while, z tym że wykona się przynajmniej raz, niezależnie od prawdziwości warunku. namespace wypisywanie { class Wypisywanie { static void Main(string[] args) { int i = 11; do { Console.Write(i + " Hello World!"); i++; }while (i < 10); } } Na powyższym obrazku widać, że do while wykonało się raz, mimo iż warunek nie jest spełniony. Ćwiczenie Przy użyciu zdobytej wiedzy spróbuj napisać prosty kalkulator obsługujący działania na dwóch liczbach. Wskazówka do Ćwiczenia W razie problemów z pisaniem postaraj się wyobrazić sobie albo narysować schemat działania twojego programu. Czy ma najpierw wypisać komunikat i oczekiwać na wybranie danego działania? Ma poprosić o podanie liczb na których ma operować, czy w inny sposób ma poprowadzić użytkownika do wykonania działania? Pierwsza aplikacja wizualno-obiektowa W tej części poradnika zajmiemy się pisaniem twojej pierwszej aplikacji z interfejsem użytkownika. Na początku skoncentrujemy się na potrzebnych nam elementach środowiska i podstawowych kontrolkach, które będziemy wykorzystywać, potem zajmiemy się pisaniem prostego kalkulatora. Tworzenie nowego projektu W tej części poradnika dalej będziemy pracować ze środowiskiem Visual Studio Community. W poprzedniej części zainstalowaliśmy wszystkie potrzebne nam elementy tego środowiska, które będą nam potrzebne podczas tworzenia projektu. Po uruchomieniu Visual Studio wybieramy opcję „Utwórz nowy projekt”. Następnie z listy wybieramy „Aplikacja Windows Forms”, jeśli masz problem ze znalezieniem odpowiedniej opcji, możesz wpisać ją w wyszukiwarce szablonów. Klikamy „Dalej” i nadajemy naszemu projektowi odpowiednią nazwę. Po nadaniu nazwy i kliknięciu „Dalej” pojawi się okienko proszące nas o wybranie wersji .NET, z którą chcemy pracować. W tym poradniku pracujemy z .NET Core 3.1. Po upewnieniu się, że wybraliśmy odpowiednią opcję, klikamy „Utwórz”. Po utworzeniu projektu pokaże nam się takie okno. Znajduje się na nim puste okienko aplikacji, którą teraz tworzymy. Możemy uruchomić projekt w taki sam sposób jak robiliśmy to z aplikacją konsolową. Klikamy nazwę naszego projektu, która jest obok zielonej strzałki i po chwili pojawi nam się takie same okienko jak w środowisku. Możemy to okienko zamknąć w taki sam sposób jak inne aplikacje komputerowe - krzyżykiem znajdującym się w prawym górnym rogu. Jednak lepiej zamykać projekt z poziomu środowiska, ponieważ przy bardziej rozbudowanych projektach zamknięcie okienka nie musi oznaczać końca działania aplikacji. Znajdź czerwony kwadrat w w górnej części środowiska, będzie w tym samym miejscu, co przycisk odpowiedzialny za uruchomienie aplikacji. Czerwony kwadrat zatrzyma działanie aplikacji, opcję po lewej i prawej stronie czerwonego kwadratu odpowiadają kolejno za wstrzymanie działania programu oraz za ponowne uruchomienie. Potrzebne informacje o środowisku Teraz skupimy się na elementach środowiska, których będziemy potrzebować. Po lewej stronie będzie zwinięty pasek o nazwie Przybornik. Na górze listy Przybornika znajduje się wyszukiwarka, pozwala w szybki sposób znaleźć potrzebne nam elementy interfejsu. Skupimy się teraz na kontrolce „Button” oraz „TextBox”. Na powyższych zdjęciach znajdują się potrzebne nam kontrolki znalezione przy użyciu wyszukiwarki. Po znalezieniu odpowiednich kontrolek przeciągamy je na obszar roboczy. W związku z tym, że w poradniku zajmujemy się pisaniem aplikacji „Kalkulator”, potrzebne nam będzie 16 przycisków (10 numerycznych i 6 funkcyjnych) oraz jeden TextBox do wyświetlania wyniku. Dla ułatwienia sobie pracy, po przeciągnięciu pierwszego przycisku ustaw jego wymiary na takie, które chcesz mieć w projekcie końcowym. Późniejsza zmiana rozmiarów wielu elementów może być czasochłonna i nieprzyjemna. Aby zmienić rozmiar przycisku kliknij go i rozciągnij używając charakterystycznych punktów, które się pojawią. Gdy już nadasz kontrolce odpowiednie wymiary, możesz ją skopiować skrótem klawiszowym ctrl + c i wkleić kolejne przyciski o tych samych wymiarach. Wymiary kontrolki TextBox zmienia się w identyczny sposób, jednak jeśli chcesz ustawić jej wysokość, musisz wybrać opcję MultiLine klikając kolejno trójkącik nad wybranym TextBox’em, a następnie opcję MultiLine. Po dodaniu wszystkich potrzebnych kontrolek, moja propozycja wyglądu aplikacji prezentuje się następująco: Po napisaniu kodu aplikacja byłaby funkcjonalna, jednak jej wygląd oraz podpisy nie są przyjazne użytkownikowi, dlatego aby to zmienić, możemy dostosować wszystkie elementy interfejsu. Po wybraniu dowolnego elementu w prawym dolnym rogu środowiska pojawią nam się właściwości, które dla tego elementu możemy zmienić. Zachęcam do samodzielnego zapoznania się ze wszystkimi elementami, dlatego teraz skupmy się tylko na podstawowych, które będą nam potrzebne. Na początek zmienimy nazwę przycisku oraz tekst, jaki jest w nim wyświetlany. By zmienić nazwę w segmencie Design zmienimy właściwość (Name) na liczba_7 oraz w segmencie Wygląd właściwość text na 7. Możemy tez dostosować wygląd, zmieniając właściwości z segmentu Widok, takie jak BackColor (kolor tła), BorderSize z listy FlatApperance (grubość ramki wokół przycisku) oraz FlatStyle (ogólny wygląd przycisku. Zachęcam do samodzielnej zabawy tymi ustawieniami i zobaczenia jak wpływają na wygląd kontrolki. W ten sam sposób możesz również zmienić ustawienia okienka klikając na nie i zmieniając np. kolor tła albo rodzaj ramki. Teraz zmienimy ustawienia TextBox’a. Zmień właściwość Text na przykładowy ciąg liczb, TextAlign na Right oraz rozmiar czcionki właściwością Font, dostosuj czcionkę do rozmiaru kontrolki (pamiętaj, żeby usunąć wybrany przez siebie ciąg liczb po dobraniu satysfakcjonujących ustawień czcionki) . Zaproponowany przeze mnie wygląd aplikacji jest teraz taki: Teraz dodajmy naszemu kalkulatorowi kod, by zapewnić mu pewną funkcjonalność. Po podwójnym kliknięciu na kontrolkę, środowisko wygeneruje nam fragment kodu odpowiedzialny za wykonanie poleceń mających miejsce po kliknięciu przycisku w programie. Kliknij dwukrotnie na wszystkie przyciski. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WinFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void liczba_1_Click(object sender, EventArgs e) { } } } Na powyższym obrazku widać wygenerowany kod. Zauważ, że funkcja void przyjmuje nazwy takie jak nazwy kontrolek, które przed chwilą stworzyłeś. W programie potrzebne będą nam trzy zmienne globalne: jedna przechowująca znak działania, jedna przechowująca wynik i jedna zmienna kontrolna. Double wynik = 0; //wynik działania String operacja = ""; //zmienna przechowująca znak działania bool czyPrzeprowadzaOperacje = false; //zmienna kontrolna do sprawdzania czy można przeprowadzić operacje Żeby móc wykonywać działania, potrzebne będą nam liczby. W tym celu dla każdej kontrolki w kodzie musimy przypisać wartość liczbową. private void liczba_7_Click(object sender, EventArgs e) { czyPrzeprowadzaOperacje = false; Button przycisk = (Button)sender; textBox1.Text = textBox1.Text + przycisk.Text; } Powyższy kod zadziała dla każdej kontrolki, można by go użyć nawet bez wklejania do każdej funkcji _Click, jednak dla ułatwienia skupimy się na prostszej wersji. Zanim wkleisz kod do wszystkich funkcji, wyjaśnię ci, w jaki sposób on działa. Na samym początku zmienna czyPrzeprowadzaOperacje jest ustawiona na fałsz. Użyjemy tej zmiennej, żeby upewnić się, że kod będzie działał dokładnie tak jak tego chcemy. Kolejna linijka “Button button = (Button)sender” na niewtajemniczonych robi wrażenie, jednak jest to bardzo proste. Ta linijka tworzy nowy obiekt typu Button o nazwie przycisk, zaś (Button)sender w uproszczeniu tworzy nadawcę. Cała funkcja należy do przycisku 7, który jest nadawcą, więc ta linijka sprawia, że nasz przycisk może „odebrać” informacje sam od siebie. Ostatnia linijka jest łatwa do zrozumienia. Chcemy przypisać tekst dla pola tekstowego i, aby to zrobić, wywołujemy Text z textBox1, a następnie przypisujemy mu tekst zawarty w przycisku (w tym wypadku jest to 7). Teraz możesz skopiować ten kod dla innych liczb. Nie martw się, nic złego się nie stanie 😊. Jak już skopiujesz ten kod w odpowiednie miejsca, uruchom program i upewnij się, że wszystkie liczby wyświetlają się poprawnie. Następnie potrzebny nam będzie kod sprawdzający, jaka operacja została wybrana. private void dzielenie_Click(object sender, EventArgs e) { Button button = (Button)sender; if (wynik != 0) { rownosc.PerformClick(); operacja = button.Text; czyPrzeprowadzaOperacje = true; } else { operacja = button.Text; wynik = Double.Parse(textBox1.Text); textBox1.Text = " "; czyPrzeprowadzaOperacje = true; } } Pozwoli na to powyższy kod. Podobnie jak poprzednio, ten sam kod możesz zastosować dla każdego przycisku osobno. Zanim jednak go powklejasz tam gdzie trzeba - trochę wyjaśnień. Zajmę się rzeczami, które wykorzystujemy po raz pierwszy. Linijka rownosc.PerformClick() ta linijka odwołuje się do kontrolni o nazwie rownosc, a PerformClick() to metoda, która wykona kod w przycisku równości bez jego kliknięcia. Stanie się tak, tylko jeśli wynik będzie różny od zera. Linijka wynik = Double.Parse(textBox1.Text) przypisze zmiennej wynik wartość z textbox1 nie możemy tego jednak zrobić bezpośrednio, w tym celu użyjemy metody Parse by zmienić string zawierający ciąg liczbowy na typ Double. Niezależnie od spełnienia instrukcji warunkowej if, zmieniamy zmienną czyPrzeprowadzaOperację naprawdę. Teraz potrzebna nam funkcja, która wykonuje obliczenia. private void rownosc_Click(object sender, EventArgs e) { switch (operacja) { case "+": textBox1.Text = (wynik + Double.Parse(textBox1.Text)).ToString(); break; case "-": textBox1.Text = (wynik - Double.Parse(textBox1.Text)).ToString(); break; case "*": textBox1.Text = (wynik * Double.Parse(textBox1.Text)).ToString(); break; case "/": textBox1.Text = (wynik / Double.Parse(textBox1.Text)).ToString(); break; default: break; } wynik = Double.Parse(textBox1.Text); } Powyższy kod wykorzystuje instrukcję switch case w celu sprawdzenia jaką operację chcemy wykonać. Jeśli spełnimy jeden z warunków, wtedy wykona się odpowiednie działanie. Skupimy się teraz na tym, co nowe. W każdej instrukcji case możesz zauważyć metodę ToString(), w tym wypadku używamy jej, żeby wyświetlić wynik obliczeń w textBox’ie. Zauważ, że wykonujemy obliczenia na typach liczbowych, których nie możemy bezpośrednio wyświetlić, właśnie dlatego używamy metody ToString(). Na koniec zostało nam tylko zajęcie się przyciskiem CE. Dla zapewnienia jego funkcjonalności wykorzystamy poniższy kod. private void CE_Click(object sender, EventArgs e) { textBox1.Text = " "; wynik = 0; } Dodatkowe objaśnienia pojęć, które wystąpiły w poradniku Zakres – dla ułatwienia przekazu posłużymy się przykładem static void Main(string[] args) { //to jest zmienna x z tego zakresu int x = 3; } void InnaFunkcja() { //to jest zmienna x z tego zakresu String x = "Hello"; } W powyższym fragmencie kodu znajdują się dwie funkcje, każda z tych funkcji jest ograniczona przez „agrafki” (otwarcia „{„ oraz zamknięcia „}”) te agrafki są zakresem tej funkcji, co sprawia, że wszystko co się w nim znajduje, jest widziane tylko w tym zakresie i nie jest dostępne poza nim. Komentarz – w języki C# możemy „zakomentować” fragmenty kodu, oznacza to, że kompilator nie będzie brał tego fragmentu pod uwagę przy kompilowaniu naszego kodu. Istnieją dwa rodzaje komentarza: jednoliniowy oraz wieloliniowy, pokazane na poniższym obrazku: static void Main(string[] args) { //to jest komentarz jednoliniowy /** to jest komentarz wieloliniowy */ } Praca domowa Chciałbym, abyś po ukończeniu tego poradnika samodzielnie zapoznał się z właściwościami kontrolek i zmieniał ich wygląd. Postaraj się także dodać dodatkową funkcjonalność w postaci obsługi liczb dziesiętnych, potęg oraz pierwiastków. Powodzenia 😊.
  4. Cześć, jesteśmy grupą studentów, którzy na swój projekt inżynierski postanowili stworzyć niedużego robota sterowanego za pomocą interaktywnej maty. Robot sterowany jest za pomocą sekwencji, które wprowadzamy na wyżej wymienionej macie. Możemy dawać mu proste komendy pozwalające na poruszanie się. Alternatywnym trybem jest jazda swobodna pozwalająca na sterowanie robotem w czasie rzeczywistym. Mata jest urządzeniem posiadającym układ przycisków 4x4 i ekran pokazujący aktualnie wpisywaną sekwencję. Posiadając podstawową wiedzę na temat programowania i elektroniki, będziesz mógł skonstruować taki zestaw sam, w zaciszu swojego domu. Bardziej szczegółowe informacje na temat samego projektu znajdziesz w samym poradniku. Repozytorium jest podzielone na pięć folderów. Dzielą się one na: Kod robota - znajduje się tu gotowy kod, dzięki któremu robot będzie w stanie się poruszać. Kod maty - znajduje się tu gotowy kod, dzięki któremu będziemy w stanie wysyłać komendy z maty do robota. Schemat robota - wymagane pliki do zamówienia płytki pcb do robota. Schemat maty - wymagane pliki do zamówienia płytki pcb do robota. Instruktaż - szczegółowy poradnik zawierający wymagane materiały oraz opis budowy robota i maty. Zalecamy z zapoznaniem się dokładnie z poradnikiem przed próbą konstrukcji. Spis treści znajdziesz w pliku README w folderze "Instruktaż". Powodzenia! Chcielibyśmy tutaj jeszcze dodać, że wykonując projekt trzeba liczyć się z pewnymi wydatkami. Orientacyjne koszty na dzień 16 stycznia 2020: Robot - koszt wszystkich części robota to około 130zł, jeśli kupujemy na botlandzie. Można zmniejszyć koszta kupując części na przykład na aliexpress, jednak wydłuży to czas w jakim części do nas przyjdą. Mata - koszt wszystkich części maty wynosi około 205zł, podobna sytuacja jak z częściami u robota, koszty można zmniejszyć kupując części na przykład z allegro lub aliexpress. Zdjęcia końcowe produktów: Robot Mata Więcej informacji na temat projektu oraz poradnik ze wszystkimi potrzebnymi plikami znajdują się w repozytorium PS. Schemat do robota zostanie jeszcze zaktualizowany w ciągu kilku najbliższych dni, ponieważ wykryliśmy błąd. Mogą również nastąpić mniejsze zmiany w samych opisach.
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.