Skocz do zawartości

Przeszukaj forum

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

  • 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 - roboty
    • Projekty - DIY
    • Projekty - DIY (początkujący)
    • Projekty - 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
    • Kosz

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


Znaleziono 21 wyników

  1. Witam serdecznie Jak nie ten dział to proszę przenieść:) Zbudowałem pixel poi na podstawie projektu z dwóch stron: https://learn.adafruit.com/supernova-poi oraz: https://forum.pjrc.com/threads/30020-Teensy-APA102-POV-Poi-Pixel-Poi-Build-Tutorial. Działa to wszystko całkiem przyzwoicie ale projekt jest rozwojowy. Przede wszystkim chciałbym napisać program pod windows do wgrywania grafik(otwarte oprogramowanie w którym jak będę chciał zbudować większy czy mniejszy wyświetlacz będzie opcja podania ilości diod czy np sterowania przez bluetooth bądź bez) Chce dodać karty sd i zmienić miejsce włącznika(miałby go zastąpić micro-styk na górze przy zaczepie łańcucha o ile można załatwić to programowo). Na rękojeści miałby znaleźć się włącznik programu. Chciałbym zacząć od dopisania kodu żeby po uruchomieniu przez kilka sekund na pasku led wyświetlał się stan naładowania baterii(w środku znajduje się ogniwo 18650). Ktoś wie jak to zrobić?? Jaki kod i gdzie wpisać?? Mój kod to: #include "FastLED.h" #define NUM_LEDS 60 #define DATA_PIN 13 #define CLOCK_PIN 11 CRGB leds[NUM_LEDS]; //int numberOfSlices = 150; void setup() { delay(200); FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN,BGR>(leds, NUM_LEDS); } //for post use this> const unsigned int array1[] = { 0xfaa60f, 0xffaf10, 0xffb914, 0xf7b312, 0xd99a01, ...... const unsigned int array2[] = { 0x080300, 0x050102, 0x000005, 0x000106, 0x020307,... void PoiSonic(unsigned long time, const unsigned int array[], int sliceNumber); void loop() { PoiSonic(10000,array1,120);//15 PoiSonic(10000,array2,256);//16 } void PoiSonic(unsigned long time, const unsigned int array[], int sliceNumber){ unsigned long currentTime = millis(); while (millis()< currentTime + (time)) { int f= sliceNumber;// previously used numberOfSlices; int z; //a counter int j=NUM_LEDS; for (int x=0;x<f;x++){ for(z=NUM_LEDS;z>0;z--){ leds[z-1]=array[x+((j-z)*f)];} FastLED.show(); delayMicroseconds(40); //may need to increase / decrease depending on spin rate } delayMicroseconds(1000); //may need to increase / decrease depending on spin rate } }
  2. Cześć! Jako nowy użytkownik, przede wszystkim chciałbym się przywitać. Szukam pomocy w zrealizowaniu projektu (oczywiście zapłacę)- zdalnie sterowanego wózka inwalidzkiego. Historia i pomysł są następujące: Poruszam się na wózku, ręcznym. Proces poruszania się, wolałbym zautomatyzować dla własnej wygody, a niejednokrotnie potrzeby. Mam na stanie hulajnogę Xiaomi m365, którą chciałbym wykorzystać podczas prac (silnik, sterownik, bateria). Wózek, czyli ramę, koła i tapicerkę mogę zrobić sam. Cóż mi zatem potrzebne? Osoba, która zajmie się oprogramowaniem sterowania silnikiem skręcania, silnikiem napędowym i zintegrowania tego w jeden, najlepiej bezprzewodowy, obsługiwany jedną ręką kontroler, jak np ten: Chciałbym, aby wózek wyglądał mniej więcej tak: Co chciałbym otrzymać: Jak wspomniałem powyżej, zintegrowane sterowanie wózkiem inwalidzkim z poziomu bezprzewodowego, obsługiwanego jedną ręką kontrolera. Pomoc w zakresie doboru i zakupu niezbędnych materiałów (silnik do sterowania, wszelkiego rodzaju sterowniki, arduino (bądź inna platforma), etc). Optymalnie byłoby, gdyby wykonawca był z okolic Poznania, lub Wrocławia. Sam pochodzę z Leszna, byłoby fantastycznie, gdybym mógł w tym procesie uczestniczyć i czegoś się nauczyć. Chciałbym oczywiście dzielić się z Wami postępami prac, także będę je tu publikował. Będzie to dla mnie bardzo ważny projekt, gdyż po osiągnięciu celu, miałbym kilka nowych pomysłów do realizacji i byćmoże komercjalizacji.
  3. Witam serdecznie! Chciałbym się podzielić stworzoną przez siebie graficzną aplikacją na Raspberry Pi 4 do podkręcania i wyświetlania informacji o systemie (wersja jądra, akutalna temperatura procesora, aktualne jego zużycie). DZIAŁA TYLKO NA RASPBERRY PI 4 Aplikacja nadal jest w rozwoju więc jeszcze nie jest idealna lecz wyżej wymienione funkcje spełnia https://github.com/Jack477/CommanderPi
  4. Płytka prototypowa AVR Witam mam dla was do zaprezentowana płytkę prototypową z mikrokontrolerem AVR w obudowie DIP40. Zaprezentowany układ został wykonany dla osób zaczynających zabawę z mikrokontrolerami AVR. Płytka PCB ma wymiary 132mm x 69mm. Został wykonany w programie KiCad. Schemat umieszczony poniżej składa się z Płytki dwuwarstwowej Mikrokontrolera AVR DIP40 Wyświetlacza 7-segmentowego Wyświetlacza LCD HD44780 Dwóch mostków H w jednej obudowie 5 przycisków przycisków 1. Obok mikrokontrolera są umieszczone jego wyprowadzenia. Do obu wyświetlaczy wyprowadzenia umieściłem obok goldpinów Portu A dla LCD oraz Portu C dla 7-segmentowego (odpowiedzialnego za załączenie segmentów) Umożliwia to łatwe połączenie używając zworek. Każdy podłączony układ ma doprowadzone zasilanie. 2. Mikrokontroler AVR – Płytka przystosowana jest do mikrokontrolerów AVR w obudowie DIP40. Nie wyposażyłem układ w programator. Lecz zastosowałem złącze ISP 10-pinowe. Programator to koszt ok 20 pln. Podłączyłem do układu zewnętrzny rezonator kwarcowy w obudowie HC-49 przy montażu należy pamiętać o przylutowaniu adaptera. Daje to możliwość zamiany taktowania procka. 3. Wyświetlacz 7-segmentowy jest to element ze wspólną anodą Jest to układ który ma już wyprowadzone i połączone segmenty i anody poszczególnych cyfr. Do obsługi wyświetlacza wykorzystywane są piny wyprowadzone przy Porcie C (segmenty) oraz obok wyświetlacza (Anody). Segmenty posiadają również rezystory 220 Ω. Można również zastosować wyświetlacz ze wspólną katodą ale należy pamiętać o tym pisząc program. 4. Wyświetlacz LCD HD44780 nie występuje on w prezentowanym układzie ma on wyprowadzenia na PCB. Jest możliwa jedynie komunikacja 4-bitowa, która oszczędza na ilości potrzebnych połączeń między mikrokontrolerem a ekranem. Wykorzystać można wiele rozmiarów wyświetlaczy. Najczęstszym jest 1602 który posiada dwa wiersze oraz 16 kolumn. Czyli 32znaki. Jest też możliwość podłączenia ekranu 2004 i zależność kolumn i wierszy jest identyczna jak w opisywanym wcześniej ekranie. Pod ekranem jest miejsce na zworkę RW która odpowiada za komunikacje zwrotną z LCD do mikrokontrolera. Nie korzystając z tej opcji należy przełączyć pomiędzy RW a GND. Obok zworki RW jest miejsce na przylutowanie potencjometru do ustawienia kontrastu. 5. Mostek H jest to element do pełnej obsługi silników. Układ L293D jest w obudowie DIP 16. Układ ten pozwala sterować w pełni (prędkość, kierunek obrotów) dwoma silnikami DC. Można również podłączyć opisywany układ do silnika krokowego bipolarnego. Dzięki wyprowadzeniom można wykorzystać zewnętrzne napięcie przystosowane do danego silnika. W każdym z silników możemy decydować o prędkości obrotowej wykorzystując złącze PWM oraz kierunkiem przy użyciu wejść 1A, 2A lub 3A, 4A (np. 1A Vcc , 2A GND -> obroty w prawo) 6. Ostatnim opisywanymi elementami są przyciski. Są one podjęte a stałe do GND a drugie końce wyprowadzeń są podłączone do złączy goldpinowych. Projekty które można zrealizować na omawianym PCB Migotanie diodami LED (należy pamiętać o podłączeniu co najmniej jednego wyprowadzenia Anod do GND) Sterowaniem Wyświetlaczem LED 7 segmentowym (multipleksacja) Obsługa wyświetlacza LCD Sterowanie silnikami DC w wykorzystaniem PWM Sterowanie silnikiem krokowym bipolarnym obsługa klawiszy (sprawdzenie stanu na pinie) Obecny układ jest pierwszą wersją po której nastąpią poprawki. W kolejnych etapach rozwoju chciałbym dodać osobne diody LED podpięte na stałe do 5V lub GND wraz z rezystorami. Dołączyć dwa moduły jednym jest ekspander pinów pracujący na magistrali TWI (I2C) oraz moduł termometru cyfrowego DS18B20 połączonego za pomocą komunikacji 1-wire. Poprawić układ PCB (układ ścieżek, wymianę obudów na inne). Zachęcam do zadawania pytań, pisania sugestii oraz krytyki w celu dalszego rozwoju. W załączniku dołączam plik rar z wszystkimi plikami KiCad'a.Board 1.rar Pozdrawiam
  5. Dzisiaj próbowałem nauczyć się sterować kilkoma funkcjami jednym przyciskiem za pomocą "switch case" i coś mi nie wyszło. Z założenia program po wciśnięciu przycisku miał zapalać diodę, gasić ją po 2 sekundach .Po kolejnym przyciśnięciu przycisku zapalać następną diodę , gasić po 2 sekundach i tak dalej... Zamiast tego diody same zapalają się i gasną po kolei . Z góry dziękuje za odpowiedzi. szkic programu: #define przycisk 6 #define led1 7 #define led2 8 #define led3 9 #define led4 10 byte x = 0; void setup (){ digitalWrite(led1,LOW); digitalWrite(led2,LOW); digitalWrite(led3,LOW); digitalWrite(led4,LOW); pinMode(led1,OUTPUT); pinMode(led2,OUTPUT); pinMode(led3,OUTPUT); pinMode(led4,OUTPUT); pinMode(przycisk,INPUT_PULLUP); } void loop(){ if(digitalRead(przycisk == LOW)){ switch(x){ case 0: digitalWrite(led1,HIGH); delay(2000); digitalWrite(led1,LOW); x=1; break; case 1: digitalWrite(led2,HIGH); delay(2000); digitalWrite(led2,LOW); x=2; break; case 2: digitalWrite(led3,HIGH); delay(2000); digitalWrite(led3,LOW); x=3; break; case 3: digitalWrite(led4,HIGH); delay(2000); digitalWrite(led4,LOW); x=0; break; } }else{ digitalWrite(led1,LOW); digitalWrite(led2,LOW); digitalWrite(led3,LOW); digitalWrite(led4,LOW); } }
  6. Witam wszystkich. Jako, że na temat mojej pracy inżynierskiej wybrałem budowę manipulatora - plotera rysującego po powierzchni do której jest zamocowany, chciałbym prosić o kilka porad. Dodam też, że jestem w tym kompletnie zielony ale mam jeszcze około rok więc myślę, że się uda. Chciałbym żeby z wyglądu był zbliżony do KUKI. 1. Jako, że robot musi mieć funkcję plotera, w czym najlepiej to zaprogramować? (Kilka osób mi poleciło raspberry pi z pythonem). Będzie to nauka od postaw więc proszę o polecenie książek do nauki tego języka. 2. Jakie książki, dzięki którym będę wiedział jak budować danego robota, jaką elektronikę, jakie silniki itd. 3. Jeśli coś ważnego pominąłem to również proszę to napisać.
  7. Wstęp Jeśli sięgnąłeś po ten artykuł, to prawdopodobnie jesteś programistą, a co więcej, chcesz być lepszym programistą! To bardzo dobrze, ponieważ rynek IT potrzebuje lepszych programistów, a wytwarzanie czystego kodu według przyjętych standardów programowania jest zdecydowanym krokiem w tę stronę. Ten wpis brał udział konkursie na najlepszy artykuł o elektronice lub programowaniu. Sprawdź wyniki oraz listę wszystkich prac » Partnerem tej edycji konkursu (marzec 2020) był popularny producent obwodów drukowanych, firma PCBWay. Czym właściwie jest czysty i dobry kod? Na to pytanie nie ma jednoznacznej odpowiedzi. Istnieje jednak zbiór pewnych reguł i narzędzi, które skutecznie wspomogą pracę programisty, a stosowane w całym zespole, polepszą jego efektywność i skuteczność. Spis treści serii artykułów: Czysty kod w praktyce - część 1 Czysty kod w praktyce - część 2 Jak więc tworzyć oprogramowanie pozbawione błędów? Podstawową regułą jest stosowanie właściwie dobranych nazw opisujących zmienne, funkcje czy struktury – jeśli kwestia ta nie jest spełniona, to żadna konwencja nie zda egzaminu. Nazwa taka powinna być odpowiedzią na wszystkie ważne pytania – w jakim celu istnieje, co robi, jakiego jest typu i jak jest używana. Jeżeli nazwa zmiennej wymaga komentarza, to znaczy, że nie ilustruje swojej intencji (dobry kod jest samokomentujący!). Przedrostki określające typy zmiennych Przykładowe przedrostki określające typy zmiennych: diGripperOpen – cyfrowy sygnał wejściowy mówiący, że chwytak jest otwarty; doGripperOpen – cyfrowy sygnał wyjściowy mówiący, aby chwytak został otwarty; aiTemperatureSensor – analogowy sygnał wejściowy czujnika temperatury; giTemperatureSensor – grupowy sygnał wejściowy czujnika temperatury (cyfrowy sygnał zakodowany na przykład na 16 bitach); nIndex – zmienna typu int zawierająca dane licznikowe; rRadius – zmienna typu real zawierająca promień; bMP3Module_On – zmienna typu bool informująca o załączeniu modułu mp3; Nie bądźmy dowcipni (ale tylko w kodzie ;d) Jeżeli nazwy są dowcipnymi określeniami, mogą być zapamiętane wyłącznie przez osoby z identycznym co autor poczuciem humoru i tylko dopóki dane określenie nie wyjdzie z mody. Nazwa zmiennych i funkcji powinny odzwierciedlać ich znaczenie. Dowcipne hasła z najnowszego standupu Rafała Paczesia zostawmy na integrację po pracy. Jedno słowo na pojęcie Należy stosować zasadę jedno słowo na jedno abstrakcyjne pojęcie i trzymać się jej w całym swoim programie. Na przykład diHumiditySensor. Nie twórzmy zgadywanek! Należy unikać używania różnych określeń do jednego celu. Powoduje to brak jednoznaczności. Czujnik zmierzchu oprogramowany w kodzie musi mieć jedną nazwę – używanie zamiennej terminologii jak czujnik optyczny, czujnik zmierzchu czy czujnik zmierzchowy powodują tylko bałagan w kodzie. Jeśli w systemie, który programujemy mamy kilka czujników, dla ich rozróżnienia nazwijmy je zgodnie z ich rolą i lokalizacją – nie stosujmy na przykład: aiHumiditySensor, aiMoistureSensor, aiWetnessSensor a na przykład aiHumiditySensor_Room, aiHumiditySensor_Kitchen, aiHumiditySensor_Bathroom. Dodajmy znaczący kontekst Jeśli mamy grupę danych, możemy posłużyć się różnymi zabiegami (w zależności od możliwości języka w jakim programujemy), aby panował w nich ład i porządek, grupując np. dane adresowe jako addrFirstName, addrLastName, addrState i tak dalej. Dzięki temu inni programiści będą wiedzieli, że zmienne te są częścią większej grupy danych. Możemy również użyć struktury, klasy – wszystko w zależności od języka programowania. Stosujmy terminologię klienta Jeśli tylko to możliwe, to do nazewnictwa zmiennych stosujemy terminologie klienta – jeśli istnieją dwa lub więcej terminów klienta na jedno pojęcie, wybieramy jedno i konsekwentnie się do tego stosujemy. Na przykład jeśli programujemy system do zarządzania produkcją u klienta, który wytwarza pakiety baterii z ogniw, używajmy zmiennych nBatteryIndex, bBatteryPresent itd. Podsumujmy dobre nazwy w kodzie przedstawiają intencje; bez mylących i fałszywych wskazówek; bez zbyt subtelnych różnic; są spójne; można je wymówić; łatwo je wyszukać; nazwy zmiennych mają rzeczowniki; nazwy funkcji mają czasowniki; dowcipne nazwy mogą nie być zrozumiane; dodajemy znaczący kontekst; nazwy zmiennych, funkcji, podprogramów w języku angielskim; zmiana nazwy na czytelniejszą to nic złego. Stosujmy dobry, konsekwentny styl Jak zapewnić tę czytelność? Po pierwsze: nazwy - zmiennych, stałych, funkcji, klas, metod, struktur itd. Każda nazwa powinna być znacząca, chyba że ma marginalne znaczenie. Jednoliterowe nazwy mogą się nadawać do zmiennych tymczasowych, takich jak np. zmienne pętli, ale tylko i wyłącznie wtedy. Nazwy powinny odzwierciedlać zastosowanie – zmienna przechowująca indeks tablicy może nazywać się „index”, a funkcja dodająca do siebie dwie liczby – „add”. Trudno się nie zgodzić, że są to o wiele czytelniejsze nazwy niż np. „dupadupacycki” czy „qwert”. Jeśli chodzi o dokumentację i komentarze, to lepiej jest używać długich nazw zmiennych (o ile dany język programowania na to pozwala), procedur, programów i funkcji, które dobrze określają ich znaczenie, zamiast używać krótkich nazw i zaopatrywać ich długim komentarzem. Poza tym długie nazwy pomagają w przypomnieniu sobie działania programu jeśli zaglądamy do niego po długiej przerwie. Jaki sens mają szczegółowe komentarze? Nie powinno się pisać kodu wyłącznie czytelnego, bądź wyłącznie optymalnego. Kod powinien być zrównoważony i wypośrodkowany – na tyle zoptymalizowany na ile nie straci na czytelności. Argument czytelności można w ogóle pominąć dopiero wtedy gdy wydajność kodu jest niewystarczająca, jednak wtedy należy taki kod opatrzyć stosownym komentarzem. Komentarze – kiedy nie mają sensu? Niewiele jest rzeczy tak pomocnych, jak dobrze umieszczony komentarz. Jednocześnie nic tak nie zaciemnia modułu, jak kilka zbyt dogmatycznych komentarzy. Nic nie jest tak szkodliwe, jak stary komentarz szerzący kłamstwa i dezinformację. Komentarze nie są szminką dla złego kodu! Jednym z często spotykanych powodów pisania komentarzy jest nieudany kod. Napisaliśmy funkcję i zauważamy, że jest źle zorganizowana. Wiemy, że jest chaotyczny. Mówimy wówczas: „Hm, będzie lepiej, jak go skomentuję”. Nie! Lepiej go poprawić! Precyzyjny i czytelny kod z małą liczbą komentarzy jest o wiele lepszy niż zabałaganiony i złożony kod z mnóstwem komentarzy. Zamiast spędzać czas na pisaniu komentarza wyjaśniającego bałagan, jaki zrobiliśmy, warto poświęcić czas na posprzątanie tego bałaganu i poprawić nasz kod - czytelny kod nie wymaga komentarza. Komentarze – kiedy mają sens? W wielu przypadkach stosowanie komentarza jest jak najbardziej słuszne. Często musimy zastosować komentarz prawny z powodu korporacyjnych standardów klienta. Czasami przydatne jest umieszczenie w komentarzu podstawowych informacji – na przykład typu czy informacji o wartości zwracanej zmiennej i wtedy warto zawrzeć taką informację w komentarzu informacyjnym. Na etapie projektowania często praktyką są komentarze TODO jako notatki zagadnień, które pozostały jeszcze „do zrobienia”. Formatowanie kodu Pamiętajmy, że kod powinien być ładnie sformatowany. Należy wybrać zbiór prostych zasad, które rządzą formatowaniem kodu, a następnie w konsekwentny sposób je stosować. Jeżeli pracujemy w zespole kilku programistów, to wszyscy jego członkowie powinni przyjąć zbiór zasad formatowania i stosować się do nich. Bardzo dobrą praktyką jest stosowanie pionowych odstępów pomiędzy segmentami kodu oraz wcięć – do poszczególnych programów w pliku, do funkcji i bloków funkcji. Z naszego programu należy również usunąć cały martwy kod – to znaczy taki, który nigdy nie jest wykorzystany (na przykład kontrolują go nigdy niespełniane warunki) lub taki, który mógł służyć jedynie do testów. Zamiast stosować magiczne liczby, użyjmy stałych nazywanych – na przykład liczba 86 400 powinna być ukryta w stałej SECONDS_PER_DAY. Jeżeli wyświetlamy 70 wierszy na stronę, to liczba 70 powinna być ukryta w stałej LINES_PER_PAGE. Spis treści serii artykułów: Czysty kod w praktyce - część 1 Czysty kod w praktyce - część 2
  8. Reguła KISS, DRY oraz inne zasady dobrego programowania Reguła KISS (ang. Keep It Simple, Stupid), dosłownie zrób to prosto, idioto – Prostota (i unikanie złożoności) powinna być priorytetem podczas programowania. Kod powinien być łatwy do odczytania i zrozumienia wymagając do tego jak najmniej wysiłku. Większość systemów działa najlepiej, gdy polegają na prostocie, a nie na złożoności. Należy się więc starać, aby nasz kod podczas analizy nie zmuszał do zbytniego myślenia. Gdy po jakimś czasie do niego wrócimy i nie wiemy co tam się dzieje, to znak, że musimy nad tym popracować. Dobrą metodą jest również pisanie naszych programów raz jeszcze gdy już poznaliśmy dokładnie proces, wprowadziliśmy wszystkie zmiany jakie zgłosił nam klient w trakcie odbioru oraz po wyprowadzeniu wszystkich początkowych błędnych założeń w trakcie programowanie offline. Ten wpis brał udział konkursie na najlepszy artykuł o elektronice lub programowaniu. Sprawdź wyniki oraz listę wszystkich prac » Partnerem tej edycji konkursu (marzec 2020) był popularny producent obwodów drukowanych, firma PCBWay. Spis treści serii artykułów: Czysty kod w praktyce - część 1 Czysty kod w praktyce - część 2 DRY (ang. Don't Repeat Yourself, pol. Nie powtarzaj się) – reguła stosowana podczas wytwarzania oprogramowania, zalecająca unikanie różnego rodzaju powtórzeń wykonywanych przez programistów - na przykład unikanie tych samych czynności podczas kompilowania, unikanie wklejania (lub pisania) tych samych (lub bardzo podobnych) fragmentów kodu w wielu miejscach. Wielokrotne użycie tego samego kodu to podstawa programowania (Zmiana implementacji tylko w jednym miejscu oraz lepsza czytelność kodu oraz łatwość w utrzymaniu). Code for the Maintainer – czyli programuj tak jakbyś to robił dla osoby, która będzie później utrzymywać ten kod. Praca przy cudzym kawałku kodu to (przeważnie) najbardziej wymagająca i największa część pracy każdego programisty. Nie powinniśmy utrudniać sobie tego zadania. Zadbajmy więc o to, aby nie trzeba było się zbytnio głowić nad kawałkiem Twojego kodu. Pisz kod w taki sposób w jakim chciałbyś go otrzymać od kolego po fachu. Boy scout rule – zawsze pozostaw po sobie kod czystszy niż go zastałeś. REP - Reuse-release equivalence principle – ponowne użycie kodu to nie kopiowanie funkcji czy podprogramu z jednego projektu do drugiego. Jeżeli chcemy użyć ponownie kod, to należy go wydzielić do biblioteki, którą później możemy użyć ponownie. Klasy oraz funkcje, które są przeznaczone do ponownego wykorzystania, powinny być w jednej paczce, aby mogła stać się reużywalną biblioteką. Nie powinny się tam znaleźć te, które nie są przeznaczone do ponownego wykorzystania. W skrócie - albo wszystkie są reużywalne, albo żadne. Zdecydowanie ułatwi to edycje biblioteki oraz rozbudowę. Nie zawsze zasada KISS lub DRY jest słuszna! Weźmy np. zasadę DRY – Don’t Repeat Yourself – piszemy kod, który jest reużywalny, nie powtarzamy logiki zawartej w jednym miejscu w aplikacji, w innym. Tylko, że z tego rodzą się czasem klasy czy funkcje potwory. Okazuje się, że mają wiele rozglłęzień, skomplikowaną strukturę – tylko po to, żeby nie powtórzyć się w innym miejscu. I tu mamy problem – jest to świadome naginanie reguły KISS – Keep It Simple Stupid – która mówi o tym, żeby kod był tak prosty, jak to tylko możliwe. Wniosek nasuwa się jeden – nie istnieje srebrna kula. Nie istnieje też żaden złoty środek. Nie ma idealnego scenariusza, w którym weźmiemy garść złotych myśli (nasze reguły) i mamy gotowy przepis na sukces. Trzeba pamiętać o tym, żeby nie mieć klapek na oczach. Należy umiejętnie żonglować poszczególnymi zasadami, żeby osiągnąć satysfakcjonujący, końcowy rezultat. Zasady tylko wspomagają nas jako programistów, są narzędziem, które musimy umiejętnie wykorzystać. Zmiana osoby w projekcie a jakość kodu – jaki ma to wpływ na projekt i dochód? Wraz ze wzrostem bałaganu w oprogramowaniu niewątpliwie spada efektywność zespołu, co w znacznym stopniu paraliżuje projekt. Wobec spadku efektywności osoba odpowiedzialna za dany projekt zwykle dodaje do projektu więcej osób w nadziei, że podniesie to wydajność zespołu i uda się wyprowadzić problem tak, aby klient odebrał oprogramowanie. Jednak nowe osoby nie są zaznajomione z projektem oraz procesem jaki się tam odbywa, zasadą działania współpracujących ze sobą klas, czujników itd. Nie wiedzą, na jakie zmiany projektu mogą sobie pozwolić, a jakie spowodują jego naruszenie czy też zaprzestanie działania innych części kodu projektu. Dodatkowo, tak jak wszyscy pozostali w zespole, są pod ogromną presją zwiększenia wydajności swojej pracy, często w nadgodzinach czy dniach dla nich domyślnie wolnych. Należy tutaj pamiętać, że praca programisty to nie to samo, co człowieka na produkcji. Efektywność programisty to ok 6 godzin na dobę, ponieważ jest to praca umysłowa, wymagająca skupienia oraz kreatywnego myślenia. Należy mieć również na uwadze fakt, że to nie kierownictwo, ale programista jest fachowcem w programowaniu i zarządzaniu kodem i to programista musi umieć wywrzeć na swoich przełożonych świadomość jak ważny jest czysty kod. Nic nie ma tak głębokiego i w długim czasie degradującego wpływu na prowadzenie projektu, jak zły kod. Po pierwszym nieudanym projekcie spowodowanym złym kodem, lider projektu powinien wyciągnąć wnioski, aby zapobiec podobnym sytuacjom w przyszłości. Jednym z działań mającym zapobiegać bałaganowi w kodzie jest refaktoryzacja. Spowoduje to wprawdzie dodatkowe obłożenie czasowe (refaktoryzacja jest kosztowna czasowo, ale jest istotnym elementem zarządzania projektem informatycznym), które należy wziąć pod uwagę w trakcie ustalania harmonogramu projektu, ale zmniejsza prawdopodobieństwo pisania całego kodu od nowa. Podsumowanie Podsumowując, nie istnieje coś takiego, jak szablon dobrych zasad projektowania. Styl pisania kodu należy dostosować do projektu jaki jest tworzony, jego zagadnień czy problematyki – należy jednak być w tym bezwzględnie konsekwentnym. Jeśli będziemy w taki sposób pracować, efektywność naszej pracy będzie stale rosnąć. Jeśli czytelnik artykułu jest początkującym programistą, to stosując powyższe metody zoptymalizuje i uporządkuje swój kod, a co za tym idzie, jego projekty będą bardziej satysfakcjonujące i być może dzięki temu stanie się zawodowym programistą czego z całego serca życzę. Spis treści serii artykułów: Czysty kod w praktyce - część 1 Czysty kod w praktyce - część 2 Bibliografia: Martin R. - Czysty kod. Podręcznik dobrego programisty https://pl.wikipedia.org/ https://i1.wp.com/blog.knoldus.com/wp-content/uploads/2018/06/cleancode.png?fit=743%2C656&ssl=1 https://www.wykop.pl/cdn/c3201142/comment_kIUd4zw6h9I4Wt4s2yRz977DpSEBAUOv.jpg https://i.ytimg.com/vi/Fevz-Kb4bxc/maxresdefault.jpg https://cdn5.vectorstock.com/i/1000x1000/77/09/clean-code-vector-4247709.jpg https://www.perforce.com/sites/default/files/image/2019-09/image-blog-social-writing-clean-code_0.png https://3.bp.blogspot.com/-lcAjDyJMDzw/UpOnmQVcPyI/AAAAAAAALYQ/Zqf4yEU-z-s/s640/good_code.png https://1024kb.pl/wp-content/uploads/2018/08/var-1024x516.png https://res.cloudinary.com/teepublic/image/private/s--yz3dO1aO--/t_Resized Artwork/c_fit,g_north_west,h_954,w_954/co_ffffff,e_outline:48/co_ffffff,e_outline:inner_fill:48/co_ffffff,e_outline:48/co_ffffff,e_outline:inner_fill:48/co_bbbbbb,e_outline:3:1000/c_mpad,g_center,h_1260,w_1260/b_rgb:eeeeee/c_limit,f_jpg,h_630,q_90,w_630/v1536857572/production/designs/3150589_0.jpg https://ronjeffries.com/xprog/wp-content/uploads/Photo-Dec-07-1-45-14-PM.jpg https://i0.wp.com/image.slidesharecdn.com/cleancode-110520031623-phpapp02/95/clean-code-5-728.jpg?w=584&ssl=1 https://cloudogu.com/images/blog/2018/CleanCode_TheartofProgramming.jpg https://slideplayer.com/slide/12686823/76/images/6/What+is+clean+code+Clean+code+can+be+read%2C+and+enhanced+by+other+developers.+It+has+meaningful+names..jpg https://octoperf.com/img/blog/are-you-buying-quality-software/clean-code.png https://media.makeameme.org/created/clean-code-clean.jpg https://image.slidesharecdn.com/cleancode-vortrag-03-2009-pdf-121006112415-phpapp02/95/clean-code-pdf-version-5-728.jpg?cb=1349523162 https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/cde14740-68df-45f4-ab1f-e36ee4f16a47/cleancode-7.png
  9. Witam. Pierwszy raz programuje procesor AVR przy pomocy Arduino. Wszystko ustawione zgodnie z TYM tematem. Kod niezwykle prosty jak budowa cepa, bo to włącznik modelarski. Jedynie sprawdza czas trwania impulsu i na tej podstawie ustawia stany na wyjściach. Mikrokontroler to Attiny13. Pierwszy próg do którego oba wyjścia są wyłączone to 1100ms. Od tego progu wyjście "0" jest stanem wysokim a "1" jest wyłączone. Kolejny to 1700ms. Po jego przekroczeniu następuje zmiana i "0" jest stanem niskim a wyjście "1" stanem wysokim. Maksymalny czas trwania impulsu to 2500ms( takie czasy z odbiornika modelarskiego sprawdziłem). I tu koniec teorii. Podczas testów okazuję się, że czasy się rozjeżdżają. Pierwszy stopień wchodzi przy 980ms a drugi przy 1500 zamiast przy 1700ms. Niby się da to dostroić ale po co? Podczas wgrywania "bootloadera" do attiny13 kwarc ustawiony na 1,2MHz tak samo jak podczas programowania. Ktoś ma jakieś pomysły dlaczego tak się dzieje? Opis kodu "ODBIORNIK TURNIGY" to czasy impulsu w ms jakie nadaje nadajnik przy różnych ustawieniach drążka sterującego. /*******ODBIORNIK TURNIGY******************** //Wyłączony- 1985 //Pozycja środek- 1485 //Pozycja 2- 978 ********************************************/ /*************PROGRAMOWANIE****************** ATtiny13A leg 1 (reset) -> Arduino 10 ATtiny13A leg 5 (PB0 MOSI)-> Arduino 11 ATtiny13A leg 6 (PB1 MISO) -> Arduino 12 ATtiny13A leg 7 (PB2 SCK) -> Arduino 13 ATtiny13A leg 8 -> 5v ATtiny13A leg 4 -> Ground (GND) ********************************************/ //PB_2 -> ADC_1 noga 7 //PB_1 -> noga 6, tranzystor 1 //PB_0 -> noga 5, tranzystor 2 unsigned long liczba; //int signal = 0; void setup() { pinMode(2 , INPUT); //Wejscie sygnalu pinMode(1 , OUTPUT); // wyjscie na tranzystor 1 pinMode(0 , OUTPUT); // wyjscie na tranzystor 2 } void loop() { liczba = pulseIn(2 , HIGH, 25000); if (liczba > 1100) { if (liczba > 1700) { digitalWrite(1 , HIGH); digitalWrite(0 , LOW); } else { digitalWrite(1 , LOW); digitalWrite(0 , HIGH); } } else { digitalWrite(1 , LOW); digitalWrite(0 , LOW); } }
  10. Cześć mam problem z zaprogramowaniem analogowego czujnika płomieni Waveshare. Jest to czujnik z botlandu za 10.99zł. Buduje robota na konkurs RoboRave w kategorii fire fighting. Jeżeli znacie jakiś poradnik to o podanie linku czy nazwy. Z góry dziękuje.
  11. Witam Chciałbym napisać kod dzięki któremu gdy kliknę przycisk, na wyświetlaczu pokazuje licznik który liczy do 100%, a w tym samym czasie obraca się silnik krokowy. Niestety nie wiem jak to zrobić żeby w tym samy czasie wszytko to się działo. Jak próbowałem to zrobić, to najpierw wyświetlacz liczył do 100%, a potem kręcił się silnik. Pomocy!
  12. Wstęp Na wstępie opiszę krótko projekt: Będzie to prosty układ, projekt głównie opiera się na kodzie w Arduino IDE (zamiana tekstu na alfabet morse'a i zapalanie diody) oraz którkim kodzie w Python do komunikacji arduino z PC. Potrzebne rzeczy: Potrzebne elementy: Arduino Uno/Leonardo, Płytka stykowa, dioda LED, rezystor min. 230 Ohm (u mnie 330 Ohm), 2x przewód męsko-męski Układ jest bardzo prosty do zmontowania Program w Arduino IDE: //zmienne String aM[25] = { //Kod alfabetu: 1-kropka, 2-kreska, 0-koniec (dla kodów o ilości kropek i kresek mniejszej od 4, optymalizacja) //A B C D E "1200", "2111", "2121", "2110", "1000", //F G H I J "1121", "2210", "1111", "1100", "1222", //K L M N O "2120", "1211", "2200", "2100", "2220", //P Q R S T "1221", "2212", "1210", "1110", "2000", //U W X Y Z "1120", "1220", "2112", "2122", "2211" }; char alfabet[25] = { //Alfabet łaciński - index aM[] i alfabet[] jest taki sam dla każdego znaku "abcdefghijklmnopqrstuwxyz" }; char message[100]; //Wiadomość otrzymana z komputera String msgGet; //Zmienna pomocnicza int aM_Delay = 300; //Czas kropki, wg zasad alfabetu morse'a kresta to 3x kropka int ledPin = 13; //Pin diody void setup() { // put your setup code here, to run once: pinMode(ledPin, OUTPUT); //ustawienie pinu diody na OUTPUT } void loop() { delay(2500); //Opóźnienie między komendami, nie jest wymagane for(int x=0; x<100; x++) //Wyczyszczenie całej wiadomości message[x] = '0'; bool waiting = true; //Zmienna pomocnicza while(waiting) { if(Serial.available() > 0) //Jeśli otrzymano wiadomość { msgGet = Serial.readString(); //Odczytanie wiadomości if(msgGet.length() > 100) //jeśli wiadomości jest za długa, zignoruj iteracje pętli - oczekiwanie na kolejną wiadomość continue; for(int i=0; i < msgGet.length(); i++) //Zapisanie wiadomości ze zmiennej string do tablicy char - ułatwia nadanie wiadomości message[i] = msgGet.charAt(i); msgGet = '0'; //Wyczyszczenie otrzymanej wiadomości waiting = false; //Koniec pętli while } } for(int m=0; m < 100; m++) //Pętla dla każdego znaku wiadomości { for(int i=0; i<=25; i++) //Pętla dla każdego znaku alfabetu { if(message[m] == alfabet[i]) //znalezienie indeksu znaku wiadomości w alfabecie { for(int x=0; x < 4; x++) //Znak może mieć max 4 kropki lub kreski { if('2' == aM[i].charAt(x)) //Jeśli 2 (kreska) - zapala diodę na aM_Delay * 3 - aM_Delay to też odstęp między sygnałami { digitalWrite(ledPin, HIGH); delay(aM_Delay * 3); digitalWrite(ledPin, LOW); delay(aM_Delay); } else if('1' == aM[i].charAt(x)) //Jesli 1 (kropka) -;;- { digitalWrite(ledPin, HIGH); delay(aM_Delay); digitalWrite(ledPin, LOW); delay(aM_Delay); } else if('0' == aM[i].charAt(x)) //Jeśli 0 - zakończ pętlę (koniec znaku) { delay(aM_Delay); break; } } } } } } Myślę, że komentarze w kodzie pozwolą wszystkim zrozumieć, o co chodzi Program w Python: import serial #biblioteka do komunikacji port = input("Enter port: ") #zmienna z ustawionym przez użytkownika portem do komunikacji ser = serial.Serial(port, 9600) #zainicjowanie płytki na wybranym porcie myMessage = "" #zmienna do zapisu wiadomości while 1: #pobieranie wiadomości w nieskończoność, dopóki nie wyłaczymy programu myMessage = input("Enter a message: ") #zapisanie wiadomości w zmiennej ser.write(myMessage.encode('UTF-8')) #wysłanie wiadomości przez port, z kodowaniem UTF-8 Aby poprawnie wprowadzić nazwę portu, najłatwiej podłączyć arduino do komputera i w arduino IDE sprawdzić port, u mnie np. jeszt to COM5 (Arduino Leonardo) - wpisujemy więc COM5 A tak wygląda program w Pythonie po odpaleniu, jednak aby nie odpalać go za każdym razem z poziomu CMD, ułatwimy sobie zadanie kolejnym plikiem: run.bat w którym podajemy ścieżkę do pliku python (wraz z rozszerzeniem!) @echo off start G:\ArduinoProjects\MorseCodeNadajnik\MorseCode_Nadajnik.py Plik .bat nie jest wymagany, ale ułatwia odpalanie komunikacji Należy również pamiętać, że każdu port USB w komputerze to inny port w do wpisanie w Pythonie (wielu o tym zapomina) Mam nadzieję, że komuś to pomoże
  13. Posiadam kamerę Sony FCB-EV7520 (dokumentacja w załączniku), której wyjściem wideo jest sygnał w postaci YPbPr 4:2:2 wysyłany za pomocą interfejsu LVDS. To czego potrzebuje to napisanie programu na układ FPGA, który odbierze sygnał LVDS, przekształci go i wypuści sygnał zgodny ze standardem HDMI lub USB. Nie jest to coś nowego, bo tego typu urządzenia są w sprzedaży, lecz są drogie 350€ i mają już konkretny kształt, a w przyszłości chciałbym móc to zamknąć na swojej PCB. Jeżeli masz doświadczenie z FPGA, szczególnie z przetwarzaniem wyżej wymienionych sygnałów wideo to zapraszam do kontaktu. Jestem zainteresowany kompleksowym rozwiązaniem, ale również jestem otwarty na współpracę na zasadzie wskazania kierunku, zasugerowania możliwego rozwiązania i pomocy w wyborze odpowiedniego sprzętu. FCB-EV7520_Manual.pdf 22_FCB-EV7520A_S.pdf
  14. Witam, mam problem z wgraniem programu do Arduino. Po kliknięciu wgraj, wszystko się kompiluje, ale gdy rozpoczyna się wgrywanie, pasek postępu dochodzi do końca, a samo wgrywanie nie kończy się w ogóle, mogło by to trwać w nieskończoność (żadne błędy nie wyskakują). Gdy odłączę Arduino mogę dopiero zobaczyć błędy które wyskoczyły: avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x4a Nie jest to raczej związane z programem, bo na każdym wszystko dzieje się tak samo. Reinstall programu już robiłem. Proszę o pomoc i z góry dziękuję
  15. Witam. Chcialbym poprosic o pomoc w dokonczeniu kodu do mojego malego projektu. Mianowicie chcialbym zrobic szafke zamykana silnikiem krokowym sterowanym przez arduino. Do mojego projektu wykorzystalem mechanizm osi Z z mojej starej drukarki 3D wraz z silnikiem i stepstickiem, ktory ma byc sterowany za pomoca arduino Nano. Po wcisnieciu przelacznika (takiego od swiatla w pokoju) w pozycji gornej na pin 13 w arduino zostaje podany stan wysoki co prowadzi do obracania sie silnika w prawo i tym samym uniesienie klapy od szafki. Zas wylacznik w pozycji dolnej podaje stan niski na pin 13 co sprawia, ze silnik sie kreci w lewo i zamyka klape. Tyle udalo mi sie zrobic. Schody zaczely sie gdy musze dodac przelaczniki typu endstop aby arduino wiedzialo kiedy ma zatrzymac silnik, poniewaz w tej chwili pracuje nieustannie albo w jedna albo w druga strone. Nie mam pojecia co nalezy dopisac lub co zmienic w istniejacym kodzie aby to dzialalo jak nalezy. Z gory dziekuje za pomoc. Oto moj kod : // Sterownik silnika krokowego do zamykania szafki // Arduino nano + silnik nema ze stepstickiem int Index; const int buttonPin = 13; // Przelacznik bistabilny int buttonState = 0; // Status przelacznika void setup() { pinMode(8, OUTPUT); //Enable pinMode(2, OUTPUT); //Step pinMode(5, OUTPUT); //Direction pinMode(buttonPin, INPUT); //Wylacznik digitalWrite(8,LOW); } void loop() { // Odczyt stanu przelacznika: buttonState = digitalRead(buttonPin); // Jesli przelacznik jest w pozycji gornej -5V- to stan wynosi HIGH - Obrot silnika w prawo: if (buttonState == HIGH) digitalWrite(5,HIGH); for(Index = 0; Index < 200; Index++) { digitalWrite(2,HIGH); delayMicroseconds(500); digitalWrite(2,LOW); delayMicroseconds(500); } // Odczyt stanu przelacznika: buttonState = digitalRead(buttonPin); // Jezeli przelacznik jest w pozycji dolnej -GND- to stan wynosi LOW - Obrot silnika w lewo: if (buttonState == LOW) digitalWrite(5,LOW); for(Index = 0; Index < 2000; Index++) { digitalWrite(2,HIGH); delayMicroseconds(500); digitalWrite(2,LOW); delayMicroseconds(500); } }
  16. Witam, właśnie przerobiłem sobie II część mini kursu Qt i mam pytanie na które na razie nie mogę samodzielnie znaleźć odpowiedzi. W jaki sposób zrobić sterowanie w odwrotnym kierunku? Mam napisany stoper w Qt i chciałbym np. go włączać i wyłączać przy pomocy przycisków podłączonych do Arduino.
  17. Cześć! Na początek powiem, że nie wiem czy wybrałem odpowiedni dział, za co przepraszam. Do rzeczy: napisałem sterownik pod pasek led WS2811 (KLIK). Potrzebowałem by raspberry podłączone do paska led i przekaźnika mogło włączać lub wyłączać pasek oraz zapalać na wybrany kolor za pomocą requestów http. Można też otrzymać stan czy pasek jest włączony i jaki kolor mamy zapalony. Jeśli ktoś by chciał użyć wystarczy uzupełnić w kodzie parametry opisane w README. Działa też pluginem dla pasków led z homebridge. Wszelki feedback, nawet ten negatywny - mile widziany https://github.com/damianchoc/led_api
  18. Witam mam problem z kompilacją gdyż wyskakuje mi taki błąd i nie wiem czemu tak się dzieje. Pomoże ktoś ? #include <Ultrasonic.h> // definicje dla HCSR04 #define TRIGGER_PIN 7 #define ECHO_PIN 4 Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); // silnik lewy const int kierunekLewy=12; const int hamulecLewy=9; const int predkoscLewy=3; //silnik prawy const int kierunekPrawy=13; const int hamulecPrawy=8; const int predkoscPrawy=11; //ustawienia void setup() { Serial.begin(9600); pinMode(kierunekLewy,OUTPUT); pinMode(kierunekPrawy,OUTPUT); pinMode(hamulecLewy,OUTPUT); pinMode(hamulecPrawy,OUTPUT); pinMode(predkoscLewy,OUTPUT); pinMode(predkoscPrawy,OUTPUT); } //petla glowna programu void loop() { float cmMsec; long microsec = ultrasonic.timing(); cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); doPrzodu(); delay(50); if (cmMsec<=30) { doTylu(); delay(500); } } void doPrzodu() { analogWrite(predkoscLewy,100); analogWrite(predkoscPrawy,105); //Lewy do przodu digitalWrite(kierunekLewy,HIGH); digitalWrite(hamulecLewy,LOW); //Prawy do przodu digitalWrite(kierunekPrawy,HIGH); digitalWrite(hamulecPrawy,LOW); } void doTylu() { analogWrite(predkoscLewy,200); analogWrite(predkoscPrawy,0); //Lewy do przodu digitalWrite(kierunekLewy,LOW); digitalWrite(hamulecLewy,LOW); //Prawy stop digitalWrite(kierunekPrawy,HIGH); digitalWrite(hamulecPrawy,HIGH); }
  19. Niby to nie moja sprawa - w sumie to nie ja rozdaję kupony, ale czy w tym wpisie jest cokolwiek nie skopiowane ze strony: https://jm.iq.pl/mini-os-emulator-dla-digisparka/ ? Pytam, bo wydaje mi się trochę nie fair, że za takie kopiuj-wklej można dostać to samo, na co inni jednak muszą trochę wysiłku włożyć. Z drugiej strony zainteresował mnie ten DigiOS - ale jedyny kod jaki widzę to https://github.com/jaromaz/DigiOS/blob/master/DigiOS.ino Stąd pytanie - gdzie jest kod systemu?
  20. Sketch DigiOS - mini OS emulator pozwala na zalogowanie się do Digisparka, wykonanie kilku komend, a następnie wylogowanie się. Działa na domyślnym Digisparku z zainstalowanym bootloaderem micronucleus oraz wykorzystuje moduł DigiCDC do emulacji komunikacji po USB, ponieważ sam Digispark nie posiada żadnego dodatkowego czipu USB i wszystko jest realizowane w oprogramowaniu AtTiny85. Emulator tylko naśladuje działanie systemu. Nie aspiruje do bycia czymś więcej, a już na pewno nie systemem operacyjnym to prosty kod wykonujący kilka poleceń, ale jego efekt końcowy jest dość użyteczny, co można ocenić na poniższym filmie: Przy zasilaniu Digisparka poprzez pin VIN można w dowolnym momencie podłączyć się do niego przez USB, a po wykonaniu komend odłączyć terminal i urządzenie - Digispark będzie dalej wykonywał kod uwzględniając wysłane komendy. W filmiku użyłem zamówionych w Botlandzie 10-cio centymetrowych przewodów połączeniowych żeńsko-żeńskich oraz żeńsko-męskich. Reszta sprzętu pochodzi z innych źródeł Dostępne komendy: p[0–2] [on|off] - wysyła sygnały HIGH i LOW na poszczególne piny od (0 do 2) uptime - wyświetla czas od uruchomienia Digisparka w linuxowym formacie uptime pretty vcc - podaje napięcie zasilania Digisparka w miliwoltach reboot - software’owo restartuje Digisparka clear - czyści ekran ls - wyświetla listę statusów GPIO temp - podaje temperaturę chipu login - wyświetla monit o podanie hasła clock [1–7] - zmniejsza taktowanie zegara (oszczędność energii). wartości: 1 – 8mHz, 2 – 4mHz, 3 – 2mHz, 4 – 1mHz, 5 – 500kHz, 6 – 250kHz, 7 – 125kHz, 0 – 16,5 mHz help - wyświetla ekran pomocy logout, exit - wylogowuje użytkownika Sketch z założenia miał zajmować jak najmniej miejsca – zamiast stringów wykorzystałem tablice znakowe, zamiast pinMode/digitalWrite rejestry i operacje bitowe, dzięki czemu udało się upchnąć tak dużo funkcji na tak małym urządzeniu. Wszystkie trzy elementy składowe zajmują razem blisko 100% pamięci Digisparka, aby jednak zwiększyć ilość dostępnego miejsca na własny kod, wystarczy usunąć odwołanie do zbędnych funkcji (np. temp, uptime, vcc). Odwołania te są oznaczone w kodzie specjalnym blokiem – po ich usunięciu udostępnione zostanie ponad 30% pamięci (z wyłączeniem bootloadera). Można wtedy łatwo rozbudować sketch o własne rozwiązania - staje się wtedy szablonem na pomysły użytkownika Dla Digisparka brak jest przykładów wieloznakowej, obustronnej komunikacji w połączeniu z DigiCDC. Jest dostępne jednoznakowe echo i zwykłe wyświetlanie informacji, ale też nie do końca poprawnie działają, szczególnie w najnowszych systemach. Musiałem przegrzebać się przez sieć i zastosować kilka własnych rozwiązań, żeby wszystko działało tak, jak w filmie. Tu właśnie moduł DigiCDC jest kluczowy i to co dla Arduino jest oczywiste, w Digisparku z DigiCDC wymagało trochę zachodu Umieszczone w kodzie delay'e są niezbędne bezpłatnej apce na Androida Serial USB Terminal, która jako jedyna obsługuje Digisparka w tym systemie. Bez nich apka źle łamie wyświetlany tekst. W kodzie jest też info, że można usunąć te delay'e, jeżeli do łączenia z Digisparkiem wykorzystuje się inny system operacyjny. Poważnym ograniczeniem biblioteki DigiCDC jest wymuszenie maksymalnie do siedmiu liczby znaków wpisywanej frazy. Przekroczenie tej liczby znaków w ciągu zawiesza komunikację. Definiowane hasło pozwala na wykonanie pewnych operacji z minimalnym poziomem autoryzacji. Minimalnym, bo zakładam, że łatwo jest je wyciągnąć bezpośrednio z Digisparka, ale może się mylę. Polecenie ls listuje stany LOW/HIGH wszystkich dostępnych GPIO w formie małej tabelki. Sprawdzane są bity - jeżeli wcześniej był ustawiony stan wysoki, to nawet po software'owym restarcie urządzenia polecenie to będzie uwzględniało wcześniejszą zmianę w wyświetlanym statusie. Zmiana taktowania wyłączy możliwość komunikacji po USB – można podpiąć pod tę zmianę wykonanie pewnych poleceń kończące się odwołaniem do funkcji reboot, wtedy Digispark się zrestartuje z domyślnymi ustawieniami zegara i automatycznie ponownie będzie możliwe logowanie do urządzenia. Chciałem nieco rozpropagować Digisparka, dlatego zależało mi na takiej uproszczonej formie: sketch + micronucleus + DigiCDC. DigiOS to szybka kompilacja w Arduino IDE, bezproblemowy upload do Digisparka przez Arduino IDE dzięki bootloaderowi micronucleus ... i gotowe Do uploadowania sketcha do Digisparka wymagane jest Arduino IDE w wersji 1.8.6 oraz poprawna instalacja Digisparka w IDE zgodnie z tą instrukcją. Do DigiOS można zalogować się pod Windows programem Putty (po wcześniejszej instalacji sterowników Digistump), w Linuxie aplikacją Minicom, a w Androidzie wspomnianą aplikacją Serial USB Terminal. Kod udostępniam poniżej, a jego zmiany można śledzić na stronie projektu w GitHubie - jest tam również dostępna wersja DigiLx z oknem logowania i znakiem zachęty w stylu linuksowym. /* ---------------------------------------------- DigiOS 1.4 - mini-OS emulator for Digispark Copyright (c) Jaromaz https://jm.iq.pl Available commands: login, p[0-2] [on|off], temp, help, vcc, clear, uptime, clock [1-7], ls, reboot, logout, exit ----------------------------------------------- */ // password of up to seven characters const char password[] = "admin12"; //----------------------------------------------- #include <DigiCDC.h> char serialChar[1], stringInput[8]; boolean stringComplete = false; byte state = 1; byte clocks[] = { 16, 8, 4, 2, 1, 500, 250, 125 }; static void reboot() //----------------------------------------------- { SerialUSB.print(F("\r\nRebooting ... ")); noInterrupts(); CLKPR = 0b10000000; CLKPR = 0; void (*ptrToFunction)(); ptrToFunction = 0x0000; (*ptrToFunction)(); } static void clockMessageFormat (byte speed) //----------------------------------------------- { SerialUSB.print(F("\r\nset to ")); SerialUSB.print(clocks[speed], DEC); SerialUSB.print((clocks[speed] > 16) ? F("k") : F("m")); SerialUSB.println(F("Hz\r\n\r\nbye ...")); } static void clockSpeed(byte speed) //----------------------------------------------- // edit the code of this procedure to get the right result { clockMessageFormat(speed); for (byte i = 0; i < 12; i++) { PORTB |= (1 << 1); SerialUSB.delay(200); PORTB &= ~(1 << 1); SerialUSB.delay(200); if (i == 5) { CLKPR = 0b10000000; CLKPR = speed; } } reboot(); } static void stateChg() { state = 2; } //----------------------------------------------- #define SECS_PER_MIN (60UL) #define SECS_PER_HOUR (3600UL) #define SECS_PER_DAY (SECS_PER_HOUR * 24L) #define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) #define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) #define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) #define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) void uptimeFormat(byte digits, char* form) //----------------------------------------------- { if (digits > 0) { SerialUSB.print(digits, DEC); SerialUSB.print(F(" ")); SerialUSB.print(form); if (digits > 1) SerialUSB.print(F("s")); if (strcmp(form, "second")) { SerialUSB.print(F(", ")); } } } static void uptime() //----------------------------------------------- { long seconds = millis() / 1000; SerialUSB.print(F("\r\nup ")); uptimeFormat(elapsedDays(seconds), "day"); uptimeFormat(numberOfHours(seconds), "hour"); uptimeFormat(numberOfMinutes(seconds), "minute"); uptimeFormat(numberOfSeconds(seconds), "second"); SerialUSB.println(); } static void getVcc() //----------------------------------------------- { ADMUX = _BV(MUX3) | _BV(MUX2); SerialUSB.delay(2); ADCSRA |= _BV(ADSC); while (bit_is_set(ADCSRA, ADSC)); uint8_t low = ADCL; uint8_t high = ADCH; long result = (high << 8) | low; result = 1125300L / result; SerialUSB.print(F("\r\nVoltage: ")); SerialUSB.print(result); SerialUSB.println(F(" mV")); } static void getTemp() //----------------------------------------------- { analogReference(INTERNAL1V1); analogRead(A0); SerialUSB.delay(200); int temp = analogRead(A0 + 15) - 273; analogReference(DEFAULT); SerialUSB.print(F("\r\nDigispark temperature: ")); SerialUSB.print(temp); SerialUSB.println(F("°C")); } void clearScreen() //----------------------------------------------- { for (byte i = 0; i < 35; i++) { SerialUSB.println(); SerialUSB.delay(5); } } static void horizontaLine() //----------------------------------------------- { for (byte i = 0; i < 32; i++) SerialUSB.print(F("-")); } static void gpioList() //----------------------------------------------- { horizontaLine(); SerialUSB.print(F("\r\nGPIO status list\r\n")); horizontaLine(); for (byte i = 0; i < 3; i++) { SerialUSB.print(F("\r\nPin ")); SerialUSB.print(i, DEC); SerialUSB.print((PINB & (1 << i)) ? F(" HIGH") : F(" LOW")); } SerialUSB.println(); horizontaLine(); } static void help() //----------------------------------------------- { horizontaLine(); SerialUSB.println(F("\r\nDigiOS version 1.4 User Commands")); horizontaLine(); SerialUSB.println(F("\r\nlogin, p[0-2] [on|off], temp, help,\ vcc, clear,\r\nuptime, clock [1-7], ls, reboot, logout,\ exit\r\n\r\nclock 1 - 8mHz, 2 - 4mHz, 3 - 2mHz, 4 - 1mHz,\ \r\n5 - 500kHz, 6 - 250kHz, 7 - 125kHz")); } static void serialReader() //----------------------------------------------- { while (SerialUSB.available()) { serialChar[0] = (char)SerialUSB.read(); if ((' ' <= serialChar[0]) && (serialChar[0] <= '~')) { strcat(stringInput, serialChar); } else { if (stringInput[0] != 0) { stringComplete = true; return; } } } } void setup() //----------------------------------------------- { // Set pins 0-2 as OUTPUT: DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2); SerialUSB.begin(); } // list of keywords and procedures assigned to them static const struct { const char phrase[8]; void (*handler)(void); } keys[] = { // ---- comment on this block to get more memory for your own code --- { "vcc", getVcc }, { "help", help }, { "temp", getTemp }, { "reboot", reboot }, { "exit", stateChg }, { "uptime", uptime }, { "clear", clearScreen }, { "ls", gpioList }, // ------------------------------------------------------------------- { "logout", stateChg } }; void loop() //----------------------------------------------- { // the Android Serial USB Terminal app requires the following 200 ms delays // if you are using another system, you can remove all these delays. serialReader(); if (stringComplete) { SerialUSB.delay(200); if (!strcmp(stringInput, "login")) stateChg(); // password validation if (state == 4) { if (!strcmp(stringInput, password)) { state = 3; } else { SerialUSB.delay(1500); SerialUSB.println(F("\r\nLogin incorrect")); state = 1; } } // status after logging in if (state == 3) { // ---- comment on this block to get more memory for your own code --- if (stringInput[0] == 'p') { if ((stringInput[1] - 48) < 3 and stringInput[4] == 'n') { PORTB |= (1 << stringInput[1] - 48); } else if ((stringInput[1] - 48) < 3 and stringInput[4] == 'f') { PORTB &= ~(1 << stringInput[1] - 48); } } if (strstr(stringInput, "clock ")) clockSpeed(stringInput[6] - 48); // --------------------------------------------------------------------- // keyword procedures for (byte i = 0; i < sizeof keys / sizeof * keys; i++) { if (!strcmp(stringInput, keys[i].phrase)) keys[i].handler(); } if (state == 3) SerialUSB.print(F("\r\ncmd:> ")); } // password input window if (state < 3) { if (state > 1) clearScreen(); SerialUSB.print(F("\r\nDigiOS 1.4 - Digispark mini-OS\r\n\r\nPassword: ")); state = 4; } SerialUSB.delay(200); stringInput[0] = 0; stringComplete = false; } }
  21. Witam panowie wgrałem prosty program przykładowy blik do mikrokontrolera Arduino Uno. Teraz chciałbym aby ten program działał bez płytki arduino na płytce prototypowej. Na stronie arduino znalazłem poradnik jak to zrobić zrobiłem wszystko według instrukcji i nie działa program. Na pinie jest zaledwie 0,5V gdzie napięcie powinno raz mieć 5V a po 1sec 0V(bo taki program jest wgrany). Nie wiem co jest nie tak wszystko powinno byc dobrze zmontowane wklejam zdjęcia układu i proszę o pomoc.
×
×
  • Utwórz nowe...