roboforum.ru

Технический форум по робототехнике.

STM32F4 + MG995 = как подобрать ШИМ?

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 05 мар 2013, 19:45

Жди неделю или ветку перечитывай до просветления. Представляй себе робинзона, делающего зарубки на столбе. Как часто он делает зарубки, откуда он знает, что пора зарубку сделать, на сколько зарубок столба хватит, что будет, когда столб кончится

Re: STM32F4 + MG995 = как подобрать ШИМ?

Angel71 » 05 мар 2013, 20:41

сервоконтроллеру не имеет значения, к чему его подключают - плате с мегой, армом, компу или планшету. в этом ещё один плюс - начинаешь делать на компе, а допиливать можно на платке.
делал ssc32, хотя если бы сейчас делал, то наверно за основу взял бы местный or. в этот OR-AVR-M128-S вообще спокойно весь нужный код простенького хекса влезет. а что из покупного кроме or есть, понятия не имею.

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 07 мар 2013, 22:11

dccharacter
В общем я понял что значит этот пределитель и т. п.
Пределитель нужен в первую очередь для подстройки частоты таймера, что бы его заставить тикать в секунду в зависимости от этого предлителя.
На данный момент я сижу на таймере 4, который шарашет с частотой 84Mhz, т. е.
84000000 тиков в секунду. Я делю эти миллионы на 84000, тем самым говорю таймеру увеличевать свое значение каждую миллисекунду. Что бы не отлавливать пока таймер до тикает до 1000, я указываю в параметр период равным 1000, когда счетчик дотикает до 1000 (т.е. в секунду) у меня срабатывает прерывания, где и загорается деод.
Таким образом я заставил гореть деод раз в секунду.

Но как я правильно все рассказал? Если верить описанию, то я вроде правильно все понял.

А что дальше? Без осциллографа мне проблематично. Единственное надежда эта теория!

Angel71
У Нас в Алмате проблема с такими платами, можешь подсказать с eBay-я?



Нашел вот такую программку
http://www.st.com/st-web-ui/static/acti ... m32091.zip
И Описание к ней
http://www.st.com/st-web-ui/static/acti ... 039457.pdf

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 08 мар 2013, 08:20

Вроде все правильно ты понял
меня только смущает число 84000. Это ты в теории или в программе так делаешь? Потому что если в программе, то странно, что у тебя все работает, потому что прескейлер вроде как 16-ти битный. А значит не может быть больше 65535. Пойду посмотрю...

Добавлено спустя 10 минут 10 секунд:
http://www.st.com/st-web-ui/static/acti ... 031020.pdf
стр 422

16-bit programmable prescaler used to divide (also “on the fly”) the counter clock
frequency by any factor between 1 and 65536

Добавлено спустя 1 час 40 минут 55 секунд:
Код: Выделить всёРазвернуть
#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_tim.h>

#include <stm32f4xx_exti.h>
#include <misc.h>
#include <stm32f4xx_syscfg.h>


//__IO uint16_t SERVO_0 = 1000;      // 1000 us = 1 ms
//__IO uint16_t SERVO_180 = 2000;      // 2000 us = 2 ms
#define SERVO_180 3*2200l
#define SERVO_0 3*800l

// Функция устанавливает позицию вала (в градусах)
void set_pos(uint8_t pos)
{
  uint16_t tmp= (uint16_t)((SERVO_180 - SERVO_0) * pos / 180l) ;
  uint16_t ServoPulse = SERVO_0 + tmp;
  TIM_SetCompare1(TIM4, ServoPulse );
}

// Функция задержки
void delay(void)
{
  volatile uint32_t i;
  for (i=1; i != 0xFFFF; i++)
    ;
}


int main(void)
{
  SystemInit();

  // Инициализация портов вводов/вывода
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // Ножка PD12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(GPIOD, &GPIO_InitStructure);


  //------------------------------------------------------------------------------------------
  // Инициализируем таймер 4
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

#define sPeriod 20000l //20ms = 20000 us
#define tClock (SystemCoreClock/8) //21MHz
#define maxCount 60000l

  uint16_t Prescaler =  8; // PCLK1 = 168MHz/8 ~= 21MHz
  uint16_t Period = 60000; // 20000; // 20 ms

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;
  TIM_TimeBaseStructure.TIM_Period = Period;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  // Разрешаем таймеру обращаться к выходу PD12
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
  //------------------------------------------------------------------------------------------
  // Инициализируем ШИМ
  TIM_OCInitTypeDef TIM_OCInitStructure;
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 20000;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);
  TIM_Cmd(TIM4, ENABLE);



  //delay();
  //TIM_SetCompare1(TIM4, 460); // 90
  //delay();
  //TIM_SetCompare1(TIM4, 760 ); // 180



  //Начинаем крутить сервой от 0 до 180 градусов.

  uint8_t i;
  while(1)
  {
    for (i=0;i<=180;i++)
    {
      delay();
      set_pos(i);
    }
    for (i=180;i>0;i--)
    {
      delay();
      set_pos(i);
    }
  }
}

Серва крутится туда-сюда, импульс меняется от 800 до 2200 мкс.
Единственная ошибка в моих объяснениях была в том, что к рассчетному прескейлеру надо единицу добавлять. Чо-то спросоня не пойму почему, но с единицей тайминги правильные.

Камень работает на 168МГц
Таймер на частоте PCLK1, т.е. 168/8 = 21МГц
С прескейлером 8 получается частота 3МГц.
Поэтому SERVO0 и SERVO180 = это утроенное количество микросекунд, т.е. 3*800 и 3*2200

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 09:01

Вот код который работает... один раз моргает в секунду деод.
Странно почему у тебя на таймере 4, камень шарашет на 168Mhz? У меня на 84MHz
Может настройки мне поменять где то?
В даташите на странице 104 указано, что шина 1 работает на частоте 84Mhz, и таймеры перечислены... TIM2,TIM3,TIM4,TIM5,...


Код: Выделить всёРазвернуть
#include <stm32f4xx.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_tim.h>

//#include <stm32f4xx_exti.h>
#include <misc.h>
//#include <stm32f4xx_syscfg.h>

#undef HSE_VALUE
#define HSE_VALUE    ((uint32_t)8000000)

__IO uint16_t SERVO_0 = 570;      // 1000 us = 1 ms 570
__IO uint16_t SERVO_90 = 1000;      // 1000 us = 1 ms 1140
__IO uint16_t SERVO_180 = 2000;      // 2000 us = 2 ms
//#define SERVO_180 1200
//#define SERVO_0 200


// Функция устанавливает позицию вала (в градусах)
void set_pos(uint8_t pos)
{
  uint32_t tmp=(SERVO_180 - SERVO_0) / 180 ;
  uint16_t ServoPulse = SERVO_0 + tmp * pos;
  TIM_SetCompare1(TIM1, ServoPulse );
  //TIM2->CCR2 = SERVO_0 + tmp * pos;
}

// Функция задержки
void delay(void)
{
  volatile uint32_t i;
  for (i=1; i != 0xFFFF; i++)
    ;
}

void delayMS(uint32_t ms)
{
    ms *= 3360;
    while(ms--) {  __NOP(); }
}

int main(void)
{
  SystemInit();

  // Инициализация портов вводов/вывода
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // Ножка PD12
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_Init(GPIOD, &GPIO_InitStructure);


  //------------------------------------------------------------------------------------------
  // Инициализируем таймер 4
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  uint16_t Prescaler =  ( (SystemCoreClock / 2) / 1000000) - 1; // 1hz
  uint16_t Period = 20000; // 20000; // 20 ms

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_TimeBaseStructInit (&TIM_TimeBaseStructure);
  //TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;
  //TIM_TimeBaseStructure.TIM_Period = Period;
  TIM_TimeBaseStructure.TIM_Prescaler = 84000 -1;
  TIM_TimeBaseStructure.TIM_Period = 1000;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  // Разрешаем таймеру обращаться к выходу PD12
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
  //------------------------------------------------------------------------------------------
  // Инициализируем ШИМ
  TIM_OCInitTypeDef TIM_OCInitStructure;
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//  TIM_OCInitStructure.TIM_Pulse = 0;
//490 + ((1000-490) / 90) * 45; // 0=490, 45=690, 90=940
//200 + ((1140-200) / 180) * 90; // 200=0,
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);

  TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC1, ENABLE);

  TIM_Cmd(TIM4, ENABLE);

  NVIC_EnableIRQ(TIM4_IRQn);

  //delayMS(20);
  //TIM_SetCompare1(TIM4, 1000); // 90
  //delayMS(20);
  //TIM_SetCompare1(TIM4, 1500); // 90
  //delayMS(20);
  //TIM_SetCompare1(TIM4, SERVO_180 ); // 180
  //delayMS(20);


   while (1);
}





volatile uint8_t servo_angle = 0;

void TIM4_IRQHandler(void)
{
     /* Если счётчик переполнился, можно смело закидывать
        в регистр сравнения новое значение. */
     if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
     {
       TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
       TIM_SetCompare1(TIM4, 500);
     }
}

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 08 мар 2013, 10:24

Возьми мой код сначала и попробуй

Добавлено спустя 21 минуту 58 секунд:
Клоки задаются функцией SetSysClock(void)
Это в файле system_stm32f4xx.c (библиотека CMSIS)

Вот регистры:
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

Что странно, потому что таймеры сидят на PCLK1, дивайдер 4, т.е. должно быть 42МHz: 168/4
Т.е. еще где-то сидит дивайдер 1/2
Пока не нашел его

Добавлено спустя 2 минуты 3 секунды:
http://www.st.com/web/en/catalog/tools/PF257927
STSW-STM32091 Clock configuration tool for STM32F40x/41x microcontrollers

Добавлено спустя 14 минут 17 секунд:
Картинка называется "взорви себе мозг"
Вложения
STM32F4clocks.png
STM32F4clocks.png (16.27 КиБ) Просмотров: 2808

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 11:09

Страно но твой код постоянно возвращает ошибку
все закоментировал, компилиться нормально. Иначе нет.

[cc]
[cc] collect2.exe: error: ld returned 1 exit status
BUILD FAILED

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 08 мар 2013, 11:20

Мой код - это модификация трех строчек твоего кода. Посмотри, что изменилось, поправь у себя, и вперед.

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 11:26

Обновил проект, вроде все заработало
Решение проблемы здесь
http://forum.easyelectronics.ru/viewtop ... 35&t=11896

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 08 мар 2013, 11:27

Ну а что "все"-то заработало? Серва крутится?

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 11:41

Работает классно, но крутится только на 100 градусов
Хотя серва позволяет крутится от ~-30 до 200 градусов
А как эти сервы калибрировать?

Добавлено спустя 11 минут 5 секунд:
Взял вот такой тестер
http://rcshop.kz/product/2996/
Но крутит только на 90 градусов. Думаю им калибрировать.

Re: STM32F4 + MG995 = как подобрать ШИМ?

dccharacter » 08 мар 2013, 12:00

Ну ты можешь поиграться с таймингами, т.е. с 800 и с 2200. Меняй только потихоньку, не давай серве в клин на краю уходить. МГ мож и выдержит, а маленькая пластмассовая серва порвется мгновенно, не успеешь даже напругу с нее снять.
Калибровку можно делать по транспартиру, не нужен для этого тестер за 810 таньге :-))))

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 12:06

Неее я не про это, я вот использую этот серво тестер, он крутит с 30 если регулировку поставить на 0. Но до левого края ещё есть 30 градусов. Вот как это понимать?

Конечно тебе отдельное спасибо! Конечно мне нужно ещё подумать над твоими изменениями.

Re: STM32F4 + MG995 = как подобрать ШИМ?

Duhas » 08 мар 2013, 16:39

свободный ход сервы обычно больше управляемого хода.

Re: STM32F4 + MG995 = как подобрать ШИМ?

Askar » 08 мар 2013, 17:02

Я так понимаю под каждую серву придется отдельно ввести подачу импульсов?


Rambler\'s Top100 Mail.ru counter