1. 程式人生 > >Arduino硬體開發--紅外遙控舵機

Arduino硬體開發--紅外遙控舵機

硬體:Arduino uno板、紅外遙控器、紅外接收三極體、舵機、杜綁線; 

埠:紅外接收管VOUT腳接11,舵機訊號接9;

效果:隨機按紅外遙控器1~9之間數字,對就舵機旋轉20、40、60、80、100、120、140、160、180度; 

程式碼:

//接收紅外資訊,解碼獲取對應數字,控制舵機旋轉對應角度。

#include <IRremote.h>//紅外庫
int RECV_PIN = 11; //紅外接收VOUT引腳定義
int SERVOPIN = 9; //舵機驅動引腳定義
int myangle;//定義角度變數
int pulsewidth;//定義脈寬變數

//編碼示例遙控數字1~9代表舵機20-180角度
long d20 = 0x00ff30CF;
long d40 = 0x00FF18E7;
long d60 = 0x00FF7A85;
long d80 = 0x00FF10EF;
long d100 = 0x00FF38C7;
long d120 = 0x00FF5AA5;
long d140 = 0x00FF42BD;
long d160 = 0x00FF4AB5;
long d180 = 0x00FF52AD;
IRrecv irrecv(RECV_PIN);
decode_results results;//結構宣告

void setup() {
  // put your setup code here, to run once:
  pinMode(RECV_PIN, INPUT); //紅外VOUT埠模式,輸入
  pinMode(SERVOPIN, OUTPUT); //舵機埠模式,輸出
  Serial.begin(9600);//波特率9600
  irrecv.enableIRIn();//開啟紅外接收
  Serial.println("system is read now!");
}

int on = 0;
unsigned long last = millis();

void loop() {
  // put your main code here, to run repeatedly:
  if (irrecv.decode(&results)) {
    if (millis() - last > 250) {
      on = !on;
      digitalWrite(13, on ? HIGH : LOW);
      dump(&results);
    }
    if (results.value == d20) {
      Serial.println("20 degree");
      startRun(20);
    }
    if (results.value == d40) {
      Serial.println("40 degree");
      startRun(40);
    }

    if (results.value == d60)
    {
      Serial.println("60 degree");
      startRun(60);
    }
    if (results.value == d80)
    {
      Serial.println("80 degree");
      startRun(80);
    }
    if (results.value == d100)
    {
      Serial.println("100 degree");
      startRun(100);
    }
    if (results.value == d120)
    {
      Serial.println("120 degree");
      startRun(120);
    }
    if (results.value == d140)
    {
      Serial.println("140 degree");
      startRun(140);
    }
    if (results.value == d160)
    {
      Serial.println("160 degree");
      startRun(160);
    }
    if (results.value == d180)
    {
      Serial.println("180 degree");
      startRun(180);
    }
    last = millis();
    irrecv.resume();
  }
}

void dump(decode_results *results)
{
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.println("Could not decode message");
  }
  else
  {
    if (results->decode_type == NEC) {
      Serial.print("Decoded NEC: ");
    }
    else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
    }
    else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
    }
    else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
    }
    Serial.print(results->value, HEX);
    Serial.print(" (");
    Serial.print(results->bits, DEC);
    Serial.println(" bits)");
  }
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 0; i < count; i++)
  {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}

void servopulse(int servopin, int myangle) /*定義一個脈衝函式,用來模擬方式產生PWM值*/
{
  pulsewidth = (myangle * 11) + 500; //將角度轉化為500-2480 的脈寬值
  digitalWrite(SERVOPIN, HIGH); //將舵機介面電平置高
  delayMicroseconds(pulsewidth);//延時脈寬值的微秒數
  digitalWrite(SERVOPIN, LOW); //將舵機介面電平置低
  delay(20 - pulsewidth / 1000); //延時週期內剩餘時間
}

void startRun(int degree) {
  if (degree > 0 && degree <= 180) //判斷收到資料值是否符合範圍
  {
    //直接獲取旋轉角度
    Serial.print("moving servo to ");
    Serial.print(degree, DEC);
    Serial.println();
    for (int i = 0; i <= 50; i++) //產生PWM個數,等效延時以保證能轉到響應角度
    {
      servopulse(SERVOPIN, degree); //模擬產生PWM
    }
  }
}

總結:基本實現預期效果,但遙控器必須對準接收管才能執行動作,如果非對準,雖然接收到訊號,串列埠列印”Could not decode message“,還未發現原因。