文件名:_BruGi第三部分(loop 主循環(huán) 第一部分)

這個部分是整個云臺控制的核心流程,通過分析他可以了解整個云臺在一個周期內(nèi)所進(jìn)行的計算糟描,了解整個控制流程怀喉,對于我來說還是太復(fù)雜了,歡迎大家一起幫助我完善船响。


void loop()//主循環(huán)函數(shù)

{

int32_t pitchPIDVal;//用來存儲俯仰軸的PID計算結(jié)果

int32_t rollPIDVal;//用來存儲橫滾軸的PID計算結(jié)果

static char pOutCnt = 0;

static char tOutCnt = 0;

static char tOutCntSub = 0;

static int stateCount = 0;

static uint8_t ledBlinkCnt = 0;

static uint8_t ledBlinkOnTime = 10;

static uint8_t ledBlinkPeriod = 20;

if (motorUpdate) // loop runs with motor ISR update rate (500 Hz)躬拢,motorUpdate就是電機中斷程序的標(biāo)志位,當(dāng)它為ture時候见间,表示中斷程序執(zhí)行一次聊闯,并執(zhí)行完畢,也就是說電機的狀態(tài)發(fā)生了變化米诉。我們這里可以提前看一下中斷程序中都做了什么:

這里插入一下中斷程序代碼:


ISR( TIMER1_OVF_vect )//ISR是ardunio的庫函數(shù)菱蔬,是專門用來處理中斷的程序,參數(shù)TIMER1_OVF_vect是中斷向量也就是中斷觸發(fā)史侣,TIMER1_OVF_vect就是當(dāng)TIMER1溢出的時候為TRUE拴泌,具體這個溢出周期時間是多少呢,需要看TIMER1的具體設(shè)置了惊橱。在BLcontroller.h中有這么一行:TIMSK1 |= _BV(TOIE1);這句代碼就是開啟timer1的溢出中斷蚪腐。而具體timer1如何配置是跟選擇PWM的輸出頻率有關(guān),8KHZ李皇,32KHZ削茁,4KHZ三種選擇。這里已32KHZ設(shè)置舉例掉房,

TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);//timer1為phase

?corrected,8bit模式 PWM模式茧跋,最大值為)0xFF(255),A通道和B通道都為升序清零卓囚,降序置位

TCCR1B = _BV(CS10);//表示不分頻瘾杭,那就是32KHz,但是什么時候去觸發(fā)溢出寄存器置位還是不清楚哪亿。粥烁。贤笆。有待繼續(xù)學(xué)習(xí)

{

freqCounter++;//初始化改值為0,每次觸發(fā)一次溢出中斷讨阻,該數(shù)值+1芥永,

if(freqCounter==(CC_FACTOR*1000/MOTORUPDATE_FREQ))//CC_FACTOR*1000代表PWM的頻率,定義MOTORUPDATE_FREQ的是電機狀態(tài)更新頻率是500HZ钝吮,這句代碼的含義就是每到需要更新電機狀態(tài)的時候執(zhí)行下列語句埋涧。

{

freqCounter=0;//把計數(shù)器清零

PWM_A_MOTOR0 = pwm_a_motor0;//默認(rèn)pwm_a_motor0=128,把驅(qū)動電機的PWM占空比設(shè)置為計算出的數(shù)據(jù)

PWM_B_MOTOR0 = pwm_b_motor0;

PWM_C_MOTOR0 = pwm_c_motor0;

PWM_A_MOTOR1 = pwm_a_motor1;

PWM_B_MOTOR1 = pwm_b_motor1;

PWM_C_MOTOR1 = pwm_c_motor1;

// update event

motorUpdate = true;//并將電機狀態(tài)更新置位奇瘦,標(biāo)明狀態(tài)已經(jīng)更新棘催。

}

// care for standard timers every 1 ms

if ((freqCounter & 0x01f) == 0) {

TIMER0_isr_emulation();//這里是什么意思還有待研究

}

}


{

motorUpdate = false;//將電機狀態(tài)更新置位

CH2_ON

// loop period

//? ? 2.053/2.035 ms max/min, error = +5/-13 us (w/o rc)

//? ? 2.098/2.003 ms max/min, error = +50/-45 us (1 x PPM16 1 x PWM)

// update IMU data

readGyros();? // td = 330us

if (config.enableGyro) updateGyroAttitude(); // td = 176 us

if (config.enableACC) updateACCAttitude(); // td = 21 us

getAttiduteAngles(); // td = 372 us//以上這幾行是獲取最新的狀態(tài)參數(shù)

//****************************

// pitch PID

//****************************

if (fpvModeFreezePitch==false) {//當(dāng)不在FPV模式下鎖定俯仰軸

// td = 92 us

pitchPIDVal = ComputePID(DT_INT_MS, DT_INT_INV, angle[PITCH], pitchAngleSet*1000, &pitchErrorSum, &pitchErrorOld, pitchPIDpar.Kp, pitchPIDpar.Ki, pitchPIDpar.Kd);//PID的計算頻率與電機更新狀態(tài)頻率要保持一致,因此PID的DT_INT為2ms耳标,頻率為500HZ醇坝,通過計算得出新的俯仰軸輸出值。

// motor control

pitchMotorDrive = pitchPIDVal * config.dirMotorPitch;//默認(rèn)config.dirMotorPitch為1

}

//****************************

// roll PID

//****************************

if (fpvModeFreezeRoll==false) {

// td = 92 us

rollPIDVal = ComputePID(DT_INT_MS, DT_INT_INV, angle[ROLL], rollAngleSet*1000, &rollErrorSum, &rollErrorOld, rollPIDpar.Kp, rollPIDpar.Ki, rollPIDpar.Kd);//同理計算出橫滾的PID輸出值

// motor control

rollMotorDrive = rollPIDVal * config.dirMotorRoll;

}

// motor update t=6us (*)

if (enableMotorUpdates)//

{

// set pitch motor pwm

MoveMotorPosSpeed(config.motorNumberPitch, pitchMotorDrive, maxPWMmotorPitchScaled);//真正驅(qū)動電機來自這一行次坡,這個函數(shù)定義在BLcontroller.h中呼猪,這里詳細(xì)分析一下


void MoveMotorPosSpeed(uint8_t motorNumber, int MotorPos, uint16_t maxPWM)//這個函數(shù)具有三個參數(shù),1.控制電機的序號贸毕,2.電機的位置.3PWM的放大因數(shù)郑叠,意義是控制具體是向哪個電機以正弦表中那三個值來生成PWM波,并且增益會是多少明棍。

{

uint16_t posStep;

uint16_t pwm_a;

uint16_t pwm_b;

uint16_t pwm_c;

// fetch pwm from sinus table?

posStep = MotorPos & 0xff;//要將pid計算出的位置與0xff相與乡革,MotorPos是一個int型數(shù)據(jù),16位吧摊腋,現(xiàn)在與0xff相與沸版,意味著只保留第八位的數(shù)據(jù)。也就是值的范圍控制在0-256

pwm_a = pwmSinMotor[(uint8_t)posStep];

pwm_b = pwmSinMotor[(uint8_t)(posStep + 85)];

pwm_c = pwmSinMotor[(uint8_t)(posStep + 170)];//驅(qū)動電機的三項PWM電角度應(yīng)該相差120°兴蒸,360°/120°=3视粮,也就是把正弦數(shù)組的長度(256)除以3分為三份,每每兩項之間在數(shù)組中相隔85(256/3)個元素,那么我們再看一下正弦數(shù)組是怎么計算的呢橙凳,根據(jù)其定義該數(shù)組長度256蕾殴,也就是說將一個電角度周期劃為了256等分,數(shù)組中數(shù)值大小范圍是-128到127岛啸,但是這里存在一個問題钓觉,因為這里(posStep+170)是不能超過255的,因此posStep值不能超過85坚踩?但是并沒有看到程序中有對應(yīng)的限制呢荡灾。睡了一晚我突然明白了,他把這里變成了一個無符號數(shù),然后如果相加過255就會溢出批幌,那么這里最后就是溢出的那個值础锐,恰好滿足了要求,因此posStep的范圍還是0-255荧缘。但是posStep的范圍是根據(jù)PID計算中進(jìn)行限定的皆警,在PID函數(shù)的語句中最后output除以4096又除以8,原來output是32位的有符號整形截粗,除以4096又除以8相當(dāng)于右移動15位耀怜,就還剩下17位,如果是正數(shù)的話桐愉,其中最高位是符號位,剩下16位為數(shù)據(jù)位掰派。數(shù)據(jù)范圍為0-65535从诲,在這個函數(shù)中又與posStep = MotorPos & 0xff;相當(dāng)于只保留低八位,數(shù)據(jù)范圍最終變?yōu)?-255.之所以這么做靡羡,是要保證PID的精度系洛,不要浮點數(shù)減少運算量,將所有的數(shù)都放大略步,保證都在整數(shù)范圍內(nèi)計算描扯,最后再將數(shù)據(jù)變小到0-255的范圍內(nèi)。

// apply power factor

pwm_a = maxPWM * pwm_a;//maxPWM是一個0~256的數(shù)趟薄,乘以一個-127-127的數(shù)绽诚,范圍會變話,但是下面緊接著又向右移動8位杭煎,相當(dāng)于是pwm_a乘以了一個小于等于1的數(shù)恩够,范圍還是在-127到127變化,但是應(yīng)該是變小了羡铲。

pwm_a = pwm_a >> 8;//

pwm_a += 128;//這里最終又加上128蜂桶,將范圍變化到了1-255。

pwm_b = maxPWM * pwm_b;

pwm_b = pwm_b >> 8;

pwm_b += 128;

pwm_c = maxPWM * pwm_c;

pwm_c = pwm_c >> 8;

pwm_c += 128;

// set motor pwm variables

if (motorNumber == 0)

{

pwm_a_motor0 = (uint8_t)pwm_a;

pwm_b_motor0 = (uint8_t)pwm_b;

pwm_c_motor0 = (uint8_t)pwm_c;

}//將PWM占空比值送到控制對應(yīng)電機的通道中

if (motorNumber == 1)

{

pwm_a_motor1 = (uint8_t)pwm_a;

pwm_b_motor1 = (uint8_t)pwm_b;

pwm_c_motor1 = (uint8_t)pwm_c;

}

}


// set roll motor pwm

MoveMotorPosSpeed(config.motorNumberRoll, rollMotorDrive, maxPWMmotorRollScaled);

}//控制橫滾軸的電機運動

// Evaluate RC-Signals, td = 120 us//這一段跟遙控信號有關(guān)也切,暫時先不分析

if (fpvModePitch==true) {

pitchAngleSet = utilLP3_float(qLPPitch, PitchPhiSet, rcLPFPitchFpv_tc);

} else if(config.rcAbsolutePitch==1) {

pitchAngleSet = utilLP3_float(qLPPitch, PitchPhiSet, rcLPFPitch_tc); // 63us

} else {

pitchAngleSet = utilLP3_float(qLPPitch, PitchPhiSet, LOWPASS_K_FLOAT(0.03));

}

if (fpvModeRoll==true) {

rollAngleSet = utilLP3_float(qLPRoll, RollPhiSet, rcLPFRollFpv_tc);

} else if(config.rcAbsoluteRoll==1) {

rollAngleSet = utilLP3_float(qLPRoll, RollPhiSet, rcLPFRoll_tc);

} else {

rollAngleSet = utilLP3_float(qLPRoll, RollPhiSet, LOWPASS_K_FLOAT(0.03));

}

// tElapsed = 1.250 ms

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扑媚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子雷恃,更是在濱河造成了極大的恐慌疆股,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褂萧,死亡現(xiàn)場離奇詭異押桃,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進(jìn)店門唱凯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羡忘,“玉大人,你說我怎么就攤上這事磕昼【淼瘢” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵票从,是天一觀的道長漫雕。 經(jīng)常有香客問我,道長峰鄙,這世上最難降的妖魔是什么浸间? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮吟榴,結(jié)果婚禮上魁蒜,老公的妹妹穿的比我還像新娘。我一直安慰自己吩翻,他們只是感情好兜看,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狭瞎,像睡著了一般细移。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熊锭,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天弧轧,我揣著相機與錄音,去河邊找鬼球涛。 笑死劣针,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亿扁。 我是一名探鬼主播捺典,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼从祝!你這毒婦竟也來了襟己?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤牍陌,失蹤者是張志新(化名)和其女友劉穎擎浴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毒涧,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡贮预,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仿吞。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡滑频,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唤冈,到底是詐尸還是另有隱情峡迷,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布你虹,位于F島的核電站绘搞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏傅物。R本人自食惡果不足惜夯辖,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望董饰。 院中可真熱鬧楼雹,春花似錦、人聲如沸尖阔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽介却。三九已至,卻和暖如春块茁,著一層夾襖步出監(jiān)牢的瞬間齿坷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工数焊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留永淌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓佩耳,卻偏偏與公主長得像遂蛀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子干厚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容