Skocz do zawartości

Kurs STM32L4 – #8 – liczniki sprzętowe (PWM, enkoder)


Pomocna odpowiedź

Dzięki za masę pracy włożoną w ten kurs, jest super.

Do rzeczy: Korzystam z kodu w śródtytule "Tryb obsługi enkoderów w STM32L4". Mam podłączony enkoder (spoza zestawu), przy zmianie pozycji (obracaniu) można wyczuć takie miękkie klikanie, każdy klik powoduje u mnie zwiększenie/zmniejszenie wartości zmiennej

value = __HAL_TIM_GET_COUNTER(&htim3)

o 2. Przy powolnym obracaniu 'pomiędzy klikami' mam upragnioną zmianę o 1, ale nie jest to optymalne. Czy w CubeMX gdzieś można wyklikać odpowiednie ustawienia?

Wiem że można dopisać linijkę kodu i podzielić 'value' przez 2, ale chyba lepiej byłoby skorzystać ze sprzętowej obsługi.

Przy zmienie ustawień w CubeMX znalazłem opcję 'Encoder Mode', przy zmianie na 'Encoder Mode TI1 and TI2' za każdym miękkim klikiem mam skok o 4, ale to nie o taką zmianę mi chodziło.

  • Lubię! 1
Link do komentarza
Share on other sites

@smilee a jak masz ten kod:

/* USER CODE BEGIN WHILE */

HAL_TIM_Base_Start(&htim3);
uint32_t old_value = 0;

while (1)
{
  uint32_t value = __HAL_TIM_GET_COUNTER(&htim3);

  if (old_value != value) {
    old_value = value;
    printf("value = %lu\n", value);
  }

/* USER CODE END WHILE */

To czy zmienna zmienia się z krokiem co 1?

Link do komentarza
Share on other sites

@Gieneq nie, nigdy. Ale cytowany listing nie miał w swoim zadaniu zliczać co 1, tylko pokazywać zmianę szerokości impulsu w zależności od prędkości kręcenia. I tutaj program spisuje się znakomicie. Kręcę szybko, impulsy następują po sobie szybko, zmienna wskazuje małe wartości 30 - 150, ekstremalnie wolno: 10000 - 40000. 

Po małym dochodzeniu mogę powiedzieć nieco więcej. 

Sprzętowo wyjścia enkodera mam podciągnięte to zasilania, więc 'w spoczynku' oba są w stanie wysokim. Kręcę w prawo (kierunek obrotu wskazówek zegara). Poniżej zdjęcie przebiegu generowanego przez enkoder (jeden softclick).

Encoder.thumb.jpg.078863b9c8936875563828446913aa12.jpg

A teraz grafika z książki pt.: "Mastering STM32" napisanej przez Carmine Noviello

954317262_Screenshot2021-10-21140626.thumb.png.fa4f62e2c556d34903df8812daceaddb.png

I to wyjaśnia zaistniałą sytuację. Mam odpowiednik trybu X2 przy ustawieniu w CubeMX: 'Encoder Mode' na 'Encoder Mode TI1'; na jeden softclick licznik zmienia wartość o 2. Żeby uleczyć moją bolączkę zmodyfikowałem linię kodu i zrobiłem tak:

value = (__HAL_TIM_GET_COUNTER(&htim3) >> 1);

Teraz już pięknie zwiększa/zmniejsza się o 1. Trzeba tylko pamiętać,że w tym przypadku wartość na pełen obrót musi być x2. (U mnie na jeden obrót jest 20 softklików, więc w CubeMX 'Counter Period' ustawiam na 40).

Można też pójść dalej i w CubeMX ustawić  'Encoder Mode' na 'Encoder Mode TI1 and TI2' i wtedy mamy odpowiednik trybu X4, wtedy linię kodu zamieniamy na 

value = (__HAL_TIM_GET_COUNTER(&htim3) >> 2);

a wartość na pełen obrót x4.

Ale to jeszcze nie koniec (niestety). Walczę dalej. Spoglądając na schemat układu liczników w STM, znajdujemy tam takie coś:

Timers.thumb.png.8e34cea973fbdc37d7719b80711b8043.png

Mogę spróbować z preskalerem. W kodzie sprawdzamy warość CNT counter, na lewo mamy preskaler PSC. Więc szybko wróciłem do oryginalnej linii kodu, a w CubeMX zmieniłem ustawienia: 'Encoder Mode' na 'Encoder Mode TI1' i dodatkowo 'Counter Settings --> Prescaler' na 2.

I trochę działa. To "trochę" to dlatego, że pierwsze dwa softkliki liczone są poprawnie, ale trzeci jest zgubiony. I tak cyklicznie.

Powrót do ustawień w CubeMX i lecimy: 'Encoder Mode' na 'Encoder Mode TI1 and TI2' i dodatkowo 'Counter Settings --> Prescaler' na 4. Tym razem gubię klik 1 a potem 6, potem 11 itd.

Niestety nie znalazłem jeszcze odpowiedzi na to, dlaczego tak się dzieje i wybieram opcję modyfikacji kodu z przesunięciem bitowym w prawo. To rozwiązuje mój problem. Tutaj zostawiłem wpis dla kogoś, kto natknął się na podobną zagwozdkę.

Jeśli ktoś ma jakieś dodatkowe info, to chętnie usłyszę. Pewnie możnaby zaprząc do pracy pana Debugger-a, ale chciałem pójść dalej z kursem, więc na razie daję temu spokój.

 

  • Lubię! 1
Link do komentarza
Share on other sites

Nie potrafię ustawić diody RGB tak żeby przez sekundę świecił się kolor niebieski a następnie gasł i zapalał się czerwony, próbowałem już różnych kombinacji i jedyne co uzyskuje to efekt, że pali się czerwony kolor, następnie niebieski, gasną na chwilę po czym zapalają się oba na raz. Czy mógłby mi ktoś pomóc z tym i wyjaśnić jak to należy ustawić i z czego to wynika?

Edit. Po wielu próbach różnych kombinacji udało się po ustawieniu na obu kanałach asymetrycznego PWM.

Edytowano przez atm320
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

@Gieneq Wstawiam kod

image.thumb.png.16cdbebae21b8986c1244e0850848dee.png

Nad pętlą while:

image.thumb.png.5ca7624b2ba3780662d5ef914e89c092.png

Program działa zgodnie z założeniem, do TIM3 dołączone są dwie diody jedna świeci 2 sekundy, natomiast druga 50ms, do TIM4 dołączona jest dioda RGB w której kolory zmieniają się co 0,5s, co daje efekt koguta policyjnego. Na dole dołączam jeszcze skriny z ustawień timerów.

TIM4:

image.thumb.png.cf890c86c9de442dcea604ec203af943.png

TIM3:

image.thumb.png.d217b129c906fb3fd552cb08999349e3.png

EDIT:

Mam jeszcze problem z 3 zadaniem, użyłem funkcji __HAL_TIM_SET_COMPARE, której zadaniem było przyjęcie nowej wartości Pulse, dla czerwonej i niebieskiej części diody RGB. Niebieska część diody która jest opisana w kodzie jako TIM_CHANNEL_1 rzeczywiście przyjmuje wartość czasu trwania impulsu enkodera, natomiast czerwona część diody opisana jako TIM_CHANNEL_2 cały czas świeci 0,5s. Czy ktoś mógłby mi wyjaśnić z czego to wynika i jak to naprawić?

image.thumb.png.cdf52c240d97f870768453aed9ec93fd.png

image.thumb.png.ce3fb7fa1edd5a68232f5fc779aa4948.png

Ustawienia TIM4 dla diody RGB

image.thumb.png.5bd2f2032c0d6441bf7baf7c61548427.png

image.thumb.png.5585aa5c176dd5c24c77d932d21c8fd2.png

Edytowano przez atm320
Link do komentarza
Share on other sites

@atm320 najpierw pierwsze pytanie o RGB, wydaje mi się, że da się to zrobić na 1 timerze. Najpierw włącz jedną z diod - będą przesunięte w fazie (migały na zmianę).

Wtedy przy przerwaniu od jednego timera używasz toggle na obu diodach - jedna zgaśnie druga się włączy. W kursie obsługiwaliśmy 3 kanały jednocześnie, tu wystarczy jeden, wybierz np połowę CNT i powinno migać z wypełnieniem 50%, dobierz tylko częstotliwość.

image.thumb.png.0f76db28fe12e327cf057b07abaabd0b.png

Rozpatrujesz przerwanie tam gdzie zaznaczyłem na żółto.

Link do komentarza
Share on other sites

Do rozdziału "Pomiar szerokości impulsu za pomocą licznika"

fajnie byłoby rozpisać dokładniej ten paragraf, np. dodać przebiegi z enkodera z zaznacznonymi miejscami od kiedy do kiedy realizowany jest pomiar szerokości impulsu, itp.

Link do komentarza
Share on other sites

Witam, wydaje mi się, że w sekcji  Obliczenie preskalera i okresu jest błąd. 

"Timer TIM6 jest licznikiem 16-bitowym, a więc przy taktowaniu z 80 MHz swoją maksymalną wartość osiągnie po niecałej milisekundzie (12,5 ns × 65 536 = 819 200 ns)."  

Jakbym miał 2 bitowy licznik i częstotliwość zegara 80MHz to mógłbym zliczyć max do 22-1 = 3. Kolejne wartości w liczniku by były: 00, 01 - 1  × 12,5, 10 - 2 x 12,5, 11 - 3 × 12,5 ns.  Czyli po 3  × 12,5 ns nastąpi przerwanie prawda? Podobnie dla 16 bitów by było przerwanie po 12,5 ns × 65 535.

Edytowano przez pirx1988
Link do komentarza
Share on other sites

Dnia 12.03.2022 o 12:47, pirx1988 napisał:

Kolejne wartości w liczniku by były: 00, 01 - 1  × 12,5, 10 - 2 x 12,5, 11 - 3 × 12,5 ns.

@pirx1988 przepraszam, za późne odpisanie. Jednak 4 okresy:

  1. 00 - mija czas - 01,
  2. 01 - mija czas - 10,
  3. 10 - mija czas - 11,
  4. 11 - mija czas - 00 + carry out.

To by sie wydarzyło dla 2bitowego licznika. Jeżeli licznik ma 16 bitów i wybierzesz sobie mniejszą wartość to porównanie nastąpi w jakimś stosunku do sygnału zegarowego, wiec możesz założyć podobną sytuację.

Link do komentarza
Share on other sites

Próbuję ustawić timer aby generował przerwanie zaraz po rozpoczęciu kręcenia enkoderem, tak aby nie było trzeba non stop sprawdzać zawartości licznika, czy jest taka możliwość?

EDIT

Znalazłem, choć do końca tego nie rozumiem, jest przerwanie które wykonuje się po zakręceniu enkoderem(u mnie na timerze 4):

void TIM4_IRQHandler(void)
{
  /* USER CODE BEGIN TIM4_IRQn 0 */

  /* USER CODE END TIM4_IRQn 0 */
  HAL_TIM_IRQHandler(&htim4);
  /* USER CODE BEGIN TIM4_IRQn 1 */

  /* USER CODE END TIM4_IRQn 1 */
}

Jednak nie jest ono __weak i nie jest dostępne w main.c 

HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_1);
HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_2);

niestety dla tych przerwań niema callbacków, albo ja nie umiem ich odnaleźć

Edytowano przez _LM_
Link do komentarza
Share on other sites

W artykule widnieje informacja, że "...liczniki od TIM2 do TIM7 są podłączone do magistrali APB2, a pozostałe do APB1". Jednak w dokumentacji jest to przedstwione na odwrót:


src.thumb.png.6ade8156150324430eb7886a247dc4d7.png

Można to zeweryfikować poprzez wykonanie ćwiczenia przedstawionego w artykule dotyczącego migania diodą co 1 sekundę. W przypadku zmniejszenia częstotliwości w magistralii APB1 na 40MHz dioda będzie włączona przez 2 sekundy i wyłączona również przez 2 sekundy. Zmiana cześtotliwości w magistrali APB2 nie ma wpływu na miganie diody, co wskazuje na to że używany w przykładzie TIM6 nie jest związany z magistralą APB2, lecz z magistralą APB1, tak jak podaje dokumentacja.

Link do komentarza
Share on other sites

Mam mały problem kodem konfiguracji timera generowanym przez CubeMX (przy czym przerabiam kurs na F103RB)

Otóż program nie generuje mi funkcji:

HAL_NVIC_EnableIRQ(TIM2_IRQn);

mimo, że ustawiam przerwanie od timera oraz jego priorytet. Przy ustawianiu przerwań z GPIO nie ma tego problemu a tutaj muszę tą funkcję ręcznie wklejać. 

Nie jest to może duży problem, raczej niedogodność ale czy zna ktoś przyczynę? Może czegoś nie ustawiam do końca?

Link do komentarza
Share on other sites

Cześć,

Mam problem z enkoderem, kupiłem goły bez płytki. Z tego co widziałem w sieci, to na tej płytce są rezystorki 10k polutowane do VCC.
Jak się domyślam chodzi o podciągnięcie niektórych pinów pod + zasilania. Nie wiem czy ma to znaczenie w moim przypadku.

Enkoder jaki zakupiłem wygląda tak:

1.thumb.png.8fc8521d613d2ee982663421927a7d7f.png

Oto kod jaki wgrałem do płytki:

/* USER CODE BEGIN 0 */
int __io_putchar(int ch) 
{
	if (ch == '\n') 
	{
		__io_putchar('\r');
	}
	
	HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, HAL_MAX_DELAY);
	return 1;
}
/* USER CODE END 0 */


/* USER CODE BEGIN WHILE */
HAL_TIM_Base_Start(&htim3);

while (1)
{
	uint32_t value = __HAL_TIM_GET_COUNTER(&htim3);
	printf("value = %lu\n", value);
}
/* USER CODE END WHILE */

 

Ustawienia Timera3 w STM32CubeIDE:
2.thumb.png.a515d307e6cee827ab31679be59bba4c.png


Program zachowuje się tak, że co drugi krok licznik cały czas nalicza i przestaje gdy przejdę do kolejnego. I tak w kółko. Czy coś źle podłączyłem?

 

Bez tytułu.png

Edytowano przez dragolice
Link do komentarza
Share on other sites

Odpowiem sam sobie na pytanie, rzecz jest bardzo prosta, jakby ktoś miał problem z podłączeniem enkodera bez płytki PCB to koniecznie musimy go doposażyć o kilka elementów. Schemat przedstawia się następująco (rysowałem ja, ale zaczerpnięte od Mirosława Kardasia z poradnika na YouTubie).

2023-03-19_134735.thumb.png.da5836e7b6caaccfb3ea3680d43fbc20.png

Po tej operacji należy skonfigurować Timer (u mnie 2):
2.thumb.png.20e0284ebdb18a52ec5bd4735c99b639.png

3.thumb.png.3e2264061c09aed5b186cc5d4cf45ffa.png

 

Kod:

/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == PRZYCISK_Pin)
	{
		__HAL_TIM_SET_COUNTER(&htim2, 0x0000);
	}
}
int __io_putchar(int ch)
{
	if (ch == '\n')
	{
		__io_putchar('\r');
	}

	HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, HAL_MAX_DELAY);
	return 1;
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
/* USER CODE END 2 */

/* USER CODE BEGIN WHILE */
int16_t old_value = 0;
while (1)
{
  int16_t value = __HAL_TIM_GET_COUNTER(&htim2);
  if (value != old_value)
  {
    printf("Wartość = %lu\n", value);
    old_value = value;
  }
}
/* USER CODE END WHILE */

 

  • Lubię! 1
Link do komentarza
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!

Anonim
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...

Ważne informacje

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