Создание собственной системы стабилизации

SergDoc

Мысли над регулятором:
как известно повсеместно используется ПИД (думаю распространяться не стоит?)
а не заменить ли его на регулятор с одним параметром?
U = K*(angle + vel*dt1) только dt1 - не время цикла, а время между считыванием скорости с датчика и подачей данных в регулятор… грубо обнуляем dt1 при чтении и смотрим в него в момент расчёта регулятора…
дело в том, что D и I в ПИДе не что иное как коррекция ошибки пропорции, так как за время между считыванием данных с датчика и поступления их в расчёт ошибка накапливается - тупо на старых данных регулятор строим, а тут его слегка предсказали…
Что даёт? Офигенный плюс к карме Дринкеру с крутилками, их всего 3 ))) ну и как следствие меньше настроек?

VitaliyRU
SergDoc:

U = K*(angle + vel*dt1)

Это аналог PI. С настройкой(К) вынесенной за скобки. Без D будет расколбас при прочиъ равных и не раздельно P и I настраивать тоже не очень. Как то так КМК…
ЗЫ PID и то слишком примитвный, там не упрощать а усложнять надо, но с этой гребанной работой все лень/некогда 😦(

SergDoc

Не согласен - D мы как раз берём от скорости, а для чего, а именно для того, что P с течением времени (то что я обозначил dt1) рассчитывается неправильно, в идеале P мы получаем чуть меньше чем должно быть ибо угол уже уплыл и с каждой интерацией это всё больше и больше. И делаем мы что? - Увеличиваем P (коэффициентом) - переруливает, плохо 😦 о - берём D и им тормозим P - опять попандос, опять недоруливаем - давайте I введём - дабы дожимало - 3 параметра для шаманства вместо вычисления правильного показателя один раз?
тут как бэ слов мало тут делать и смотреть надо 😃

VitaliyRU:

Это аналог PI. С настройкой(К) вынесенной за скобки. Без D будет расколбас

КУК прекрасно переносит )))

VitaliyRU
SergDoc:

берём D и им тормозим P - опять попандос

С D мат модель чуть ближе к физической. То что D тормозит P(когда скорость и ускорение в разные стороны направлены) наоборот хорошо. Но все равно далеко от иделала. На разные возмущающие воздействия(по переданному импульсу) нужны разные PD. Ну и PID при слабых воздействиях толком не работает(в т.ч. по описанной выше причине) от этого коптер так на подушке ерзает и в ветер раскачиваться…
вот на такой хрени
реакция нужна как у кошки что бы в дверной проем пролететь по ФПВ 😃. Ветер от собственных винтов…
ЗЫ c Вашим dt я если честно идею не уловил…

SergDoc:

КУК прекрасно переносит )))

Если сравнивать с автомобильными подвесками то это начало прошлого века. Обычный амортизатор трения. А если посмотреть на WRC… то небо и земля. Причем сейчас на дорогих версиях серийных машин амортизаторы(типа бнв эмок, мерсов ML и прочих ауди РС и ипрез врыкс) по скожей технологии сделаны. Однотрубные с газом высокого давления 😃) Они позволяют юолее правильную регрессивную характеристику выдерживать.

SergDoc
VitaliyRU:

ЗЫ c Вашим dt я если честно идею не уловил…

идея дожать пропорцию до реальной (в момент расчёта регулятора)

VitaliyRU
SergDoc:

идея дожать пропорцию до реальной (в момент расчёта регулятора)

Ааа, перечитал еще раз - дошло 😃 Это все блохи не имеющие ни какого принципиального значения P и i то эмпирические были. И сами эти коэф. зависят от соотношения момента инерции к моменту от моторов грубо помноженное на приемистость моторов. Т.е. определяющем являеться не как скорость мерить, а физические параметры коптера. И вообще чем больше настроек тем лучше 😃) не ? 😃)

mataor
VitaliyRU:

ComPort это какой unit в Delphi?

угу, могу поделится если надо

oleg70
SergDoc:

только dt1 - не время цикла, а время между считыванием скорости с датчика и подачей данных в регулятор…

А разве это не одно и тоже ?? (по другому то как ?)

SergDoc:

Офигенный плюс к карме Дринкеру с крутилками, их всего 3

Для самолета вообще можно обойтись одной “П” - составляющей… (проверено), вполне сносно летает, но как и следовало ожидать угол крена/тангажа выдерживается с ошибкой, поэтому я все же “усложнил 😃” и добавил таки “И” “Д”.
А для коптера такое “кастрирование” выйдет боком однозначно…

Придумать бы метод оценки коэфициентов ПИДа в зависимости от реакции аппарата на возмущение (!)… т.е. как нибуть замерять их оптимальность… тогда можно было бы просто сделать “автокоррекцию” и вообще забыть про крутилки, но пока че то не могу…

fpv_mutant

Подскажите по ws2812…у меня есть 1 метр,есть ардуина мини…прошивка на апм 3,1,5
Чего я хочу? на каждый из четырех лучей прилепить по 8 диодов ws2812 и моргать предупреждениями АПМа и +свои эффекты.

SergDoc

Кто-нибудь MPU9250 в живую видел? Чёт мне приехали с какой-то маркировкой MP92 и без надписи iventsense?

omegapraim
SergDoc:

Кто-нибудь MPU9250 в живую видел? Чёт мне приехали с какой-то маркировкой MP92 и без надписи iventsense?

Тута походу честный магаз вот там картинка есть www.csgshop.com/product.php?id_product=169

strizhmax
SergDoc:

Чёт мне приехали с какой-то маркировкой MP92

Все верно, табличку на 40й странице даташИта посмотри.

oleg70

Пока экспериментировал со своей платой стабилизации, заметил “интересный” момент: не все ESC хотят работать с 3.3v PWM…, даже хваленые типа “турнига плюс”… (??). Самое интересное, по принципиальной схеме, PWM подается на ногу прерывания Атмеги, т.е. работать должно легко и везде, но не тут то было… “гугление” этого вопроса внятных ответов не дало…
Кто нибуть сталкивался с этим ?

SergDoc

На плющах всю жизнь - всё прекрасно, вопрос на какой частоте и перешиты ли регули, с родной прошивкой работают нормально до 300 гц

oleg70
SergDoc:

плющах всю жизнь - всё прекрасно

У меня вот “плющ” 25А не прошитый и с нормальной (50Гц) частотой не работает… и не только он, буквально перебирал из запасов разные марки и на разный ампераж (выбор есть), нормально работают SuperSimple, получается что если делать коммерческий продукт, то преобразователь надо ставить на плату… (не понятно только почему, сигнал подается на дискретную ногу INT0, даже при 5в питании, 3.3в железно “единица”)

strizhmax

А на выходе точно PWM? Осцил или логический анализатор воткнуть и посмотреть.

SergDoc
oleg70:

даже при 5в питании, 3.3в железно “единица”)

Ну как бы давно летаем - никогда не было проблем…
Open Pilot (всех мастей), vr brain, Naze32, Multipilot, AeroQad, AutoQad, у меня пачка различных контроллеров, rual, Drinker, Siberian, Mahowik, VisAsta… ни у кого проблем не было… (PX4 и их производные не берём - там есть преобразователи уровня)
Ищите непропай или проблему в коде… предделители на таймеры правильно выставлены, а то я раз на 800Гц вместо 400Гц запустил 1-й и 8-й таймеры…

oleg70:

У меня вот “плющ” 25А не прошитый и с нормальной (50Гц) частотой не работает… и не только он

Так - а по потреблению 5В что? ибо я описывал глюки плющей при перегреве - где-то “ESC ликбез” что-ли нестабильно начинают работать, они на внутреннем rc генераторе…

Drinker
oleg70:

тогда можно было бы просто сделать “автокоррекцию” и вообще забыть про крутилки, но пока че то не могу…

Есть такой метод “релейный” автонастройки ПИД регулятора. Довольно прост, но все руки не дойдут до опробывания.

oleg70
SergDoc:

я описывал глюки плющей

Эксперимент ставил “чистый” - моя плата и китайский сервотестер, чатота/длительность/вольтаж все проверенно осциллографом… Как, а главное чем (?), ESC “чует” пониженный уровень не понятно… Если всеж следовать здравому смыслу, то дело скорей не в размахе ШИМ, а в его временнОм возникновении при старте…
Как говорится “ничего не понятно но результат налицо”, причем плющей таких у меня два одинаковых и одинаково не работающих…

SergDoc

Инициализацию таймеров - код можно?

oleg70
SergDoc:

Инициализацию таймеров - код можно?

Вот: (частота проца у меня 160 Мгц)

//PWM output SETUP ============================================================
//=============================================================================
//=============================================================================
//=============================================================================

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  // GPIOC Configuration:
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 ;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP ;
  GPIO_Init(GPIOC, &GPIO_InitStruct);

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP ;
  GPIO_Init(GPIOD, &GPIO_InitStruct);

  /* Connect TIM3 pins to AF2 */
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3);

    /* Connect TIM4 pins to AF2 */
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4);


  /* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 15000;
TIM_TimeBaseStructure.TIM_Prescaler = 80;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = 15000;
TIM_TimeBaseStructure.TIM_Prescaler = 80;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

// OUT TIM3========================================
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM3, &TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC4Init(TIM3, &TIM_OCInitStructure);

TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

// OUT TIM4========================================
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM4, &TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM4, &TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC4Init(TIM4, &TIM_OCInitStructure);

TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);


    TIM_ARRPreloadConfig(TIM3, ENABLE);
    TIM_ARRPreloadConfig(TIM4, ENABLE);


    /* TIM3 enable counter */
    TIM_Cmd(TIM3, ENABLE);
    TIM_Cmd(TIM4, ENABLE);