ethanak Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 Wyrażenie opinii to nie to samo co "ja mam focha i nie będę sprawdzać o co chodzi" Cytuj Link do komentarza Share on other sites More sharing options...
FlyingDutch Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 3 minuty temu, _LM_ napisał: To że dyskusja jest taka żywa świadczy o tym że taka biblioteka jest potrzebna. Być może już na tym etapie przydałoby się zbudować coś co można zaprezentować tak aby każdy mógł wyrazić swoją opinię i wskazać miejsca gdzie należy coś poprawić. To może jasno sprecyzujcie założenia: jaką funkcjonalność ta biblioteka ma zapewniać. Nie można programować w C++ (chociaż każdy program tworzony w "Arduino IDE" jest tak naprawdę napisany w C++ i jako taki kompilowany) z nieznanego powodu. OOP i C++ zapewnia dużo większą warstwę abstrakcji niż C i uważam, że projekt biblioteki powinien być napisany z użyciem OOP. Jeśli powodem wyboru C jest nieznajomość C++ to polecam te tutoriale: https://www.youtube.com/watch?v=wN0x9eZLix4 https://www.youtube.com/watch?v=GQp1zzTwrIg Po drugie projekt ma być także na małe AVR'y (np. Arduino Uno), które mają bardzo mało zasobów (ATMega328: 2KB RAM i 32 Flash). Z tego powodu nie powinna zawierać za dużej ilości specjalizowanego kodu,aa w zamian powinna być łatwo rozszerzalna o nowe opcje i hardware. Wymaga to bardzo dobrego zaimplementowania szkieletu biblioteki - według mnie jako zestawu klas abstrakcyjnych . Po drugie już w drugim poście tego wątku była mowa o C++ (*.cpp) i nikt wtedy nie protestował. Pozdrawiam Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 (edytowany) @FlyingDutch Zawsze można napisać obiektowo w C, używanie C++ wcale nie jest do tego niezbędne 🙂 Masz rację, że konieczne jest zebranie założeń, a później wybranie rozwiązania, nie odwrotnie. Inaczej nic z tego nie wyjdzie - chociaż jeśli mam być szczery, to uważam że właśnie tak się ten projekt skończy. Edytowano Grudzień 27, 2021 przez Elvis 2 Cytuj Link do komentarza Share on other sites More sharing options...
FlyingDutch Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 22 minuty temu, _LM_ napisał: To że dyskusja jest taka żywa świadczy o tym że taka biblioteka jest potrzebna. Być może już na tym etapie przydałoby się zbudować coś co można zaprezentować tak aby każdy mógł wyrazić swoją opinię i wskazać miejsca gdzie należy coś poprawić. Według mnie jest wręcz przeciwnie: taka biblioteka nie jest nikomu potrzebna. Gdyby była potrzebna to takie firmy jak "Seed Studio", czy "SparkFun" już dawno by ją napisały (jak wiele innych bardzo przydatnych bibliotek do Arduino). Dlaczego to nie ma sensu: ponieważ, aby biblioteka była tak uniwersalna jak w to zakładacie wyjdzie za duża dla np. Arduino Uno, czy Nano. Według mnie lepiej za pomocą OPP tak zaprojektować główny szkielet, aby korzystając z dziedziczenia można ją było łatwo rozszerzać o wymagane funkcje. Pozdrawiam 1 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
pmochocki Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 19 minut temu, FlyingDutch napisał: Po drugie już w drugim poście tego wątku była mowa o C++ (*.cpp) i nikt wtedy nie protestował. A co było w trzecim poście? 20 minut temu, FlyingDutch napisał: OOP i C++ zapewnia dużo większą warstwę abstrakcji niż C i uważam, że projekt biblioteki powinien być napisany z użyciem OOP. Jeśli powodem wyboru C jest nieznajomość C++ to polecam te tutoriale To prawda C++ daje ogromne możliwości ale, raczej należy podejść do tego języka z pokorą: Bjarne Stroustrup: "C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, you blow your whole leg off." Anonim z poczuciem humoru: "If C gives you enough rope to hang yourself, C++ gives you enough rope to bind and gag your neighborhood, rig the sails on a small ship, and still have enough rope left over to hang yourself from the yardarm." Z drugiej strony może to być C jak i może być C++. Tak jak napisał @Elvis. 26 minut temu, Elvis napisał: @FlyingDutch Zawsze można napisać obiektowo w C, używanie C++ wcale nie jest do tego niezbędne Zgadzam się natomiast, że założenie, aby chodziło to na AVRach jest ambitne. 21 minut temu, FlyingDutch napisał: Gdyby była potrzebna to takie firmy jak "Seed Studio", czy "SparkFun" już dawno by ją napisały A to nie jest czasem tak, że oni piszą coś pod konkretny sprzęt, żeby to łatwiej sprzedać... Tu założenie jednak jest inne, bo właśnie ma być bardziej abstrakcyjne... 28 minut temu, Elvis napisał: Inaczej nic z tego nie wyjdzie - chociaż jeśli mam być szczery, to uważam że właśnie tak się ten projekt skończy A ja tam trzymam kciuki za kolegę. Cytuj Link do komentarza Share on other sites More sharing options...
FlyingDutch Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 21 minut temu, pmochocki napisał: A to nie jest czasem tak, że oni piszą coś pod konkretny sprzęt, żeby to łatwiej sprzedać... Tu założenie jednak jest inne, bo właśnie ma być bardziej abstrakcyjne... jak by była potrzebna taka biblioteka to dodawaliby ją do wyświetlaczy LCD 😁 Cytat To prawda C++ daje ogromne możliwości ale, raczej należy podejść do tego języka z pokorą: Cyli co ? Nie używać? To dlaczego core (dla board Arduino) - najważniejsze biblioteki są napisane w C++ (z wykorzystaniem OOP). Nie wiem, używam C++ od ponad dwudziestu lat (zarówno na dużych stacjach roboczych - jak np. świętej pamięci SUN i CPU Ultra-SPARC, jak i na mikro-kontrolerach AVR) i nie wiem o jakie pokorze mówisz. Jeśli się wie co się robi to da się używać C++ nawet na małych mikro-kontrolerach. BTW: życzę jak najszybszego określenia zakresu funkcjonalności wspomnianej biblioteki (i reszty założeń), tak aby dyskusja w tym wątku zaczęła być merytoryczna. Pozdrawiam 1 Cytuj Link do komentarza Share on other sites More sharing options...
pmochocki Grudzień 27, 2021 Udostępnij Grudzień 27, 2021 2 minuty temu, FlyingDutch napisał: Cyli co ? Nie używać? To dlaczego core (dla board Arduino) - najważniejsze biblioteki są napisane w C++ (z wykorzystaniem OOP). Nie wiem, używam C++ od ponad dwudziestu lat (zarówno na dużych stacjach roboczych - jak np. świętej pamięci SUN i CPU Ultra-SPARC, jak i na mikro-kontrolerach AVR) i nie wiem o jakie pokorze mówisz. Jeśli się wie co się robi to da się używać C++ nawet na małych mikro-kontrolerach. Jak najbardziej używać. Raczej nie używałbym w ważnym projekcie po dwóch tutorialach na YT. Może źle zrozumiałem Twój wpis, ale brzmiało to jak: nie znasz C++ to żaden problem - oglądasz tutoriala i kodujesz. Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Grudzień 29, 2021 Autor tematu Udostępnij Grudzień 29, 2021 Pytanie techniczne: powołując nowy typ danych, opisany wewnątrz struktury a zawierający elementy o różnych rozmiarach, np: typedef struct{ char a; char * ptr}new_t; To czy zawsze muszę robić dopełnienia do pełnego rozmiaru? Czyli w tym przypadku, zależnie od architektury wskaznik ptr może mieć rożny rozmiar. Cytuj Link do komentarza Share on other sites More sharing options...
FlyingDutch Grudzień 30, 2021 Udostępnij Grudzień 30, 2021 10 godzin temu, _LM_ napisał: Pytanie techniczne: powołując nowy typ danych, opisany wewnątrz struktury a zawierający elementy o różnych rozmiarach, np: typedef struct{ char a; char * ptr}new_t; To czy zawsze muszę robić dopełnienia do pełnego rozmiaru? Czyli w tym przypadku, zależnie od architektury wskaznik ptr może mieć rożny rozmiar. Wskaźnik wskaźnikiem, ale długość danych na które on wskazuje może być różna. Możesz użyć funkcji malloc(długość_składnika+1) do przydziału pamięci na składową struktury, lub zamiast char* ptr zastosować tablice char o określonej długości np.: char skladowa[33]; Pozdrawiam 1 Cytuj Link do komentarza Share on other sites More sharing options...
_LM_ Marzec 25, 2022 Autor tematu Udostępnij Marzec 25, 2022 (edytowany) Trochę ucichło w temacie ale to nie oznacza że nie pracowałem nad projektem 😉 tj w miarę moich skromnych możliwości w ramach wolnego czasu. A więc postanowiłem zbudować szkielet tej biblioteki w oparciu o drzewa struktur odwołujących się do siebie, oraz wstępną funkcją umożliwiającą poruszanie się po menu. Funkcja główna nie zwraca jednak wskaźnika bezpośredniego(na siebie) ale indeks w tablicy na którym miejscu się znajduje. Zrobiłem tak, ponieważ używanie indeksów zamiast wskaźników bezpośrednich według mnie ułatwia późniejsze dodawanie akcji w zależności od wybranej pozycji - mam tu na myśli wejście w daną pozycję, zasadniczą są dwie akcje: wyświetlenie bieżącego stanu menu lub obsługa funkcji powiązanej z zadaną pozycją. Główny "silnik" menu zwraca kilka możliwych komunikatów które umieściłem w enumie i są to: typedef enum{ _ok = 0, // mozna przejsc do nast pozycji _isNull, // pozycja pusta -> mozliwe wywolanie f _isRunf, // jesli f uruchomiona _isEndf, // funkcja zakonczyla dzialanie, wroc do menu _err // blad - zle poelcenie }_menu_stat_t; A więc w tej chwili prezentuje się to tak, oto główna funkcja umożliwiająca poruszanie się po menu _menu_stat_t menu_navigator(menu_t ** p, node_t *nodTab, uint8_t * id,uint8_t * node, _menuNavi_t navi) { if (navi >= __naviEnd) { // gdy polecenie nieznane return _err; } static nodeType_t localNode = 0; if (NULL != (*p)->menuNav[navi]) { // spr czy po nie pusta *p = (menu_t*) (*p)->menuNav[navi]; // nowa wartosc wskaznika *id = (*p)->id; // nowe ID if ((navi == _parent) || (navi == _child)) {// obliczanie nowej wartosci wezla for (uint8_t i = 0; i < MAXNODE; i++) { if ((*p)->menuNav[_parent] == nodTab[i].ptrNode) { localNode = nodTab[i].nodeID; // jesli znaleziono *node = localNode; // zapamietaj wezel break; } } } return _ok; } return _isNull; } Oczywiście analiza tego kodu bez znajomości struktury której on dotyczy nie miałaby sensu, więc typedef struct menu{ const struct menu * menuNav[__naviEnd]; const idType_t id;//,node; }menu_t; typedef struct{ const menu_t * ptrNode; const nodeType_t nodeID; }node_t; teraz funkcja obsługująca menu void MENUEVENT(void) { // event po kazdej zmianie stanu menu //static uint8_t refresh = 0; if (menuSet) { if(menu_Event == display)runCmd(cmd); if(menu_Event == runFunct)runFun(cmd); cmd = cmdEnd; menuSet = 0; } } i funckje pomocnicze, najpewniej później będą statyczne void fnInput(cmd_t cmdIn) { menuSet = 1; cmd = cmdIn; } void runCmd(cmd_t cmd) { menuVisible = 1; //info dla prog glownego ze menu powinno byc wyswietlone static menu_t * ptrMenu = (menu_t*)start; _menu_stat_t stat = menu_navigator(&ptrMenu, (node_t*)&nodeTab, &id, &node,cmd); if(node >= MAXNODE)node = 0; if(0 == id && ptrMenu == start){ // nie koniecznie do poprawy menuVisible = 0; ptrMenu = (menu_t*)start; node = 0; return; } if (_ok == stat)menu_execute(id,node,menu.outStream); if (_isNull == stat){ // menu_Event = runFunct;//wykonanie funkcji //!!!!!!!!!! zmiana tylko na czas debugu!!!!!! menuVisible = 0; ptrMenu = (menu_t*)start; node = 0; //!!!!!!!!!!! } } void runFun(cmd_t cmd){ // wywolanie funkcji wykonawczej, od teraz menuEvent wskakuje tutaj _menu_stat_t stat = menu_run_fnc(id, node, cmd); if((stat == _isNull) ||(stat == _isEndf)){ menu_Event = display; // przelaczenie na wyswietlanie menu_execute(id,node,menu.outStream); // odswierzenie menu } } _menu_stat_t menu_execute(idType_t id,nodeType_t node, void * streamPtr){ lcd_t * p = streamPtr; p->flocate(0,0); p->fstr("N:"); p->fint(node); //p->fstr((char*)menustrtab[node].nazwa); //p->fstr(" "); p->fstr(" ID:"); p->fint(id); //p->flocate(1,0); //p->fstr((char*)menustrtab[node].pozycje[id]); //p->fstr(" "); return _ok; } Jak widać "menu_execute" nie operuje bezpośrednio na wyświetlaczu, czy innym medium ale przyjmuje wskaźniki na strumień wyjściowy, czyni to bibliotekę bardziej elastyczną, z resztą, gdyby libs był przywiązany do jednego strumienia nie mógłby nazywać się libsem 🙂 Od strony pętli głównej jest tylko jedna funkcja sprawdzająca status biblioteki i program główny wygląda tak(na STM32 teraz) while (1) { static uint8_t swState = idle; static uint32_t swtick = 0; if(0 == HAL_GPIO_ReadPin(ENCOSW_GPIO_Port, ENCOSW_Pin) && swState == idle) { swtick = HAL_GetTick()+20; swState = debounce; } if(0 == HAL_GPIO_ReadPin(ENCOSW_GPIO_Port, ENCOSW_Pin) && swState == debounce) { if(HAL_GetTick() > swtick){ swState = run; HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); fnInput(cmdOK); } }else if(HAL_GPIO_ReadPin(ENCOSW_GPIO_Port, ENCOSW_Pin) && swState == debounce)swState = idle; if(swState == run)swState = swend; if(1 == HAL_GPIO_ReadPin(ENCOSW_GPIO_Port, ENCOSW_Pin) && swState == swend)swState = idle; ENCODER_EVENT(); MENUEVENT(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } Czyli skacze do "MENU_EVENT" i na tej podstawie, jeśli menu jest aktywne, podejmuje akcję. Tu jeszcze drzewo struktur na którym operuje biblioteka: #include"stdlib.h" #include"user_menu_tab.h" #include"menu_abstract.h" const node_t nodeTab[] ={ {.ptrNode = start,.nodeID = 0}, {.ptrNode = m,.nodeID = 1}, {.ptrNode = mk,.nodeID = 2}, {.ptrNode = k,.nodeID = 3}, }; const menu_t start[] ={ { .menuNav[_next] = start, .menuNav[_prev] = start, .menuNav[_parent] = start, .menuNav[_child] = m, .id = START }, }; const menu_t m[] ={ { .menuNav[_next] = &m[M2], .menuNav[_prev] = &m[MEND], .menuNav[_parent] = m, .menuNav[_child] = NULL, .id = M1 }, { .menuNav[_next] = &m[M3], .menuNav[_prev] = &m[M1], .menuNav[_parent] = m, .menuNav[_child] = mk, .id = M2 }, { .menuNav[_next] = &m[MEND], .menuNav[_prev] = &m[M2], .menuNav[_parent] = m, .menuNav[_child] = k, .id = M3 }, { .menuNav[_next] = &m[M1], .menuNav[_prev] = &m[M3], .menuNav[_parent] = m, .menuNav[_child] = &start[START], .id = MEND }, }; const menu_t mk[] ={ { .menuNav[_next] = &mk[MK2], .menuNav[_prev] = &mk[MKEND], .menuNav[_parent] = mk, .menuNav[_child] = NULL, .id = MK1 }, { .menuNav[_next] = &mk[MK3], .menuNav[_prev] = &mk[MK1], .menuNav[_parent] = mk, .menuNav[_child] = NULL, .id = MK2 }, { .menuNav[_next] = &mk[MKEND], .menuNav[_prev] = &mk[MK2], .menuNav[_parent] = mk, .menuNav[_child] = NULL, .id = MK3 }, { .menuNav[_next] = &mk[MK1], .menuNav[_prev] = &mk[MK3], .menuNav[_parent] = mk, .menuNav[_child] = &m[M2], .id = MKEND }, }; const menu_t k[] ={ { .menuNav[_next] = &k[K2], .menuNav[_prev] = &k[KEND], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K1 }, { .menuNav[_next] = &k[K3], .menuNav[_prev] = &k[K1], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K2 }, { .menuNav[_next] = &k[K4], .menuNav[_prev] = &k[K2], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K3 }, { .menuNav[_next] = &k[K5], .menuNav[_prev] = &k[K3], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K4 }, { .menuNav[_next] = &k[K6], .menuNav[_prev] = &k[K4], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K5 }, { .menuNav[_next] = &k[KEND], .menuNav[_prev] = &k[K5], .menuNav[_parent] = k, .menuNav[_child] = NULL, .id = K6 }, { .menuNav[_next] = &k[K1], .menuNav[_prev] = &k[K6], .menuNav[_parent] = k, .menuNav[_child] = &m[M3], .id = KEND }, }; #ifndef MNEULIB_USER_MENU_TAB_H_ #define MNEULIB_USER_MENU_TAB_H_ #include "menu_abstract.h" enum start{START}; enum m{M1,M2,M3,MEND}; enum mk{MK1,MK2,MK3,MKEND}; enum k{K1,K2,K3,K4,K5,K6,KEND}; extern const menu_t start[]; extern const menu_t m[]; extern const menu_t mk[]; extern const menu_t k[]; extern const node_t nodeTab[MAXNODE]; // tab ptr #endif /* MNEULIB_USER_MENU_TAB_H_ */ Wygenerowane za pomocą aplikacji którą piszę do tego celu 🙂 Jest jeszcze sporo rzeczy do zrobienia, takich jak bezpośredni dostęp do pozycji za pomocą klawiszy funkcyjnych, chciałbym mieć też możliwość blokowania niektórych pozycji za pomocą prostego hasła. Pozdrawiam 🙂 Edytowano Marzec 25, 2022 przez _LM_ 2 Cytuj Link do komentarza Share on other sites More sharing options...
Popularny post _LM_ Kwiecień 14, 2022 Autor tematu Popularny post Udostępnij Kwiecień 14, 2022 Biblioteka została wstępnie przetestowana na mikrokontrolerze STM32L476 i wygląda na to że działa 🙂 w tej chwili portuję ją na AVRy co też nie stanowi większego problemu poza dostępem do struktur kiedy umieszczam je w pamięci flash. Prawdopodobnie będę potrzebował pomocy w tym zakresie. Mimo to efekty są obiecujące, myślę że w najbliższym czasie będę mógł pokazać krótki film z działania libsa. 4 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!