LoginSignup
1
1

More than 1 year has passed since last update.

ATTiny85で赤外線送信する

Last updated at Posted at 2022-04-19

既出すぎる内容な気もしますが、いわゆるArduino端末によく使われる
ATMega328Pではなく、ATTiny85を用いた内容、かつ
irRemoteライブラリを使わない実装としたため記事にします。

この記事は下書きのまま一年以上放置してしまいましたが
編集途中でも公開しておきます。

背景

オーム社の照明リモコンCRS-01Wは、壁スイッチでON/OFFすると
OFFから開始されるので、リモコンでONしなければ電気が点かない。
とても不便なので壁スイッチONでリモコンONの操作もさせたいと思います。

シーリングソケット
├ 通電した時にだけON信号を出す赤外線送信機
└ シーリング照明

実装

sketch

#include <avr/wdt.h> // wdt_disable()を使うため
#define OUTPUT_PIN  (_BV(4) | _BV(1)) // 4:インジケータ、1:赤外線LED (PWM)

static const unsigned int irSignal[] = { // オーム社の照明リモコンCRS-01W:スイッチON信号
//  ON, OFF,  ON,OFF,  ON,OFF,  ON,OFF,  ON, OFF,  ON, OFF,  ON, OFF,  ON, OFF,  ON,OFF,  ON, OFF
  2550,2700, 800,850, 850,850, 800,850, 850,1900, 800,1900, 850,1850, 850,1900, 800,850, 850,9000
};

/**
 * 赤外線LEDを38kHzで点灯させる(1番ピン)
 */
void pwm_out(int microseconds) {
  PORTB |= _BV(4); // インジケータ点灯:digitalWrite(4, HIGH)と同じ
  // タイマー(TC0)を設定
  OCR0A = 25;  // TOP value :  38kHz --> 26.3us.
  OCR0B = 6;  //  H period  : 6.4us.
  TCCR0A = B00100011; // COM0A: 00, COM0B: 10, WGM01-00: 11
  TCCR0B = B00001001; // FOC:00, WGM02:1, CS02-01: 001 (system clock x1)
  TCNT0 = OCR0A;
  delayMicroseconds(microseconds); // 指定マイクロ秒だけ点灯
  // タイマー(TC0)をリセット
  TCCR0A = 0; // タイマー(TC0)リセット
  TCCR0B = 0; // タイマー(TC0)リセット
  PORTB &= ~_BV(4); // インジケータ消灯:digitalWrite(4, LOW)と同じ
}
 
void setup() {
  /**
   * 初期化
   */
  cli(); // noInterrupts();の中身(割り込み停止)
  DDRB = OUTPUT_PIN; // B010010000 pinMode(PB1, OUTPUT),pinMode(PB4, OUTPUT)
  PORTB = 0; // B00000000 PB1もPB4もLOW
  ACSR |= 0x80; // アナログコンパレータ禁止
  ADCSRA &= 0x7f; // disable ADC
  wdt_disable(); // ウォッチドッグタイマを停止
  TIMSK = 0; // disable Timer0/1 overflow interrupt.
  sei(); // noInterrupts();の中身(割り込み停止)

  /**
   * ループ
   */
  int len = sizeof(irSignal) / sizeof(irSignal[0]); // 送信する信号の数
  int ir_mcs = 0; // マイクロ秒。信号の送信に要する時間
  for (int i = 0; i < len; i++) {
    ir_mcs += irSignal[i]; // 合計:32,650マイクロ秒=32.65ミリ秒(9000マイクロ秒の赤外線OFFはダミー)
  }
  int interval_ms = 50; // ミリ秒。次の信号を送信するまでの間隔
  int loop_ms = 1000; // ミリ秒。信号を送信し続ける時間
  int loop_cnt = loop_ms / interval_ms; // ループの回数を計算
  // 次の信号を送信するまでの待ち時間(ミリ秒)
  //  =インターバル(ミリ秒)-(1回あたりの赤外線送信時間(マイクロ秒)÷1000)
  double wait_ms = interval_ms - (ir_mcs / 1000); // 50 - 32.65 = 17.35
  for (; loop_cnt > 0; loop_cnt--) {
    // このループ全体で一つの赤外線信号
    for (int i = 0; i < len; i += 2) { // 1回のループでONとOFFを処理する
      pwm_out(irSignal[i]); // 赤外線ON(38kHzで指定のマイクロ秒だけ点灯)
      delayMicroseconds(irSignal[i+1]); // 赤外線OFF
    }
    // インターバル。delayが使えないのでdelayMicrosecondsを必要ms分ループ
    for (int i = 0; i < wait_ms; i++) { // (小数点切り捨て=17ミリ秒待つ処理)
      delayMicroseconds(1000); // 1ミリ秒待つ
    }
  }
}

// Arduinoのタイマーは使わないため、loop()では何も処理しない
void loop() {}

回路図

スクリーンショット 2020-12-24 12.53.48.png

解説

赤外線信号の仕組み

今回学んだことを羅列します。

  • 赤外線信号は 点灯・消灯を繰り返す時間の長さ で情報を伝えます(モールス信号みたいなもの)
  • 一般的に赤外線通信に使う赤外線の波長は 900nm らしいです(LEDを購入するときに念のため確認しましょう)
  • 受信側は太陽光など他の光と区別するために 38kHzという周波数の光だけを受信する ようにできています
  • つまり発信側も38kHzで発光させる必用があります
  • 38kHzとは 26.3μ秒で一周期 で、この間にON/OFFを1回します(ONは6μ秒、残り時間はOFFで良いみたいです→省電力)
  • デューティー比=1/3:一周期でONになっている時間は1/3の時間とする(つまり8.7μ秒がON、上記の6μ秒と矛盾してるけどw)
  • 送信機の条件は 38kHzで発光できること点灯・消灯時間をμ秒で制御できること 、になります

ちなみに今回の信号は irSignal で定義したとおりです。単位は μ秒 です。
(最後のOFF継続時間9000μ秒は、信号終了が判断可能な時間を十分に確保しようと、私が勝手に追加したものです)

赤外線信号の定義
static const unsigned int irSignal[] = { // オーム社の照明リモコンCRS-01W:スイッチON信号
//  ON, OFF,  ON,OFF,  ON,OFF,  ON,OFF,  ON, OFF,  ON, OFF,  ON, OFF,  ON, OFF,  ON,OFF,  ON, OFF
  2550,2700, 800,850, 850,850, 800,850, 850,1900, 800,1900, 850,1850, 850,1900, 800,850, 850,9000
};

PWM

ATTiny85のPWM(パルス幅変調)は0番ピン・1番ピンです。
データシート
今回は1番ピンを使って38kHzの赤外線信号を点灯させます。
なぜ0番ではなく1番ピンを使うのかは後述します。
(irRemoteでも勝手に1番ピンが使われるのはPWMに対応しているからという理由です、他のピンでは代替えできません)

irRemoteライブラリを使わない理由

いま思えば最後のスイッチOFF時間を十分に取れていなかっただけかも知れませんが
送信した信号がうまく解析してもらえなかったのが理由です。
ON/OFFを繰り返し10回行いますが、3回分しか認識しなかったり15回分だと判断してしまったり。。
それ以外にも delay() が使えないとか(使わない方が良い?)
ライブラリに手を加えないと動かない、とか、いくつか問題がありました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1