Skocz do zawartości

Pomocna odpowiedź

(edytowany)

W załączeniu odręczny schemat kinematyki ramienia i macierze dla poszczególnych przekształceń.

schemat.thumb.jpg.2cb776ebb4b438cde9c3632f3af200c7.jpg    30338598_ukady.thumb.jpg.4aa5703ba79c1cbb8986ddb4be2f90af.jpg    macierze.thumb.jpg.33c90abe5ce5c35aed993807f5df5568.jpg

Jak się gdzieś nie pomyliłem 🙂

Policzyłem też macierz transformacji...

Fragment - macierz translacji wygląda tak 😂:

X: (((((c1 * c2 - s1 * s2) * c3) * c4 + ((c1 * c2 - s1 * s2) * s3) * s4) * c5 + (((c1 * s2 + s1 * c2) * -1) * -1) * s5) * s6 + ((((c1 * c2 + -s1 * s2) * c3) * -s4 + ((c1 * c2 + -s1 * s2) * s3) * c4)) * -c6) * H + (((((c1 * c2 + -s1 * s2) * c3) * c4 + ((c1 * c2 + -s1 * s2) * s3) * s4) * s5 + (((c1 * s2 + -s1 * -c2) * -1) * -1) * -c5) * G + ((((c1 * c2 + -s1 * s2) * c3) * -s4 + ((c1 * c2 + -s1 * s2) * s3) * c4) * F + (((c1 * s2 + -s1 * -c2) * -1) * E + ((c1 * c2 + -s1 * s2) * C * c3 + (c1 * s2 + -s1 * -c2) * D))))

Y: (((((s1 * c2 + c1 * s2) * c3) * c4 + ((s1 * c2 + c1 * s2) * s3) * s4) * c5 + (((s1 * s2 + c1 * -c2) * -1) * -1) * s5) * s6 + ((((s1 * c2 + c1 * s2) * c3) * -s4 + ((s1 * c2 + c1 * s2) * s3) * c4)) * -c6) * H + (((((s1 * c2 + c1 * s2) * c3) * c4 + ((s1 * c2 + c1 * s2) * s3) * s4) * s5 + (((s1 * s2 + c1 * -c2) * -1) * -1) * -c5) * G + ((((s1 * c2 + c1 * s2) * c3) * -s4 + ((s1 * c2 + c1 * s2) * s3) * c4) * F + (((s1 * s2 + c1 * -c2) * -1) * E + ((s1 * c2 + c1 * s2) * C * c3 + (s1 * s2 + c1 * -c2) * D))))

Z: (((s3 * c4 - c3 * s4) * c5) * s6 + ((- s3 * s4  - c3 * c4)) * -c6) * H + (((s3 * c4 - c3 * s4) * s5) * G + ((s3 * -s4 - c3 * c4) * F + ((C * s3 + (B + A)))))

gdzie: c1 = cos teta1, s1 = sin teta1, itd.

Na razie to tylko wynik mieszania wierszy i kolumn z mnożenia macierzy teraz trzeba by to po upraszczać, ale najpierw sprawdzę czy wzory zadziałają dla dwóch/trzech znanych pozycji.

Macierzy obrotu (orientacji końcówki) na razie nie zamieszczam bo szkoda miejsca...😂😂😂

Edytowano przez Szałszanin
  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites
22 godziny temu, Szałszanin napisał:

Cześć @FlyingDutch,

Enkodery, których zamierzam użyć to:

OMRON E6B2-CWZ6C
Rotary Encoder Incremental
1000 p/r
5-24Vdc

Mają tak jak typowe enkodery inkrementalne 6 wyprowadzeń: VCC, GND, OUT A, OUT B, OUT Z i COMMON.

Cześć @Szałszanin,

muszę przeanalizować wykresy czasowe podane dla tych enkoderów. Trzeba będzie zmienić dekoder dla takiego enkodera z powodu istnienia trzech faz przebiegu (kod w HDL'u).

Dzięki za odpowiedź 😉

Pozdrawiam

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
22 godziny temu, Szałszanin napisał:

W załączeniu odręczny schemat kinematyki ramienia i macierze dla poszczególnych przekształceń.

schemat.thumb.jpg.2cb776ebb4b438cde9c3632f3af200c7.jpg    30338598_ukady.thumb.jpg.4aa5703ba79c1cbb8986ddb4be2f90af.jpg    macierze.thumb.jpg.33c90abe5ce5c35aed993807f5df5568.jpg

Jak się gdzieś nie pomyliłem 🙂

Policzyłem też macierz transformacji...

Fragment - macierz translacji wygląda tak 😂:

Na razie to tylko wynik mieszania wierszy i kolumn z mnożenia macierzy teraz trzeba by to po upraszczać, ale najpierw sprawdzę czy wzory zadziałają dla dwóch/trzech znanych pozycji.

Macierzy obrotu (orientacji końcówki) na razie nie zamieszczam bo szkoda miejsca...😂😂😂

Cześć @Szałszanin,

super, że miałeś  czas, aby się za to zabrać. Jak będziesz miał ostateczną (uproszczoną) wersję macierzy translacji, to będzie się można przymierzyć, jak to najlepiej policzyć na układzie FPGA. Ja teraz siedzę nad problemem odpowiedniego stablicowania i liczenia funkcji trygonometrycznych (dla rozdzielczości 10 bitów z enkoderów).

Pozdrawiam

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Witaj @FlyingDutch,

Rozumiem, że programujemy tylko 0 … 90 stopni (0..249 z 1000 imp./obrót) bo reszta jest symetryczna, a tablicę cosinusa obchodzimy ze wzoru cos x = sin (90 - x).

Kod dla dekodera dla jednego kanału (wg https://www.digikey.com/eewiki/pages/viewpage.action?pageId=62259228) :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity quadrature_decoder is
	generic(
		PULSES_PER_ROUND	: 	integer := 1000;
		DEBOUNCE_TIME		:	integer := 12000	--ilość cykli zegara wymagana do zarejestrowania nowej pozycji 1ms @ 12MHz
	);
	port(
		clk			:	IN			STD_LOGIC;
		in_a		:	IN			STD_LOGIC;
		in_b		:	IN			STD_LOGIC;
		position	:	BUFFER	integer range 0 to 10 := 0
	);
end quadrature_decoder;

architecture logic of quadrature_decoder is
	signal	a 			:	STD_LOGIC_VECTOR(1 downto 0);
	signal	a_prev		:	STD_LOGIC;
	signal	b			:	STD_LOGIC_VECTOR(1 downto 0);
	signal	b_prev		:	STD_LOGIC;
	signal	debounce_counter	:	integer range 0 to debounce_time;

begin

	process(clk)
	begin
	
		if(rising_edge(clk)) then
		
			--zsynchronizuj i odfiltruj wejścia a/b 
			a <= a(0) & in_a;
			b <= b(0) & in_b;
			
			if(((a(0) xor a(1)) or (b(0) xor b(1))) = '1') then		--wejście a lub b uległo zmianie - wyzeruj licznik
				debounce_counter <= 0;
			
			elsif(debounce_counter = DEBOUNCE_TIME) then	--licznik filtra osiągnął założoną wartość, zaktualizuj a_prev i b_prev
				a_prev <= a(1);
				b_prev <= b(1);
			
			else	--nie minął debounce_time - zwiększ licznik filtra
				debounce_counter <= debounce_counter + 1;
			
			end if;
				
			--określ kierunek i pozycję
			if(debounce_counter = DEBOUNCE_TIME 	--licznik filtra osiągnął założoną wartość i nowa wartość jest różna od porzedniej
				and ((a_prev xor a(1)) or (b_prev xor b(1))) = '1') then
					
				if((b_prev xor a(1)) = '1') then	--zgodnie z kierunkiem zegara
					if(position < PULSES_PER_ROUND) then position <= position + 1;
					else position <= 0;
					end if;
				
				else	--przeciwnie do kierunku zegara
					if(position > 0) then position <= position - 1;
					else position <= PULSES_PER_ROUND - 1;
					end if;
				
				end if;
			end if;
		end if;
	end process;

end logic;

Zamierzam nie wykorzystywać Out Z (znacznik pełnego obrotu).

timing.thumb.jpg.d13f0246a2aa7056f7ba32ce9f857574.jpg

Pozdrawiam.

P.S. Jeszcze nie testowany...

Edytowano przez Szałszanin
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, Szałszanin napisał:

Witaj @FlyingDutch,

Rozumiem, że programujemy tylko 0 … 90 stopni (0..249 z 1000 imp./obrót) bo reszta jest symetryczna, a tablicę cosinusa obchodzimy ze wzoru cos x = sin (90 - x)..

Cześć,

dokładnie tak jak napisałeś. Jest tylko kwestia w jakim formacie trzymamy tablice funkcji trygonometrycznych, jako liczby stało-przecinkowe, czy zmienno-przecinkowe?

Ponieważ kod do dodawania i mnożenia liczb 32-bitowych float działa, to zapiszmy wartości tablicowanych funkcji trygonometrycznych właśnie w tym formacie.

Pozdrawiam

Udostępnij ten post


Link to post
Share on other sites

Cześć,

napisałem dzisiaj program w C++ (Borland C++ Builder 6) do generacji funkcji sinus. Ponieważ do plików *.coe dla IP core Xilinx'a do generacji ROM w BRAM, nie można używać wartości dziesiętnych, była konieczność zapisania liczb float w formacie binarnym (IEEE-754 32-bit). Format ten składa się z trzech części: bit znaku, wykładnik, mantysa.Patrz linki:

https://ryanstutorials.net/binary-tutorial/binary-floating-point.php

https://math.stackexchange.com/questions/144659/an-algorithm-to-convert-float-number-to-binary-representation

https://www.h-schmidt.net/FloatConverter/IEEE754.html

Konwersja 32-bitowej liczby float do jej reprezentacji binarnej, nie jest wbrew pozorom trywialna. Napisany program prawidłowo konwertuje mi wartości float do ich binarnej reprezentacji. Jutro zamieszczę program do generacji pliku coe, tak, aby można z niego bezpośrednio wygenerować ROM BRAM w ISE 14.7 Xilinxa (tablice funcji sinus).

Pozdrawiam

 

 

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
Dnia 20.06.2019 o 13:43, Szałszanin napisał:

Jak myślicie: Czy Arduino wystarczy by bez strat zliczać 7 enkoderów inkrementalnych?

Jakie Arduino masz na myśli?

 

Dnia 22.06.2019 o 09:03, Szałszanin napisał:

Tak mi się wydawało, że Arduino mogłoby dać radę, ale się pogubi przy szybszych ruchach. Tego wolałbym uniknąć. Spróbuję zatem zaprząc do pracy FPGA

Armata na wróbla.

 

Dnia 21.06.2019 o 10:18, daniel89 napisał:

Jeśli potrzebujesz 7 to poszukaj innych chipów co mają Seven 16-bit timers ... Jeśli takich nie znajdziesz to może z dwóch STM-ów uda się to zrobić.

Wystarczy jeden timer wbudowany w ARM i obsłuży bez problemu 7 czy więcej enkoderów. Zamiast timera można tez zagonić do roboty przerwania zewnętrzne. Program będzie prostszy.

Edytowano przez InspektorGadzet

Udostępnij ten post


Link to post
Share on other sites
10 godzin temu, InspektorGadzet napisał:

Wystarczy jeden timer wbudowany w ARM i obsłuży bez problemu 7 czy więcej enkoderów. Zamiast timera można tez zagonić do roboty przerwania zewnętrzne. Program będzie prostszy.

Cześć,

pewnie by się dało to zrobić na STM32, natomiast co do tego, czy program będzie prostszy to nie jestem pewien. Mógłbyś podać jakiś konkretny model STm32xx i szkielet kodu, jak byś to napisał? Dla mnie liczy się także aspekt edukacyjny projektu i tzw. "fun" z jego wykonania..

Pozdrawiam

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
1 godzinę temu, FlyingDutch napisał:

Cześć,

pewnie by się dało to zrobić na STM32, natomiast co do tego, czy program będzie prostszy to nie jestem pewien. Mógłbyś podać jakiś konkretny model STm32xx i szkielet kodu, jak byś to napisał? Dla mnie liczy się także aspekt edukacyjny projektu i tzw. "fun" z jego wykonania..

Pozdrawiam

Praktycznie dowolny STM32 byle miał wymagane peryferia i  liczbę GPIO.

Enkoder jest optyczny, więc drżenia styków nie ma, to wszystko upraszcza, bo można skorzystać z EXTI. Jeden z pinów enkodera wywołuje przerwanie na jednym zboczu, drugi w przerwani jest sprawdzany. Kod można "wyklikać" w CubeMX (inicjalizacja przerwań EXTI, PLL, inne peryferia) po czym w przerwaniach od enkodera:

if( HAL_GPIO_ReadPin( PORT, PIN ) licznik++;
else licznik--;
   

To samo dla pozostałych enkoderów. Odczyt enkodera jest banalny a może i nie. Najprościej:

if( licznik ){
  zmiana += licznik;
  licznik = 0;
}

Taki kod ma pewną wadę, Jakieś tam promile, że będzie gubił impulsy. Należałoby więc zawiesić przerwania na czas operacji na zmiennej licznik. Wystarczy zablokować przerwanie EXTI:

NVIC_DisableIRQ( EXTI???_IRQn );

NVIC_EnableIRQ( EXTI???_IRQn );

Mogę taki kod zrobić w jakieś 15 minut na płytkę NUCLEO czy DISCOVERY. Do tego kolejne 5..10 aby wyniki posłać na UART czy USB i ok 10..20 minut na przetestowanie.

Edytowano przez InspektorGadzet

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
1 godzinę temu, InspektorGadzet napisał:

Taki kod ma pewną wadę, Jakieś tam promile, że będzie gubił impulsy. Należałoby więc zawiesić przerwania na czas operacji na zmiennej licznik. Wystarczy zablokować przerwanie EXTI:

Mogę taki kod zrobić w jakieś 15 minut na płytkę NUCLEO czy DISCOVERY. Do tego kolejne 5..10 aby wyniki posłać na UART czy USB i ok 10..20 minut na przetestowanie.

Cześć,

przerwania od 7-miu encoderów przychodzą równolegle, jeśli w procedurze  obsługi jednego przerwania wyłączysz przerwania, to masz dużą szansę, że będziesz gubił impulsy z innych enkoderów (trzeba, by było to policzyć dla konkretnej płytki i zegara). Właśnie z tego powodu FPGA jest dobrym wyborem dla tego projektu, bo dekodery enkoderów pracuję całkowicie równolegle (sprzętowo) co w dużym stopniu upraszcza projekt.

Nie uwzględniłeś w ogóle kierunku obrotów danego ramienia w dekodowaniu pozycji enkodera (oraz 3-ciego wyjścia Z dla enkodera). Nie było upraszczającego założenia, że enkodery są optyczne - projekt ma być uniwersalny. Jeśli rzeczywiście jesteś tak dobry jak piszesz(zajmuje Ci to tak mało czasu), to napisz pełny kod i go przetestuj, a następnie  wklej do postu, to będzie można go przedyskutować.

Pozdrawiam

Edytowano przez FlyingDutch

Udostępnij ten post


Link to post
Share on other sites
45 minut temu, FlyingDutch napisał:

przerwania od 7-miu encoderów przychodzą równolegle, jeśli w procedurze  obsługi jednego przerwania wyłączysz przerwania, to masz dużą szansę, że będziesz gubił impulsy z innych enkoderów

Widać nie znasz konstrukcji mikrokontrolera. Przerwanie nie będzie zgubione tylko nie zostanie wygenerowane do czasu jego odblokowania. Aby zgubić przerwanie musiałoby nastąpić dwa lub więcej razy zbocze generujące przerwanie a nie sądzę, aby enkoder dał kilkaset impulsów na sekundę.

 

48 minut temu, FlyingDutch napisał:

Właśnie z tego powodu FPGA jest dobrym wyborem dla tego projektu,

Jak się nie umie na mikrokontrolerze to do banalnych działań zaprzęga się FPGA.

 

49 minut temu, FlyingDutch napisał:

bo dekodery enkoderów pracuję całkowicie równolegle (sprzętowo) co w dużym stopniu upraszcza projekt.

Komplikuje o zbędny, w tym przypadku, FPGA.

 

50 minut temu, FlyingDutch napisał:

Nie uwzględniłeś w ogóle kierunku obrotów

Nie widzisz w kodzie licznik++ i licznik-- ?

 

50 minut temu, FlyingDutch napisał:

oraz 3-ciego wyjścia Z dla enkodera)

Po co mam powtarzać taki sam fragment kilka razy? Pokazałem jak obsłużyć jeden enkoder tak samo obsłużysz i 20.

 

52 minuty temu, FlyingDutch napisał:

Nie było upraszczającego założenia, że enkodery są optyczne - projekt ma być uniwersalny.

W pierwszych postaw wyraźnie napisano że są optyczne. Jeśli mechaniczne, to nie mogą pracować zbyt szybko no i ile taki mechaniczny wytrzyma? Jeśli już rzucasz mi kody pod nogi to pokaż jak w FPGA zrealizujesz likwidację drżenia styków. Ja obsłużę wejścia enkodera w przerwaniu 1ms z programowym filtrem RC

if( wejscie ) if( filtr < 10 ) filtr++; else fl_key = true;
else if ( filtr > -10 ) filtr--; else fl_key = false;

No i mam filtr RC 20ms, pokaż rozwiązanie dla FPGA.

 

57 minut temu, FlyingDutch napisał:

to napisz pełny kod i go przetestuj, a następnie  wklej do postu,

Nie muszę testować bo już używałem tego co pokazałem wcześniej. Aby zrobić dobre testy przyślij mi enkodery sprzęgnięte z silnikiem, jakiś sprzęt, który tym wszystkiem steruje zakładając najgorszy przypadek.

 

59 minut temu, FlyingDutch napisał:

to będzie można go przedyskutować. 

Co to za dyskusja, jak nie wiesz, że flaga przerwania jest ustawiona nawet jak przerwanie jest wyłączone? W tym co jużnapisałem wskazałeś dwa, według Ciebie błędy, których nie ma! Taka dyskusja nie ma sensu!

  • Nie zgadzam się! 3

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Cześć,

o ile dobrze pamiętam to dla popularnego STM32F103 to tylko EXTI0 do EXTI4 obsługują bezpośrednie linie. Pozostałe są grupowane po pięć (trzeba określać wektor przerwania), więc kod nie  będzie taki sam dla wszystkich siedmiu enkoderów. Kod dla FPGA  dla obsługi enkoderów z usuwaniem drgań zestyków był już podany w tej dyskusji, widać nie czytasz dokładnie postów na które odpowiadasz. Pamiętaj, że oprócz zdekodowania stanu wszystkich encoderów trzeba jeszcze przeliczyć aktualne pozycje liczników enkoderów na współrzędne x, y, z końcówki ramienia, co jest dość obciążającym CPU zadaniem obliczeniowym - w przypadku FPGA mogę również te obliczenia zrównoleglić (co w przypadku CPU jest trudne do uzyskania - no chyba, że będziemy tu zatrudniać RTOS'a lub wielo-rdzeniowe CPU). Po drugie, gdyby była taka potrzeba, to bez spadku wydajności mogę dodać dowolną liczbę enkoderów (lub wykonywać inne przetwarzania)

Tutaj link do artykułu o przerwaniach zewnętrznych dla STM32F1xx:

http://embedded-lab.com/blog/stm32-external-interrupt/

Cytat

Jak się nie umie na mikrokontrolerze to do banalnych działań zaprzęga się FPGA.

Z mojego doświadczenia wynika, że ten sam problem często można dużo prościej rozwiązać na FPGA niż na mikro-kontrolerze (np. generacja obrazu VGA czy HDMI). Często  kod, który musisz napisać  w języku HDL jest dużo prostszy niż odpowiadający mu kod w języku C dla mikro-kontrolera. Jeśli nie lubisz/ nie masz doświadczenia z układami FPGA to twój problem. Po drugie napisałem Ci już, że dla mnie ważny jest aspekt edukacyjny tego rozwiązania FPGA (samodoskonalenia się w budowie układów opartych na FPGA).

Pozdrawiam

Edytowano przez FlyingDutch

Udostępnij ten post


Link to post
Share on other sites
16 minut temu, FlyingDutch napisał:

o ile dobrze pamiętam to dla popularnego STM32F103 to tylko EXTI0 do EXTI4 obsługują bezpośrednie linie. Pozostałe są grupowane po pięć (trzeba określać wektor przerwania), więc kod nie  będzie taki sam dla wszystkich siedmiu enkoderów

Będzie jak napiszesz mądrze albo użyjesz HAL_GPIO_EXTI_Callback

 

17 minut temu, FlyingDutch napisał:

Kod dla FPGA  dla obsługi enkoderów z usuwaniem drgań zestyków był już podany w tej dyskusji, widać nie czytasz dokładnie postów na które odpowiadasz.

Nie czytałem tych wypocin bo w tym projekcie FPGA jest zbędna.

 

18 minut temu, FlyingDutch napisał:

Pamiętaj, że oprócz zdekodowania stanu wszystkich encoderów trzeba jeszcze przeliczyć aktualne pozycje liczników enkoderów na współrzędne x, y, z końcówki ramienia, co jest dość obciążającym CPU zadaniem obliczeniowym

Odnoszę wrażenia, ze znasz FPGA nie znasz ARM i dlatego na siłę próbujesz udowodnić, ze FPGA będzie lepsza.

  • Nie zgadzam się! 3

Udostępnij ten post


Link to post
Share on other sites
1 godzinę temu, InspektorGadzet napisał:

Odnoszę wrażenia, ze znasz FPGA nie znasz ARM i dlatego na siłę próbujesz udowodnić, ze FPGA będzie lepsza.

Oczywiście mistrzu, proszę o jeszcze więcej pomocnych komentarzy, bo chcę z nich czerpać wiedzę 😉

Pozdrawiam

Udostępnij ten post


Link to post
Share on other sites

Włączę się jako pomysłodawca tematu 🙂

Od pierwszego postu się zastanawiam czy lepiej procesor czy FPGA. 

Program na procesor mogę napisać w 2 godziny, ale czy obsługa 7 przerwań  i do tego na bieżąco mnożenie 7 macierzy z sinusami i kosinusami bieżącej wartości liczników na pewno nie zajmie zbyt dużo czasu? Przyznam, że nie policzyłem czasów przetwarzania dla takich operacji. Może i tak. Może w następnym etapie spróbuję i takiego podejścia (łatwiejsze do wykonania).

Ponieważ jednak moim założeniem podstawowym jest nie gubić impulsów, intuicyjnie spodobał mi się pomysł FPGA, a do tego jest to co wspomniał @FlyingDutch - aspekt edukacyjny. Jeszcze nie umiem mnożyć macierzy ani używać LUT na FPGA. Ale już zaczynam rozumieć...

Mimo powyższych uwag @InspektorGadzet, uważam że przetwarzanie równoległe jest w tym przypadku korzystniejsze i w takiej wersji będę kontynuował.

Pozdrawiam. 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

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!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...