LoginSignup
4
7

More than 5 years have passed since last update.

Arduinoで割り込みとI2Cを併用する

Last updated at Posted at 2016-12-22

普段はスリープして,ボタンによる割り込みで起動するLCDディスプレイをArduinoで作ろうとした際に困ったことと対処法をログしておきます.

使用機材

配線

I2C_interrut.png
(雑ですみません…)

使用機能について

attachInterrupt( digitalPinToInterrupt(pinNo) , func , mode )

digitalピン入力より割り込み処理し,関数を実行します.

  • pinNo: digitalの使用ピン番号.Arduino Unoでは2か3しか使えない.
  • func: 割り込みで実行する関数
  • mode: 割り込み処理するデジタル入力の種類.
    • RISING
    • FALLING
    • CHANGE

問題点

ボタンを押したらLCDの表示を変えようと思うと,一見以下のコードを書いたらよさそうに思います1

誤例.ino
#include <I2CLiquidCrystal.h>
#include <mglcd.h>
I2CLiquidCrystal lcd;

void func() {
  lcd.print("intterupted");
}

void setup() {
  lcd.begin(16,2);
  pinMode(2,INPUT);
  attachInterrupt(digitalPinToInterrupt(2),func,FALLING);
  interrupts();
}

void loop() {
}

しかしボタンを押してもLCDには何も表示されません.

対処

I2Cのライブラリ(wire.h)は割り込みを用いており,割り込み内で割り込み発動,みたいなことになり,ハングしているのでは,と考えています.
対処としては,状態変数を用いてfunc()外でlcdインスタンスをいじるようにすれば問題ないようです.

正.ino
#include <I2CLiquidCrystal.h>
#include <mglcd.h>
I2CLiquidCrystal lcd;

volatile bool state=false;

void func() {
  state = true;
}

void setup() {
  lcd.begin(16,2);
  pinMode(2,INPUT);
  attachInterrupt(digitalPinToInterrupt(2),func,FALLING);
}

void loop() {
  if(state){
    lcd.print("interrupted");
  }
  delay(100);
}

I2Cが割り込みを用いているため,どこかでnointerrupts()関数で割り込み禁止しても同様に誤動作します.


  1. 他のコードではよく見るinterrupt.hをインクルードしていませんが,Arduino.hですでに記述されているので実際不要です(Arduino 1.6現在). 

4
7
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
4
7