ATtiny85の外部割込み機能を使ってみよう

こんにちは、くのへ@MasazaneKunoheです。

今日はATtiny85の「外部割込み」機能について紹介します!

マイコンには「割り込み」と呼ばれる機能があります。
この「割り込み」の機能は「外部割込み」と「ピンチェンジ割込み」の2種類の方法がありますが、今回は「外部割込み」について解説します。
ピンチェンジ割込みは、別な記事で紹介します。

紹介する内容

今回は「外部割込み」の機能を紹介します。

「割込み」という機能は、読んで字のごとく、「割込みピン」と呼ばれるピンが電圧変化を感知すると、実行中のプログラムに割り込んで、先に所定のプログラムを動かし、そしてその処理が終わったら元のプログラムの一時停止した所から実行する、という機能です。(↓イメージ図)

この記事では、音楽を奏でるこちらの記事のコードを改造し、音楽を奏でるloopの実行中に、LEDをオン・オフさせる動作を割り込ませます。

やり方(概要)

「割込み」機能を使うためには、「割込みピン」と呼ばれるピンの電圧を変化させます。
ATtiny85では、もともと外部割込みピンが1つ用意されています。

↓この図のINT0(インタラプトゼロ)ピンが外部割込みピンです。7ピン(PB2ピン)ですね!

このピンの電圧変化イベントを検出して、特定の割り込みプログラムを実行させることが出来ます。

次章から次の順番で解説します。

①音楽を奏でるブザーと、外部割込みピンに電圧を掛けるボタンと、LEDを持つ回路を作ります。
②外部割込みを行うプログラムをATtiny85に書き込みます。

詳細

①音楽を奏でるブザーと、外部割込みに電圧を掛けるボタンと、LEDを持つ回路を作ります。

次のような回路を組みます。
これは、ATtiny85の3番ピン(PB4ピン)とGNDをブザーに接続するのはこの記事と同じですが、INT0ピンである7番ピン(PB2ピン)に色々付いています。

これを回路図で書くとこのような回路です。

この図の通り、INT0である7番ピン(PB2ピン)を10kΩ抵抗でプルダウンさせ、押しボタンを押すとINT0ピンの電圧がHIGHになる回路を作ります。
後は、3番ピンにブザーが付いていて、これで音楽を鳴らす回路です。

②外部割込みを行うプログラムをATtiny85に書き込みます。

上記の①の回路が出来たら、今度はATtiny85に外部割込みを行わせるコードをプログラミングします

こちらの記事に記載したおさかな天国を奏でる次のスケッチを改造します。

//ピンの設定
#define soundPin 4 //D4ピン(3番ピン)を音の出力ピンとする

//音階データ

//おさかな天国
int scale[] = {
  783,783,783,783,783,783,783,880,987,0,0,0,0,0,880,987,
  1046,0,1046,0,1046,1046,0,987,880,0,0,0,0,0,0,0,

  739,739,739,739,739,739,739,783,880,0,0,0,0,0,880,880,
  783,0,783,0,783,783,0,659,783,0,0,0,0,0,0,0
};

//音の長さ
int time[] ={
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250
};

//配列の長さ
int scaleLen = sizeof(scale) / sizeof(int);

//loop用のカウンター
int i=0;


void setup() {
  // put your setup code here, to run once:

  pinMode(soundPin, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

  SoundMusic();

}

void SoundMusic()
{
  if (i < scaleLen){
    tone(soundPin, scale[i], time[i] * 0.9);  //
    delay(time[i]);
    i++;
  }else{
    //i = 0;
  }   
}

このコードを次のように加筆します。

//ピンの設定
#define soundPin 4 //D4ピン(3番ピン)を音の出力ピンとする

//音階データ

//おさかな天国
int scale[] = {
  783,783,783,783,783,783,783,880,987,0,0,0,0,0,880,987,
  1046,0,1046,0,1046,1046,0,987,880,0,0,0,0,0,0,0,

  739,739,739,739,739,739,739,783,880,0,0,0,0,0,880,880,
  783,0,783,0,783,783,0,659,783,0,0,0,0,0,0,0
};

//音の長さ
int time[] ={
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
  250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250
};

//配列の長さ
int scaleLen = sizeof(scale) / sizeof(int);

//loop用のカウンター
int i=0;

//LEDピン
#define LED_Pin 0

void setup() {
  // put your setup code here, to run once:

  pinMode(soundPin, OUTPUT);
  pinMode(LED_Pin,OUTPUT);

  attachInterrupt(0,Interruption, RISING);

}

void loop() {
  // put your main code here, to run repeatedly:

  SoundMusic();

}

void SoundMusic()
{
  if (i < scaleLen){
    tone(soundPin, scale[i], time[i] * 0.9);  //
    delay(time[i]);
    i++;
  }else{
    //i = 0;
  }   
}

void Interruption()
{
  digitalWrite(LED_Pin, !digitalRead(LED_Pin));
}

これをATtiny85に書き込んで、回路に組み込み、実行してみましょう。
音楽が流れている最中(Loop中)にLEDがオンオフします。
プログラム実行中にInterruption()という別の処理を割り込ませることが出来ました!!

これを動かしているのがこちらの動画になります!!

コード解説

割込みを使う方法は以下の通りです。

1) setupの中にattachInterruptを記載する

サンプルコードの以下の部分です。

attachInterrupt(0,Interruption, RISING);

attachInterruptは外部割込み機能をONにするための命令です。
attachInterrupt(第1引数, 第2引数, 第3引数)の形で記載し、それぞれの引数は次の通りです。

第1引数:割込みピンの指定(0と書くとINT0を指定したことになる)
第2引数:動かすサブプロシージャ
第3引数:割込みピンの電圧変化イベント

今回のサンプルコードの場合は、「0番(INT0)ピンに、電圧がLOWからHIGHに上昇(RISING)した時に、Interruptionというサブプロシージャを動かす」と言う命令になっています。
今回は「Interruption」というサブプロシージャを動かすこととしていますが、名前は何でもいいです。

第3引数の電圧変化イベントは、RISING(電圧上昇)も含めて、以下を指定することが出来ます。

  • LOW : LOWレベルで割り込みを発生させます。
  • CHANGE : 信号が変化したときに割り込みを発生させます。
  • RISING : 信号が立ち上がりエッジである場合に割り込みを発生させます。
  • FALLING : 信号が立ち下がりエッジである場合に割り込みを発生させます。
  • HIGH : HIGHレベルで割り込みを発生させます。

別な記事で紹介しますが、PCINT(ピンチェンジ割込み)の場合はCHANGEしか使えません。この点がATtiny85での外部割込みとピンチェンジ割込みの機能的な大きな違いになります。

2) 割込み時に動かすサブプロシージャInterruptionを記載する

サンプルコードの以下の部分です。

void Interruption()
{
  digitalWrite(LED_Pin, !digitalRead(LED_Pin));
}

このサンプルコードはLEDピンをON/OFFさせるコードにしていますが、もっと複雑な処理でも構いません。
割込み時に処置したい内容をここにコーディングすると、割込みピンが電圧変化した時に動作します。

これで割込みヨシ!!


今日は「ATtiny85の外部割込み」の使い方を紹介しました。

割込み機能が必須となるような状況はあまりないと思いますが、今回の音楽を鳴らすコードのように、for文などのループしている途中に、何らかの処理を割り込ませたい時に使えます。

また、電池消費を抑えるための「スリープモード」を使う場合、スリープモードからの復帰をさせるのは割込み機能を使うこととなります。
スリープモードを使う場合は、割込み機能の習得は必須ですので、是非習得しましょう!

ではまた別の記事で会いましょう。
ではでは~

🦅バサバサ~