ArduCanard V2.0 航模自動(dòng)控制鴨翼小程序第二版
//ArduCanard是用arduino控制鴨翼的一個(gè)小程序,純屬個(gè)人瞎寫,但是恰好可以運(yùn)行。
//V2.0版優(yōu)化內(nèi)容:1.增加攻角限制器,在攻角大于35°后鴨翼不再響應(yīng)拉桿量,變成純正風(fēng)向標(biāo)。 2.舵機(jī)直接用pwm輸出來控制,不用servo.h了,似乎可以避免串口和servo.h共用timer造成的卡頓問題。卡頓似乎有改善。
// 飛行效果:https://www.bilibili.com/video/BV16v4y1s7VB/?spm_id_from=333.999.0.0 //
//警告:該程序用于把鴨翼變成風(fēng)向標(biāo),便于靜不穩(wěn)定飛機(jī)或者放寬靜穩(wěn)定飛機(jī)的控制。飛機(jī)上必需要額外加陀螺才能保持穩(wěn)定。程序經(jīng)過飛行驗(yàn)證,但是使用者一切后果自負(fù),包括但不限于俯仰發(fā)散、深失速、尾旋、上樹、提控回家,務(wù)必在開闊無人的地方進(jìn)行測(cè)試。
//傳感器:維特智能JY-ME01軸編碼器,精度0.1°。通信用的串口,從傳感器的板子的串口TX焊線出來連arduino板子的RX即可。
//傳感器輸出數(shù)據(jù)是字符串,格式為 Angle:xxx.xxx °,因此數(shù)據(jù)需要處理一下,從字符串中把后面的數(shù)字提取出來,再除以1000,得到攻角的值(此處因?yàn)橛昧薲elay函數(shù),導(dǎo)致程序運(yùn)行有延時(shí),后續(xù)會(huì)改進(jìn))
char comdata = "";//字符串函數(shù)
String aoa = "";//字符串函數(shù)
float AOA;
byte PWM_PIN = 2; //將PWM的信號(hào)線輸入到3號(hào)引腳
int pwm_value;
float AOAlimitmax=30;//攻角限制+-30
int theta;
void servopulse(int angle)//定義一個(gè)脈沖函數(shù)
{
? int pulsewidth=(angle*11)+500;? //將角度轉(zhuǎn)化為500-2480的脈寬值
? digitalWrite(9,HIGH);? ? //將舵機(jī)接口電平至高
? delayMicroseconds(pulsewidth);? //延時(shí)脈寬值的微秒數(shù)
? digitalWrite(9,LOW);? ? ?//將舵機(jī)接口電平至低
? delayMicroseconds(20000-pulsewidth);
}
void setup() {
? pinMode(9,OUTPUT);//設(shè)定舵機(jī)接口為輸出接口
? servopulse(90);
? delay(500);
? pinMode(PWM_PIN, INPUT);//將該引腳設(shè)置為輸入模式
? Serial.begin(9600);//打開串口波特率9600
}
void loop()
{
? ? pwm_value = pulseIn(PWM_PIN, HIGH);//檢測(cè)高電平
? ? float AOAcmd=(pwm_value-1000)*(AOAlimitmax*2)/1000-AOAlimitmax ;//pwm1000=-AOAlimitmax,pwm1500=0,pwm2000=AOAlimitmax?
? ? String aoa = "";//緩存清零
? ? while (Serial.available() > 0)//循環(huán)串口是否有數(shù)據(jù)
? ? {?
? ? ? comdata=Serial.read();
? ? ? if(isDigit(comdata)) //是數(shù)字就執(zhí)行
? ? ? ? {
? ? ? ? ? aoa += comdata;//疊加數(shù)據(jù)到aoa
? ? ? ? }
? ? ? delay(2);//延時(shí)等待響應(yīng)
? ? }
? if (aoa.length()>0)//如果aoa有數(shù)據(jù)
? {?
? ? ? AOA=aoa.toFloat();
? ? ? AOA=AOA/1000-180;
? }
? delay(2);//延時(shí)等待響應(yīng)
? if (AOA>35&&AOAcmd>0)
? {theta=-1.1*AOA+90+5;}
? else
? {theta=-1.1*(AOA-AOAcmd)+90+5;}
? if (theta>140)
? {theta=140;}
? if (theta<60)
? {theta=60;}
? servopulse(theta);
? //Serial.print(pwm_value);
? //Serial.print(",");
? //Serial.print(AOAcmd);
? //Serial.print(",");
? //Serial.print(AOA);
? //Serial.print(",");
? //Serial.println(theta);
}