Answer the question
In order to leave comments, you need to log in
Why is the servo buggy in FreeRTOS?
I'm just starting to switch to STM after AVR
. Also, my first experience with preemptive RTOS, before that I used only cooperative ones.
Example from here
When trying to build a servo into an RTOS, the servo starts to go crazy
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "FreeRTOS.h" // Подключаем FreeRTOS
#include "task.h" // Переключение задач
// Функция устанавливает позицию вала (в градусах)
#define SERVO_180 8200
#define SERVO_0 1800
void set_pos(uint8_t pos) {
uint32_t tmp = (SERVO_180 - SERVO_0) / 180;
TIM2->CCR2 = SERVO_0 + tmp * pos;
}
// Крутим сервопривод
void servo_task(void *pvParameters) {
uint8_t i;
while(1) {
for(i = 0; i <= 180; i += 10) {
vTaskDelay(10);
set_pos(i);
}
}
}
// Мигаем светодиодом
void led_task(void *pvParameters) {
while(1) {
GPIOC->ODR |= (GPIO_Pin_8);
vTaskDelay(1000);
GPIOC->ODR &= ~(GPIO_Pin_8);
vTaskDelay(1000);
}
}
int main(void) {
// Настраиваем порт A
GPIO_InitTypeDef PORT_A;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Тактируем
PORT_A.GPIO_Pin = (GPIO_Pin_1);
PORT_A.GPIO_Mode = GPIO_Mode_AF_PP; // Будем использовать альтернативный режим, а не обычный GPIO
PORT_A.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &PORT_A);
// Настраиваем порт С
GPIO_InitTypeDef PORT_C;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
PORT_C.GPIO_Pin = (GPIO_Pin_9 | GPIO_Pin_8);
PORT_C.GPIO_Mode = GPIO_Mode_Out_PP;
PORT_C.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &PORT_C);
// Настраиваем таймер таймер 2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // Тактируем
TIM2->CCER |= (TIM_CCER_CC2E); // Разрешаем таймеру использовать ногу PA1 для ШИМа
TIM2->CCMR1 |= (TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2);
TIM2->PSC = 6; // Настраиваем предделитель, чтобы частота ШИМа была в районе 50 Гц
TIM2->CR1 |= TIM_CR1_CEN; // Запускаем
// Создаем задачи для ОС
xTaskCreate(servo_task, (signed char*)"servo", configMINIMAL_STACK_SIZE, NULL, 2, (xTaskHandle*)NULL);
xTaskCreate(led_task, (signed char*)"led", configMINIMAL_STACK_SIZE, NULL, 2, (xTaskHandle*)NULL);
// Пинаем планировщик
vTaskStartScheduler();
};
Answer the question
In order to leave comments, you need to log in
#define SERVO_180 8200 #define SERVO_0 1800 void set_pos(uint8_t pos) { uint32_t tmp = (SERVO_180 - SERVO_0) / 180; TIM2->CCR2 = SERVO_0 + tmp * pos; }
uint32_t tmp = ((SERVO_180 - SERVO_0) * pos) / 180 + SERVO_0;
TIM2->CCR2 = tmp;
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question