Skocz do zawartości

PrimeSoul

Użytkownicy
  • Zawartość

    34
  • Rejestracja

  • Ostatnio

Reputacja

5 Neutralna

O PrimeSoul

  • Ranga
    3/10

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Września
  • Zainteresowania
    Programowanie C/C++, Sport, Robotyka, Film
  • Zawód
    technik elektronik
  1. @Zealota Oj sorki, mój błąd przy spakowaniu plików. Zaraz poprawię. UPDATE: Teraz załącznik powinien już zawierać wszystkie pliki projektowe.
  2. Cześć wszystkim, Walczę co nieco z serwonapędami na płytce Discovery z STM32F407VG na pokładzie (stary model, z programatorem poprzedniej generacji). Sprawa wygląda tak, że mam serwo wieloobrotowe z enkoderem w postaci czujnika szczelinowego i tarczy (sygnał dubluję 3 razy, na razie tylko do testów, później każdy kanał sterowany będzie oddzielnie). Dokładność pozycjonowania taka sobie, ale do potrzeb projektu wystarcza. Kwestia jest taka, że serwo poruszać się ma wg wyliczonej prędkości z regulatora (jeszcze nie zaimplementowany, dopiero w planach) w przerwaniu od timera systemowego. Wartość aktualnego sterowania serwem będzie zapisywana do zmiennej globalnej. No i teraz kluczowa sprawa - chciałbym, żeby timer, na którym jest sterowane to serwo, samoczynnie zmieniał swoje wypełnienie na wartość zmiennej globalnej z obliczonym sterowaniem. Idealnym rozwiązaniem moim skromnym zdaniem byłoby użycie DMA w kierunku Memory -> Peripheral w trybie kołowym (half-word). Niestety, całość nie chce zadziałać - startuje tylko pierwszy kanał timera i w dodatku z ustawieniem domyślnym, nie zmienia swojego wypełnienia przy zmianach zmiennej przypisanej do kanału w DMA, a pozostałe nawet nie startują z domyślnymi wartościami. W załączniku wrzuciłem okrojony tylko do tej kwestii projekt testowy i projekt z CubeMXa. Poniżej kod main'a: /* Private variables ---------------------------------------------------------*/ TIM_HandleTypeDef htim4; DMA_HandleTypeDef hdma_tim4_ch2; DMA_HandleTypeDef hdma_tim4_ch1; DMA_HandleTypeDef hdma_tim4_ch3; /* USER CODE BEGIN PV */ volatile uint16_t PwmPulse = 199; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_TIM4_Init(void); static void MX_DMA_Init(void); /* USER CODE BEGIN PFP */ (...) int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM4_Init(); MX_DMA_Init(); /* USER CODE BEGIN 2 */ // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); // TIM4->CCR1 = PwmPulse; // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); // TIM4->CCR2 = PwmPulse; // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); // TIM4->CCR3 = PwmPulse; // HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4); // TIM4->CCR4 = PwmPulse; HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t*)&PwmPulse, 1); HAL_Delay(100); HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_2, (uint32_t*)&PwmPulse, 1); HAL_Delay(100); HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_3, (uint32_t*)&PwmPulse, 1); HAL_Delay(100); //HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_2, (uint32_t*)&PwmPulse, sizeof(PwmPulse)/2); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // TIM4->CCR2 = PwmPulse; // HAL_Delay(100); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } Zakomentowana frakcja kodu bez DMA działa bez problemu i generalnie jest to awaryjna opcja, której użyję, jeśli nic z DMA nie uda mi się sensownego wypracować. No i jeszcze wygenerowane z CubeMXa funkcje konfiguracyjne dla timera i DMA: static void MX_TIM4_Init(void) { /* USER CODE BEGIN TIM4_Init 0 */ /* USER CODE END TIM4_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; /* USER CODE BEGIN TIM4_Init 1 */ /* USER CODE END TIM4_Init 1 */ htim4.Instance = TIM4; htim4.Init.Prescaler = 839; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 1999; htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim4) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 99; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } sConfigOC.Pulse = 189; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sConfigOC.Pulse = 199; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } sConfigOC.Pulse = 0; if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM4_Init 2 */ /* USER CODE END TIM4_Init 2 */ HAL_TIM_MspPostInit(&htim4); } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Stream0_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /* DMA1_Stream3_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn); /* DMA1_Stream7_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn); } Podobny problem miałem też wcześniej, gdy rozwiązywałem zadania z kursu STM32, ale tam była to kwestia złej kierunkowości w DMA, tutaj ją sprawdziłem w Cube'ie chyba z 3 razy. Będę baaaardzo wdzięczny za wszelką pomoc w tym zakresie, przejrzenie kodu / projektu. Środowisko: SW4STM32 + STM32CubeMX Pozdrawiam Wrk_03_SERVO_LIB.zip
  3. Chyba 10k... Wziąłem pierwszy z brzegu, a teraz już nie pamiętam, bo układ musiałem rozmontować. Ale na pewno było to coś względnie dużego, bo dioda przy tym rezystorze świeciła szczątkowo. @RFM Tego nie wiedziałem, muszę poczytać na ten temat z czystej ciekawości .
  4. Co do sterowania - tak, 3V z STMa działa też bez zarzutu. Konwerter jest mi niepotrzebny do wysterowania tym serwem, co sprawdziłem zaraz po odkryciu tego fenomenu. Ciekaw jestem tylko, dlaczego i w jaki sposób pojawia się 3V amplituda za konwerterem, gdzie nominalnie powinno być 5V, tak jak na rezystorze. Jakąś diodką to ściąga w dół czy co? Dlatego traktuję to jako zagadkę w dziale "inne", bo jeśli chodzi o użycie to idzie względnie gładko
  5. W nocie katalogowej SG90, którą znalazłem. Link here. Ze zdjęcia to to samo, co mam na biurku (choć ten model to u mnie leży już od lat, nawet nie wiem skąd go wziąłem już).
  6. Cześć wszystkim, Mam pewną kwestię do omówienia, która mnie mocno zaciekawiła. Posiadam oryginalne serwo Tower SG90 i steruję nim z STM32F4 (z kursu). Standard napięciowy STMa to 3V, dla serwo wg specyfikacji wygoglowanej 5V, przy czym dotyczy to także sygnału sterującego. Z tego powodu łączę wyjście PWM z STMa do konwertera napięć i po drugiej stronie wlatuje wejście sterujące SG90. Zasilania 3V i 5V mają wspólną masę, przy czym serwo ciągnie prąd z zasilacza, a płytka po USB. I teraz zagadka: pomierzyłem na oscyloskopie przebiegi po obu stronach konwertera i na obu amplituda jest ... 3V. Z ciekawości odłączyłem serwo i podłączyłem rezystor - amplituda 5V, PWM pod względem czasowym bez zmian. Co tu się dzieje w tym układzie, bo mnie zamurowało? Pozdrawiam
  7. A tak swoją drogą, to nie widziałem, żeby ktoś wypisał odpowiedź na pytanie na końcu odcinka kursu, więc dla ciekawych (którzy odpowiedzi nie znali) wrzucam poniżej zrzut z manuala, który to wyjaśnia chyba dość preceyzyjnie.
  8. @Elvis, właśnie miałem pisać. Problem DMA rozwiązałem. Oczywiście moja własna głupota okazała się przyczyną. Podczas pierwszego testu nie używałem jednego kanału, a wszystkie 4 i 3 zdefiniowałem sobie na DMA. Okazało się, że tylko 1 ze zdefiniowanych przez DMA kanałów określiłem jako MemtoPeriph, a w pozostałych zapomniałem tego zrobić. A jak później testowałem, to konfiguracja robiona była w stanie lekkiego zdenerwowania i z głupoty... powieliłem ten sam błąd, tym razem już tylko przy 1 kanale. Ech, wstyd mi przed samym sobą. Dzięki za zaangażowanie wszystkim.
  9. @Treker Nie próbowałem żadnym narzędziem, bo takich w sumie nigdy nie używałem i żadnego z nich nie znam. Natomiast jak przeglądałem pliki samemu, to na pewno różnice widziałem, choćby wspomniany wyżej SYSTICK_Callback był inaczej zrobiony i wcale nie było to przypadkowe wg deweloperów ST. Fajnie byłoby jakby ktoś bardziej doświadczony ode mnie w STMach spróbował na najnowszym CubeMXie postawić taki PWM sterowany przez DMA, bo może widziałby więcej niż ja w kwestii jakichś nieprawidłowości itp.
  10. Mam jeszcze jedną kwestię do tego odcinka poradnika. Chodzi mi konkretnie o przykład z wygenerowaniem PWM przez DMA zamiast przekazania wypełnienia bezpośrednio do rejestru. Ostatnim razem to zostawiłem, bo nie chciało działać. Przeznaczyłem dzisiaj chyba z 4 h na szukanie rozwiązania i dalej się nie udało. Rzecz w tym, że robię krok po kroku wszystko jak w poleceniach i nie generuje mi PWMa na diodzie. Próbowałem wykonać diagnostykę i jedyne, co zdołałem wynaleźć, to kod błędu "1", czyli "Transfer error", na kanale DMA (przez STMStudio). Najlepsze jest to, że jak wrzucę projekt z paczki to działa. Ale jak skopiuję całego maina (który swoją drogą wygląda u mnie identycznie w części pisanej przez użytkownika) z działającego projektu do mojego, to znowu nie generuje PWM. Wnioskuję po tym, że problem leży gdzieś w plikach wygenerowanych przez CubeMXa i to nawet nie przez błędy w konfiguracji, bo sama konfiguracja w tym przypadku ograniczała się do ustawień, które potem zostały przepisane do funkcji konfigurujących poniżej maina. No i żeby była jasność, wersja bez DMA, a z wpisem bezpośrednio do rejestru timera działa. Zna ktoś może rozwiązanie tego problemu?
  11. Cześć, Co do tej części kursu, to znalazłem moim skromnym zdaniem ogromny babol w pierwszym programistycznym przykładzie, ale niekoniecznie związany z autorstwem kursu, a raczej CubeMXem. Niestety, użycie przerwania od timera systemowego jest niemożliwe w aktualnej wersji bibliotek generowanych w CubeMXie. Tu można znaleźć dyskusję na ten temat i jednocześnie sposób rozwiązania problemu (dodanie jednej linii kodu w pliku wygenerowanym przez Cube'a). Co ciekawe, z tego pomysłu ST, który rzekomo bug'iem nie jest, niezadowolonych jest baaaardzo wielu użytkowników CubeMXa ;D. I choć trochę deweloperzy ST w tym racji mają moim zdaniem, to jednak aż tak drastyczne kroki nie są na pewno mile widziane zwłaszcza w firmach pracujących na STMach. Pozdrawiam
  12. Z moich uwag, poza tym, co wcześniej opisał Elvis odnośnie końca linii i buforowania, to dorzuciłbym problematyczne działanie przykładu z 10 znakami w buforze. Na moim kompie RealTerm wyrzucał krzaczki na końcu stringa (w sensie 10 znaków normalnie i potem jakieś randomy). Wydaje mi się, że wynikało to z faktu braku zamknięcia tablicy znakiem '\0' (10-znakowy bufor i 10 znaków zapisanych). Jak uzupełniłem ten znak na dodanym przeze mnie 11. miejscu problem zniknął i wypisywanie odbywało się normalnie.
  13. Cześć, Natrafiłem na identyczny problem jak koledzy wyżej, tj. przy korzystaniu z plug-in'u CubeMX'a do ac6 nie da się ustawić taktowania z HSE. Po wpisaniu do pola HSE 8, konwertuje liczbę na 8 Hz, tzn. 0.00..8. Jak wpisać 8 000 000, wtedy akceptuje wartość jako 8 MHz tylko po to, by po przejściu do innej karty lub kliknięciu innego pola od razu skonwertować powrotnie na 8 Hz. Przy czym problem jest o tyle gorszy, że po reinstallu nic się nie zmieniło, dalej plug-in zachowuje się tak samo. Korzystanie z zewnętrznego CubeMX'a rozwiązuje problem, ale jest dosyć... upierdliwe, bo za każdym razem muszę ręcznie ścieżki zmieniać, a przy plug-in'ie szło to z automatu. Da się coś z tym zrobić? Dodam, że plug-in najnowszy, ściągnięty ze strony ST. EDIT: Cofam to, co pisałem o zewnętrznym CubeMX'ie. Owszem, można tam ustawić zegar, ale z kolei wyrzuca błąd przy generowaniu projektu. Więc problem zaczyna być bardzo uciążliwy. EDIT2: Ok. Problem z CubeMX'em zewnętrznym rozwiązany. Nie pasował mu polski znak w ścieżce (cóż, taki użytkownik... ). Pozostaje więc jedynie kwestia plug-in'u. Pozdrawiam
  14. Yup, dokładnie tego samego. Nawet system mam Win10, choć początkowo planowałem zrobić kurs na Ubuntu. Dzisiaj w wolnej chwili spróbuję zrobić reinstalację wszystkiego, co wczoraj wgrywałem. Informacja, jaka może być jeszcze przydatna, to fakt, że korzystałem z czystego Eclipse z dwoma plug-in'ami (System Workbench + CubeMX), zamiast gotowego, skonfigurowanego Eclipse'a ze strony ST. Dzisiaj zamierzam zrobić podejście już na gotowcu + Cube'a jako oddzielny program, może tym razem pójdzie bez problemów. EDIT: Jak powiedziałem, tak zrobiłem. I tym razem działa. Szkoda, bo liczyłem na to, że będę miał jednego Eclipse'a skonfigurowanego zarówno pod STMy i AVRy, ale nie jest źle, można przeżyć. EDIT2: Kolejny problem - po wgraniu pierwszego programu, następne wgrywania są ... puste. Mam namyśli, że gdy już wygeneruję plik *.hex (a generowałem ich mnóstwo), to potem wrzucam go do ST-linka i startuję programming. Czas wgrywania trwa 0s 0ms, a zachowanie STMa się nie zmienia, tzn. działa tak, jakby program nie został wczytany na mikrokontroler. "Erase chip" z ST-linka zadziałał i usunął poprzedni program, ale to też nie pomogło przy wgrywaniu nowego. Ktoś coś wie na ten temat? EDIT3: Problem z edit 2 leży w CubeMXie. Przeczesałem komentarze wcześniejsze i zasugerowany nimi spróbowałem zrobić od nowa konfigurację sprzętową. Zadziałało od razu. No i każda edycja kodu daje radę do momentu, gdy próbuję zmienić cokolwiek w projekcie w CubeMXie. Jest na to jakaś recepta czy trzeba się z tym męczyć?
  15. Cześć, Mam problem przy kompilacji pierwszego programu. W konsoli po kliknięciu na builda wyświetla mi błąd "make: *** No rule to make target `clean'. Stop.". Zdążyłem po necie już popatrzeć, że to potencjalnie może być problem z brakiem lub błędami w makefile'u. Coś ktoś wie jak to rozwiązać? EDIT: Po rozwinięciu okna błędu do detali pojawia się jeszcze komunikat "Invalid thread access".
×
×
  • Utwórz nowe...