紅外線遙控車

回覆文章
cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

紅外線遙控車

文章 cajhbb »

SN754410.png
SN754410.png (23.25 KiB) 已瀏覽 135 次
pins diagram l293d.jpg
pins diagram l293d.jpg (30.29 KiB) 已瀏覽 135 次
https://atceiling.blogspot.com/2014/02/ ... l293d.html 參考資料
cajhbb
系統管理員
文章: 983
註冊時間: 2018年 6月 30日, 02:16

Re: 紅外線遙控車

文章 cajhbb »

電路圖.png
電路圖.png (68.84 KiB) 已瀏覽 132 次

代碼: 選擇全部

/* 紅外線遙控車

   David Johnson-Davies - www.technoblogy.com - 2015年7月20日
   ATtiny85 @ 1 MHz (內部振盪器; BOD 禁用)
   
   CC BY 4.0
   授權條款: 創作共用 署名 4.0 國際 授權協議:
   http://creativecommons.org/licenses/by/4.0/
*/

volatile int NextBit; // 下一位元
volatile unsigned long RecdData; // 接收到的資料

// 馬達控制 **********************************************

void ReceivedCode (boolean Repeat) {
  static int Left, Right, Speed = 127;
  // 檢查是否來自正確的遙控器
  if ((RecdData & 0xFFFF) != 0xbF00) return;
  if (Repeat) return; // 忽略按鍵持續按下
  // 讀取按下的按鍵
  int key = RecdData >> 16 & 0xFF;
  // 馬達命令
  if ((key >= 0x10) && (key <= 0x1A)) Speed = ((key - 16) * 12) + 7;
  else if (key == 0x05) { Left = 2; Right = 2; }                    // 前進
  else if (key == 0x0D) { Left = -2; Right = -2; }                  // 後退
  else if (key == 0x08) { Left = 2; Right = 1; }                    // 左轉
  else if (key == 0x0A) { Left = 1; Right = 2; }                    // 右轉
  else if ((key == 0x06) || (key == 0x09)) { Left = 0; Right = 0; } // 停止
  else if (key == 0x0E) { Left = 2; Right = -2; }                   // 旋轉
  //
  if (Left >= 0) {
    digitalWrite(0, LOW);
    OCR1A = Left * Speed;
  } else {
    digitalWrite(0, HIGH);
    OCR1A = 255 + (Left * Speed);
  }
  if (Right >= 0) {
    digitalWrite(3, LOW);
    OCR1B = Right * Speed;
  } else {
    digitalWrite(3, HIGH);
    OCR1B = 255 + (Right * Speed);
  }
}

// 紅外線控制 **********************************************

// 中斷服務例程 - 每次PB2下降沿時調用
ISR (INT0_vect) {
  int Time = TCNT0;
  int Overflow = TIFR & 1<<TOV0;
  // 持續尋找 AGC 脈衝和間隙
  if (NextBit == 32) {
    if ((Time >= 194) && (Time <= 228) && (Overflow == 0)) {
      RecdData = 0; NextBit = 0;
    } else if ((Time >= 159) && (Time <= 193) && (Overflow == 0)) ReceivedCode(1);
  // 資料位元
  } else {
    if ((Time > 44) || (Overflow != 0)) NextBit = 32; // 無效 - 重新啟動
    else {
      if (Time > 26) RecdData = RecdData | ((unsigned long) 1<<NextBit);
      if (NextBit == 31) ReceivedCode(0);
      NextBit++;
    }
  }
  TCNT0 = 0;                  // 清除計數器
  TIFR = TIFR | 1<<TOV0;      // 清除溢出
  GIFR = GIFR | 1<<INTF0;     // 清除 INT0 標誌
}

// 設置 **********************************************
  
void setup() {
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT);
  // 設置 Timer/Counter0 用於紅外線接收器 (假設時鐘頻率為 1MHz)
  TCCR0A = 0;                 // 無比較匹配
  TCCR0B = 3<<CS00;           // 預分頻 /64
  // 設置 INT0 中斷在 PB2 上
  MCUCR = MCUCR | 2<<ISC00;   // 下降沿中斷
  GIMSK = GIMSK | 1<<INT0;    // 啟用 INT0
  NextBit = 32;               // 等待 AGC 開始脈衝
  // 設置 Timer/Counter1 用於 PB1 和 PB4 上的快 PWM
  TCCR1 = 1<<CTC1 | 1<<PWM1A | 2<<COM1A0 | 7<<CS10;
  GTCCR = 1<<PWM1B | 2<<COM1B0;
}

void loop() {
  // 所有操作都在中斷中完成!
}

回覆文章