-
Postów
740 -
Dołączył
-
Ostatnia wizyta
Typ zawartości
Profile
Forum
Blogi
Wydarzenia
Galeria
Pliki
Sklep
Articles
Market
Community Map
Odpowiedzi opublikowane przez Sebo_b
-
-
12 hours ago, r.ziomber said:
Ale ja oczekuje krytyki! Chce sie uczyc od zawodowych programistow i doskonalic swoje znikome umiejetnosci.
Jesli tylko masz czas napisac, z checia wyslucham, co zrobilem zle!
Na szybko zrefaktorowałem Twój kod, a w sumie to napisałem go od nowa zachowując logikę. Nie testowałem tego kodu (tylko syntax), więc jest pewnie sporo bugów. Ale wyłapanie bugów to dobre ćwiczenie
#include <limits.h> #include <cstdlib> class Timer { public: typedef void(*Callback)(void*); Timer(); ~Timer(); /** * count < 0 for unlimited execution * returns task number or 0 if fail; **/ size_t addTask(long delay, long interval, int count, Callback callback, void* cbParam); void removeTask(size_t taskId); void run(); void cleanUp(); private: struct Task { long interval; unsigned long nextCall; int count; size_t taskId; Callback cb; void* cbParam; }; Task* tasks; size_t tasksSize; size_t taskIdCounter; bool clean; unsigned long nextCall; }; Timer::Timer(): tasks(NULL), tasksSize(0), clean(true), nextCall(ULONG_MAX), taskIdCounter(0) { } Timer::~Timer() { if (tasks) free(tasks); } size_t Timer::addTask(long delay, long interval, int count, Timer::Callback callback, void* cbParam) { if (count == 0 || callback == NULL || interval == 0) return 0; Task *t = NULL; unsigned long now = ::now(); if (!clean) { for (size_t i = 0; i < tasksSize; ++i) { if (tasks[i].count == 0) { if (t == NULL) { t = tasks+i; clean = true; } else { clean = false; } } } } else { Task* newTasks = static_cast<Task*>(realloc(tasks,(tasksSize+1)*sizeof(Task))); if (!newTasks) return 0; tasks = newTasks; t = newTasks + tasksSize++; } t->interval = interval; t->nextCall = now + interval + delay; t->count = count; t->cb = callback; t->cbParam = cbParam; t->taskId = ++taskIdCounter; if ( static_cast<long>(nextCall - t->nextCall) >= 0) nextCall = t->nextCall; return t->taskId; } void Timer::removeTask(size_t taskId) { // we don't need to update nextCall, in the worst case we end up with one empty loop in run() // unsigned long nextCallSoFar = ULONG_MAX; for (size_t i = 0; i < tasksSize; ++i) { if (tasks[i].taskId == taskId) { tasks[i].count = 0; clean = false; // if ( nextCall != tasks[i].nextCall) return; } // else if (static_cast<long>(nextCallSoFar - tasks[i].nextCall) >= 0) { // nextCallSoFar = tasks[i].nextCall; // } } // nextCall = nextCallSoFar; } void Timer::run() { unsigned long now = ::now(); if ( static_cast<long>(now - nextCall) >= 0 ) { for (size_t i = 0; i < tasksSize; ++i) { nextCall = ULONG_MAX; if (tasks[i].count != 0 && static_cast<long>(now - tasks[i].nextCall) >= 0) { tasks[i].cb( tasks[i].cbParam); if (tasks[i].count > 0 && --tasks[i].count == 0) clean = false; else tasks[i].nextCall = now + tasks[i].interval; } if ( static_cast<long>(nextCall - tasks[i].nextCall) >= 0) nextCall = tasks[i].nextCall; } } } void Timer::cleanUp() { if (clean) return; Timer *head = tasks, *tail = tasks + tasksSize - 1; while (head < tail) { if (head->count == 0 && tail->count != 0) { *head = *tail; tail->count = 0; } if (head->count != 0) ++head; if (tail->count == 0) --tail; } size_t newTasksSize = head-tasks; Task* newTasks = static_cast<Task*>(realloc(tasks,newTasksSize*sizeof(Task))); if (newTasks == NULL) return; // we basically keep it unclan tasks = newTasks; tasksSize = newTasksSize; clean = true; }
- 1
-
(post do usunięcia)
-
Z tym co zaproponowane overflowy nie powinny mieć wpływu na średnie czasy - arytmetyka zadziała.
1 minute ago, Behlur_Olderys said:static_cast wygląda najbardziej elegancko, ale znowu - muszę sam się przekonać
Tutaj nie ma się co przekonywać, to trochę jak byś przyjechał z Anglii (pisanie w C) i twierdził, że musisz się przekonać do prawostronnego ruchu (C++) Piszesz w C++ to używać "pożądnych" castów. Co więcej, zaczniesz (lepiej nie) używać wielodziedziczenia i C casty się wysypią.
-
4 hours ago, r.ziomber said:
przedzial czasu obejmujacy przekroczenie zakresu zmiennej
Masz rację, że jest tam bug, a nawet dwa:
1. Overflow nextCall - tak jak napisałeś, now() będzie duże, nextCall małe
2. Overflow now() bo nie mamy pewności czy pod koniec zakresu zdąży się wykonać, czyli nextCall będzie duże, a now() małe
To są dodatkowe cornercase'y, więc || a nie && w Twoim rozwiązaniu powinien to załatwić, tylko że pierwszy warunek zawiera się w tym co zaproponowałeś - więc wystarczyło by :
if ( now() - nextCall < ULONG_MAX / 2 ) { // lub - bez dzielenia (choć to tylko estetyka w tym przypadku) if ( now() - nextCall < (ULONG_MAX >> 1) ) { // lub - moim zdaniem bardziej czytelnie if ( now() - nextCall < LONG_MAX ) // lub - bez użycia limits if ( now() - nextCall < (~0ul >> 1) ) // a ja bym napisał to tak, żeby było dla każdego czytelne (choć nie widać tak od razu, że obsługuje corner-case'y) if ( static_cast<long>(now() - nextCall) >= 0 ) {
- 2
-
Też podejrzewałem, że sobie to kompensuje. Align na 3 gwiazdy daje wszystkie potrzebne do tego informacje.
-
34 minutes ago, RMK said:
Można więc napisać lub wykorzystać oprogramowanie
Z takich ciekawostek, guiding potrafi działać przez port ST4 albo właśnie bezpośrednio przez pule-commands do silników. Więc jest tak jak piszesz, ale z kamerą.
-
1 hour ago, MateuszW said:
Niestety nie, na 100% SW nie używa drugiej osi.
Dzięki.
4 minutes ago, MateuszW said:Można napisać, ale jak dotąd, nikt nie napisał
Napisał tylko zamiast skomplikowanego mapowiania nieba używa do tego bardziej elastycznej metody i kamery - nazywa się PHD2
-
W trybie AZ montaże AZEQ trackują w obu osiach Alt i Az - inaczej się nie da.
-
2 hours ago, Tayson said:
Stackujesz w DSS? Mam nadzieję że w finalny stacku kanały RGB nie są zrownane.
Poprawna kalibracje koloru możesz uzyskać np eXcalibratorem + np nova astrometry net / upload + color combine w maximie.
Alternatywa to jeszcze np PixInsight płatny.
Pracuję na Macu - więc mam bardzo ograniczony wybór softu. Gdyby Pixinsight kosztował z połowę tego co kosztuje to bym się pewnie skusił, teraz sporo jeszcze przede mną zanim zacznę odczuwać braki w używanych toolach.
2 hours ago, Tayson said:Bez stosowania masek w pewnym momencie zatrzymasz się w rozwoju i nie dasz ani kroka dalej. Twój wybór....
Jeśli dojdę do tego momentu, to pewnie zacznę stosować. Po niedzieli wracam do Wawy i moje hobby się mocno ograniczy, jechać po 50-100km ze sprzętem i stać z pół nocy na zimnie samemu... pewnie znowu teleskop wyląduje w szafie na długie miesiące
Podeszłem teraz inaczej, Nebulosity tylko stack + stretch, reszta w Affinity. Kanały są wszystkie, nawet niebieskie gwiazdki wyszły, tylko znowu jakieś takie niebiesko-zielone to zdjęcie. Trochę szumu tła zostawione specjalnie dla @Pav1007
-
9 hours ago, Behlur_Olderys said:
jest z tym dużo pracy dla programistów ostatnio
Wciąż jest dużo, ale już coraz mniej. Oprócz pracy typowo dla elektronika: komórki od czasu iOSa i Androida to już nie embedded. Zostały telewizory, ale tam też coraz więcej Androida, więc jeśli nie pracujesz u SoC vendora (np MTK) to też nie embedded. Automotive się jeszcze broni rękami i nogami przed Googlem i Applem.
- 1
-
3 minutes ago, piotr.d said:
OK, ale co ja wtedy mogę zrobić?
Na Synscanie poniżej align na 3 gwiazdy jest Polar Alignment. Działa to tak:
1. Montaż ustawia się na jasnej gwieździe, np Arcturus
2. Prosi o dokładne ustawienie jej w środku pola (pilotem). PS: nie wiem czy znasz tę metodę, ale jeśli nie masz okularu z krzyżem, to rozogniskowanie pomaga w ustawieniu obiektu centrycznie (jest po prostu dużym kółkiem w okularze).
3. Przestawia o błąd w jednej osi i prosi o ustawienie śrubami (NIE pilotem).
4. Robi to samo dla drugiej osi.
Po tym trzeba znowu wyalignować na 3 gwiazdy. Czasem procedurę powtórzyć, żeby mieć jeszcze dokładniej.
8 minutes ago, piotr.d said:Pozwolę sobie zadać jeszcze pytanie odnośnie tego żeby wiedzieć czy dobrze zrozumiałem. Załóżmy, że trafiłem na montaż idealny, który nie ma błędów
Jeśli montaż będzie idealnie prowadził i będzie idealnie wypoziomowany - to obiekt będzie sztywno, niezależnie od alignowania. Alignowanie jest potrzebne tylko do GOTO*, procedurę alignowania można pominąć i kręcić ręcznie.
* - nie mogę nigdzie znaleźć potwierdzenie / zaprzeczenia czy montaże SW EQ zawsze prowadzą tylko w jednej osi, czy może jak wykryje cone-error (brak poziomu) w czasie alignacji to pomaga sobie drugą osią. Mam podejrzenie, że sobie pomaga, bo wczoraj miałem żyletę na biegun (ustawiane softem) a obiekty po godzinie odjeżdżały, nie zauważyłem, że w menu był ustawiony cone-error z poprzednich alignów.
-
Widziałem to - czerwony jest zgubiony gdzieś na wcześniejszym etapie (przed eksportem stacka do programu graficznego). Nie byłem w stanie go już odzyskać bez cofania się do początku.
-
6 hours ago, Pav1007 said:
Ja jednak proponuję zrobić zwykłego flata
Nie mam flatownicy, sprzęt rozkładam po zmroku i składam przed świtem Więc posiłkuję się jak mogę. W drugiej próbie zrobiłem "ręcznie" syntetycznego flata.
Dziś nauczyłem się jeszcze jednego, obrabiać należy w nocy / wieczorem, a nie w bardzo słoneczny dzień
Jak teraz?
-
@Zorg7 ja polecam Affinity Photo jako tańszą konkurencję PSa. Darmowy nie jest, ale cena bardzo konkurencyjna.
-
9 minutes ago, Pav1007 said:
Masz świetną skalę na ten obiekt.
Dzięki - mam jeszcze większa z asi290mc, jak uda mi się porządnie to złożyć to może nałożę sam środek.
Co do "paprochów", to chyba znalazłem, synthetic flat fielder z Nebulosity dość mocno to wycina. Złożę na spokojnie jeszcze raz. Dzięki wszystkim za komentarze.
-
49 minutes ago, RomekAstrobaza said:
Aby czy na pewno?
Na pewno. Patrzyłem na Twoje zdjęcie przed publikacją - masz tam większy FOV, ale 1:1 każda punktowa (nie szare tło) gwiazda u Ciebie występuje też u mnie. Tylko @Pav1007 jak zwykle ma rację, że za bardzo pojechałem z tłem, dlatego się dość bardzo odcięły, niektóre mają po kilka pixeli.
Załączam porównanie Twojego zdjęcia do mojego - 1:1 crop ze środka, nic nie modyfikowane.
EDIT: forum wycina animowane PNG, wrzucam GIFa.
- 1
-
Dzięki @wessel za zdjęcie referencyjne.
-
2 minutes ago, wessel said:
A gwiazdki nakładasz stemplem, to nie jest dobry pomysł
Nie nałożyłem żadnej gwiazdki stemplem. Jestem też przeciwnikiem masek - choć tutaj dla dwóch placków zrobiłem wyjątek.
-
EDIT: usunięte, bo tylko śmieci
-
W tle nic już więcej nie ma, sprawdzałem - i chyba zaczynam lubić ciemne Niebieski też mi przeszkadzał, ale popatrzyłem na kilka innych zdjęć i tam chyba po prostu jest niebiesko...
-
Dość oklepany obiekt, ale chciałem go powtórzyć w szerszym polu (wiem, i tak wąskie).
Łapane wczoraj, księżyc prawie 90% ale o 23:30 już dość nisko, bo 10 st.
MN190 / EQ6-R / Canon 40D / ISO400 / 120x30s + darki.
EDIT: Po żywej dyskusji w wątku i pomocy wielu forowiczów (dzięki) podmieniam zdjęcie na trochę lepsze. Do ideału daleko - ale na razie muszę odpocząć od tego obiektu. Może się przesiądę na czarnobiałą kamerę bez filtrów
-
1 hour ago, Behlur_Olderys said:
Ciekawe, chyba masz rację z tym timeAwaited, ciekawe co się stanie jak tak napiszę Może w weekend znajdę trochę czasu...
Ale operatory przesunięcia w Twoim kodzie jakoś mnie zniechęcają strasznie
Może za mało embedded kodu widziałeś Można to owrapować w define'y - ale moim zdaniem wtedy nie jest czytelne. Jak usuniesz delta, bo myślę, że z nią to przesadziłem (zrób testy na sprzęcie, sam jestem ciekaw) - to kod się uprasza do kilku linii i imo jest mega czytelny.
Oczywiście założenie jest, że chcesz mieć jak najdokładniej zachowany czas całej sekwencji, a nie różnicę pomiędzy wywołaniami.
// constructor nextCall = now() + interval; //active loop if ( nextCall < now() ) { nextCall += interval; callWhatever(); }
- 1
-
1 hour ago, sidiouss said:
1kHz
1kHz? Rozumiem, że to 1 kbps. 20 lat temu na 8051 wyciągałem stabilne 115200bps (choć nie na timerach). Więc 1kHz dzisiaj to nie powinien być żaden problem.
-
1 hour ago, sidiouss said:
STMy z DMA
Schodzimy coraz niżej
Co do samego kodu, dość pokrętnie napisane, np:
m_timeStart = timeNow; // leftover = timeNow - m_timeAwaited // in SetAwaitedTime m_timeAwaited = (unsigned long)(m_timeStart + m_interval - leftover); // so m_timeAwaited = m_interval + m_timeAwaited
Propozycja:
// constructor nextCall = now() + interval; delta = 0; //active loop unsigned long n = now(); if (nextCall - (delta >> 8) < n) { nextCall += interval; delta = ( (abs(nextCall - n) << 7) + (delta*4) )/5; // old delta is weighted 4, new delta is weighted 1, this needs to be checked on hardware to determine right weights callWhatever(); }
W zaproponowanym rozwiązaniu:
- kolejne czasy liczę zawsze od bazowego (nextCall += interval), więc niedokładności wywołań nie wpływają na kolejne wywołania,
- kod jest odporny na przepełnienia, po prostu arytmetyka zadziała,
- gdyby stosować proste if (nextCall < n to czasy odchylały by się zawsze w jedną stronę, było by spóźnienie, stąd delta która odchyla to w stronę przeciwną
- delta za każdym razem się koryguje (średnia ważona, waga 4 na starą wartość, waga 1 na nową)
- delta ma 8 bitów dokładności po przecinku, nowa jest przesuwana o 7 bitów bo interesuje nas połowa delty żeby rozłożyć czasu równomiernie po obu stronach
- jeśli na Arduino mnożenie i dzielenie jest drogie (nie wiem tego) to *4 można zamienić na << 2
Nie kompilowałem/debuggowałem/testowałem tego kodu, więc ręki nie dam sobie uciąć, że wszystko działa poprawnie - ale pokazuje o co chodzi.
EDIT: ta delta może być przedwczesną optymalizacją - bez tego pewnie średnio zadziała tak samo dobrze.
- 1
Okresowe wołanie funkcji w Arduini
w ATM, DIY, Arduino
Opublikowano
Nie rozumiem, w którym miejscu?
To jest oczywiście kolejny krok, wydzielenie kolekcji na zewnątrz. Ale z drugiej strony jest to taka prosta struktura, że można pominąć.