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

oleg70

Да, следующий проект надо делать “все на одной плате”, а то вот что придется упихивать (кроме телевизора:)) в модель:

теперь, с этой доской надо ездить в машине, и проверять работу софта…

SergDoc

Прикольно, Сергей, тут не та тема, в своей ответь на какой гире так было.

и на муратовских и на ЛСМ, и взлёт только на гирах , нааамного лучше (ровнее плавнее) можно мягко стартовать 😃
в том кино полёт чисто на одних гирах, правда я ещё пультом перед камерой махал, а аппарат никуда не девался - висел, но в само кино это не попало… пересоберу контроллер покажу акро (Вий в нём стабильнее чем КУК)… по сей причине и говорю, что в помещении без ветра вполне можно было и без акселя кино сляпать… или на худой конец задушить его до каких 0.2 Гц полетел бы только так и с вибрациями…

mahowik

Подтверждаю )) на гирах без корекциии можно висеть более минуты… пробовал itg3205 и mpu6050…

Gapey
SergDoc:

ну это на верхней плате текущего контроллера, вот думаю, пока не делал её - не заменить ли microSD (она как-то и не актуальна для логов хватит и флеши на плате) на приёмо-передатчик, что работает по SPI? ну например маленький RFM22B

несоветую ставить передающий модуль на одной плате с GPS приемником , даже если антенны будет вынесены далеко от платы …

  • написать нормально работающую в наших условиях радиосистему это отдельная довольно сложная задача … надеюсЪ опенпилоты доведут доума свой OPLink , тогда можно будет использовать его …
SergDoc

А на какой частоте интересно он работает? если не ошибаюсь он на f103-м собран… ага 433… и что же у него с другой стороны платы спрятано? гы-гы тот самый RFM22B…

Alexey_1811

Народ. Кто то разбирался в протоколе mavlink. Хочу переделать ОСД под данный протокол для Ардукоптер. Смотрел готовые библиотеки и нифига не догоняю. Как то там все через опу.

DVE

Так если все данные уже читаются, их можно и не трогать, в MinimOSD непосредственно вывод смотрите в OSD_Panels.ino, функция writePanels(), можете поменять под себя как угодно.

Alexey_1811

У меня OSD своя. Раньше стояла на мультиви, а теперь хочу переделать на ардукоптер.

rual
Gapey:

несоветую ставить передающий модуль на одной плате с GPS приемником , даже если антенны будет вынесены далеко от платы …

Есть противопоказания? Хочется всё в одном и компактно, а если нельзя то и смысла нет

Gapey:

написать нормально работающую в наших условиях радиосистему это отдельная довольно сложная задача

Для начала придлагал стянуть готовый РЧ-модуль с модема 3ДР, со встроенным ПО, своё пока не досуг.

Gapey
rual:

Есть противопоказания? Хочется всё в одном и компактно, а если нельзя то и смысла нет

ну все на одной плате тоже нехорошо …
противопоказания : любой передающий модуль это источник электромагнитных помех который нужно ставить какможно дальше от приемника и антенны навигации …
видеале GPS и компас выносить на отдельную плату и поднимать какможно выше…

rual:

Для начала придлагал стянуть готовый РЧ-модуль с модема 3ДР, со встроенным ПО, своё пока не досуг.

ну так у 3ДР не RFM22 а HM-TRP модули … там трансивер и проц в одном флаконе , но в прошивке только rs232 , а интересно так чтобы шла нетолько телеметрия но и управление по тому-же каналу …
как вариант можно слона переразвести под свои нужды …

SergDoc
Gapey:

противопоказания : любой передающий модуль это источник электромагнитных помех который нужно ставить какможно дальше от приемника и антенны навигации …

ну, например, на другой стороне платы, дорожка до разъёма антенны как можно короче, а антенна как можно дальше( в моём случае вообще под пузом аппарата), плюс имеются латунные экраны дабы, закрыть передатчик (не железные, магнитометру не навредить)…

SergDoc

Пока вспомнил, виртуальная еепром, не стирается stlink-ком, он затирает только тот участок флеши где сама программа, так что если какие-то переделки были в ней то сначала надо сделать полное стирание через usart в режиме бутлоадера…

Таймкоп разбушевался code.google.com/p/afrodevices/source/detail?r=335 😃 18+

oleg70

У меня вопрос по PID (что то не как не могу победить), возьмем один канал, например “крен”:
Делаю так в цикле: “П”=“уст.”-“текущ.” (она же “error”)
“И”=“И”+error
“Д”=“Д(n-1)”-“текущ.”
PID=“П”+“И”+“Д”
ну и конечно каждый компонент умножаю на коэфициент “K”<1.0 (float).
Какого порядка этот “K” должен быть?, частота выполнения цикла 250 Гц., ставил даже “К”=0.1, все равно идет перерегулирование (не затухающие колебания)…
Может что то не так делаю?

HikeR
oleg70:

Какого порядка этот “K” должен быть?

этот К должен быть разным для каждого из P, I, D.

oleg70
HikeR:

разным для каждого

Да, конечно пробую разные, но результат тот же, похоже не правильно что то делаю, судя по разным источникам интернета
встречал разночтения типа: “Д”=“Д(n-1)”-“текущ.” и “Д”=“текущ.”-Д(n-1)", как правильно не знаю…

Может кто подкинет рабочий кусочек кода для анализа?

SergDoc
// **** PITCH & ROLL & YAW PID ****
        float dT = cycleTime * 1e-6;                                                           // pt1 element 


        prop = max(abs((float)rcCommand[PITCH]), abs((float)rcCommand[ROLL]));  // range [0;500] Crashpilot: prop is float now
        for (axis = 0; axis < 3; axis++) {
            if ((f.ANGLE_MODE || f.HORIZON_MODE) && axis < 2) {            // MODE relying on ACC 50 degrees max inclination
                errorAngle = constrain(2.0f * (float)rcCommand[axis] + (float)GPS_angle[axis], -500.0f, +500.0f) - (float)angle[axis] + (float)cfg.angleTrim[axis];
                errorAngle = errorAngle*(float)cycleTime/BasePIDtime;      // Crashpilot: Include Cylcletime take 3ms as basis. More deltaT more error
                                                        PTermACC = errorAngle * (float)cfg.P8[PIDLEVEL] / 100.0f;
                PTermACC = constrain(PTermACC, -(float)cfg.D8[PIDLEVEL] * 5.0f, +(float)cfg.D8[PIDLEVEL] * 5.0f);
                errorAngleI[axis] = constrain(errorAngleI[axis] + errorAngle, -10000.0f, +10000.0f); // WindUp
                ITermACC = ((float)errorAngleI[axis] * (float)cfg.I8[PIDLEVEL])/4096.0f;
            }
            if (!f.ANGLE_MODE || axis == 2) {                              // MODE relying on GYRO or YAW axis
                error = (float)rcCommand[axis]*80.0f/(float)cfg.P8[axis];
                                                        error = error*(float)cycleTime/BasePIDtime;                // Crashpilot: Include Cylcletime take 3ms as basis. More deltaT more error
                                                          error -= (float)gyroData[axis];
                PTermGYRO = (float)rcCommand[axis];
                errorGyroI[axis] = constrain(errorGyroI[axis] + error, -16000.0f, +16000.0f);
                if (abs(gyroData[axis]) > 640.0f)
                    errorGyroI[axis] = 0;
                ITermGYRO = (errorGyroI[axis]/125.0f * (float)cfg.I8[axis])/64.0f;
            }
            if (f.HORIZON_MODE && axis < 2) {
                PTerm = (PTermACC * (500.0f - prop) + PTermGYRO * prop) / 500.0f;
                ITerm = (ITermACC * (500.0f - prop) + ITermGYRO * prop) / 500.0f;
            } else {
                if (f.ANGLE_MODE && axis < 2) {
                    PTerm = PTermACC;
                    ITerm = ITermACC;
                } else {
                    PTerm = PTermGYRO;
                    ITerm = ITermGYRO;
                }
            }
            PTerm -= (float)gyroData[axis] * (float)dynP8[axis] / 10.0f / 8.0f;


            delta = (float)gyroData[axis] - (float)lastGyro[axis];
            lastGyro[axis] = gyroData[axis];

            deltaSum = delta1[axis] + delta2[axis] + delta;
                  delta2[axis] = delta1[axis];
            delta1[axis] = delta;


            deltaSum = lastDTerm[axis] + (dT / (RC + dT)) * (deltaSum - lastDTerm[axis]); // pt1 element 
            lastDTerm[axis] = deltaSum;                                         // pt1 element 

            DTerm = ((float)deltaSum * (float)dynD8[axis])/32.0f;
            axisPID[axis] =  PTerm + ITerm - DTerm;
        }
HikeR

код реально нечитаем и нелогичен 😉

mataor

пчему же? просто с ним придется много повозится… код из вия
кстати… в нем нету понятия времени, чисто по умолчанию принято что вызывается примерно через одинаковые промежутки…

SergDoc:

axisPID[axis] = PTerm + ITerm - DTerm;

а вот тут собственно что и спрашивали…

для пояснения… расчет разбит на 2 части:

  1. Для режима удержания горизонта, используем в I данные акселя
  2. Для акро режима и YAW оси используется чисто гироскоп
SergDoc

что первое под руку попалось 😦 вообще это naze32 harakiri сейчас копаю якобы порт ardu на PX4 чёт мне кажется это не порт а подгонка программного, с екф к стати, к их протоколам, могу ошибаться…

mataor

этот код чисто виевский и практически без доработок… вот оригинал

//**** PITCH & ROLL & YAW PID ****
		for(axis=0;axis<3;axis++) {
			if (f.ACC_MODE && axis<2 ) { //LEVEL MODE
				// 50 degrees max inclination
				errorAngle = constrain(2*rcCommand[axis] + GPS_angle[axis],-500,+500) - angle[axis] + conf.angleTrim[axis]; //16 bits is ok here
			#ifdef LEVEL_PDF
				PTerm      = -(int32_t)angle[axis]*conf.P8[PIDLEVEL]/100 ;
			#else
				PTerm      = (int32_t)errorAngle*conf.P8[PIDLEVEL]/100 ;
			#endif
				PTerm = constrain(PTerm,-conf.D8[PIDLEVEL]*5,+conf.D8[PIDLEVEL]*5);

				errorAngleI[axis]  = constrain(errorAngleI[axis]+errorAngle,-10000,+10000);
				ITerm              = ((int32_t)errorAngleI[axis]*conf.I8[PIDLEVEL])>>12;
			} else { //ACRO MODE or YAW axis
				if (abs(rcCommand[axis])<350) error =          rcCommand[axis]*10*8/conf.P8[axis] ;
                                         else error = (int32_t)rcCommand[axis]*10*8/conf.P8[axis] ;
				error -= gyroData[axis];
				PTerm = rcCommand[axis];
      				errorGyroI[axis]  = constrain(errorGyroI[axis]+error,-16000,+16000);          // WindUp   16 bits is ok here
				if (abs(gyroData[axis])>640) errorGyroI[axis] = 0;
				ITerm = (errorGyroI[axis]/125*conf.I8[axis])>>6;
			}
			if (abs(gyroData[axis])<160) PTerm -=          gyroData[axis]*dynP8[axis]/10/8;
							      else PTerm -= (int32_t)gyroData[axis]*dynP8[axis]/10/8; // 32 bits is needed for calculation
			delta          = gyroData[axis] - lastGyro[axis];
			lastGyro[axis] = gyroData[axis];
			deltaSum       = delta1[axis]+delta2[axis]+delta;
			delta2[axis]   = delta1[axis];
			delta1[axis]   = delta;

			if (abs(deltaSum)<640) DTerm = (deltaSum*dynD8[axis])>>5;
							  else DTerm = ((int32_t)deltaSum*dynD8[axis])>>5;

			axisPID[axis] =  PTerm + ITerm - DTerm;
		}

там никакого портирования не нужно… чисто вставил и чуток подправил… тут чисто математика