アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になります。

Arduinoのプログラムで質問が有ります。

下記のプログラムは2番ピンに信号が入ると割り込みで13番ピンのLEDが設定時間点灯します。
ただ、設定時間になると信号が入っていてもLEDは消灯してしまいます。

そこで、信号が入っている間(ボタンが押されている時)はLEDに点灯してもらいたいのです。
2番ピンに入る信号が不安定なのですが、LEDはずーっと点灯してもらいたいのです。
ちなみにDelayは使いたくありません。(わがままスミマセン)

皆様、よろしくお願い致します。


int PinFlag ;
long TimeCount ;

void InterPin()
{
PinFlag = 1 ; // 割込み有ればON
}
void setup()
{
pinMode(13,OUTPUT) ; // 13番ピン付属LED出力
attachInterrupt(0,InterPin, RISING) ; // 2番ピンの割込みを指定(立上がりで割込み)
PinFlag = 0 ;
TimeCount = 0 ;
}
void loop()
{
// 割込み有ればその時点の時刻を保存してLEDを点灯する
while(PinFlag) {
PinFlag = 0 ;
TimeCount = millis() ; // 現在の時刻を保存
digitalWrite(13,HIGH) ; // LEDを点灯
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(13,LOW) ; // LEDを消灯
}
}
}

A 回答 (7件)

>このプログラムをLEONARDOで4系統で制御したいのですが上手くいきません。



すべて4つ必要。

volatile int PinFlag1 ; //1系統目INPUT2/OUTOUT13用
volatile int PinFlag2 ; //2系統目INPUT3/OUTOUT12用
volatile int PinFlag3 ; //3系統目INPUT0/OUTOUT11用
volatile int PinFlag4 ; //4系統目INPUT1/OUTOUT10用
long TimeCount1 ; //1系統目INPUT2/OUTOUT13用
long TimeCount2 ; //2系統目INPUT3/OUTOUT12用
long TimeCount3 ; //3系統目INPUT0/OUTOUT11用
long TimeCount4 ; //4系統目INPUT1/OUTOUT10用

//1系統目INPUT2割り込み
void InterPin1()
{
PinFlag1 = 1 ; // 割込み有ればON
}
//2系統目INPUT3割り込み
void InterPin2()
{
PinFlag2 = 1 ; // 割込み有ればON
}
//3系統目INPUT0割り込み
void InterPin3()
{
PinFlag3 = 1 ; // 割込み有ればON
}
//4系統目INPUT1割り込み
void InterPin4()
{
PinFlag4 = 1 ; // 割込み有ればON
}
void setup()
{
pinMode(2,INPUT) ; // 1系統目2番ピン付属ボタン入力
pinMode(3,INPUT) ; // 2系統目3番ピン付属ボタン入力
pinMode(0,INPUT) ; // 3系統目0番ピン付属ボタン入力
pinMode(1,INPUT) ; // 4系統目1番ピン付属ボタン入力
pinMode(13,OUTPUT) ; // 1系統目13番ピン付属LED出力
pinMode(12,OUTPUT) ; // 2系統目12番ピン付属LED出力
pinMode(11,OUTPUT) ; // 3系統目11番ピン付属LED出力
pinMode(10,OUTPUT) ; // 4系統目10番ピン付属LED出力
attachInterrupt(2,InterPin1, CHANGE) ; // 1系統目2番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(3,InterPin2, CHANGE) ; // 2系統目3番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(0,InterPin3, CHANGE) ; // 3系統目0番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(1,InterPin4, CHANGE) ; // 4系統目1番ピンの割込みを指定(変化したら割り込み)
PinFlag1 = 0 ; // 1系統目
PinFlag2 = 0 ; // 2系統目
PinFlag3 = 0 ; // 3系統目
PinFlag4 = 0 ; // 4系統目
TimeCount1 = 0 ; // 1系統目
TimeCount2 = 0 ; // 2系統目
TimeCount3 = 0 ; // 3系統目
TimeCount4 = 0 ; // 4系統目
}
void loop(){
{
// 1系統目
// 割込み有ればその時点の時刻を保存する
while(PinFlag1) {
PinFlag1 = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(2)==HIGH) {
// 立ち上がりなのであれば
TimeCount1 = 0 ; // タイマー停止
digitalWrite(13,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount1 = millis() ; // 現在の時刻を保存
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount1 != 0) {
if ((millis() - TimeCount1) >= 1010) {
TimeCount1 = 0 ;
digitalWrite(13,LOW) ; // LEDを消灯
}
}
}
// 2系統目
// 割込み有ればその時点の時刻を保存する
while(PinFlag2) {
PinFlag2 = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(3)==HIGH) {
// 立ち上がりなのであれば
TimeCount2 = 0 ; // タイマー停止
digitalWrite(12,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount2 = millis() ; // 現在の時刻を保存
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount2 != 0) {
if ((millis() - TimeCount2) >= 1010) {
TimeCount2 = 0 ;
digitalWrite(12,LOW) ; // LEDを消灯
}
}
}
// 3系統目
// 割込み有ればその時点の時刻を保存する
while(PinFlag3) {
PinFlag3 = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(0)==HIGH) {
// 立ち上がりなのであれば
TimeCount3 = 0 ; // タイマー停止
digitalWrite(11,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount3 = millis() ; // 現在の時刻を保存
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount3 != 0) {
if ((millis() - TimeCount3) >= 1010) {
TimeCount3 = 0 ;
digitalWrite(11,LOW) ; // LEDを消灯
}
}
}
// 4系統目
// 割込み有ればその時点の時刻を保存する
while(PinFlag4) {
PinFlag4 = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(1)==HIGH) {
// 立ち上がりなのであれば
TimeCount4 = 0 ; // タイマー停止
digitalWrite(10,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount4 = millis() ; // 現在の時刻を保存
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount4 != 0) {
if ((millis() - TimeCount4) >= 1010) {
TimeCount4 = 0 ;
digitalWrite(10,LOW) ; // LEDを消灯
}
}
}
}

系統番号とINPUTピン番号、OUTPUTピン番号が順番通りになってない場合は、以下のような対応一覧表を作って、ミスを防ぎましょう。

系統番号 INPUT OUTPUT InterPin TimeCount PinFlag
1       2    13      1     1       1
2       3    12      2     2       2
3       0    11      3     3       3
4       1    10      4     4       4

この回答への補足

chie65535様

早速のご回答ありがとうございます。

スケッチをコピーしてIDE(ライティングソフト)に張り付けましたがエラーに
void loop(){の{ を削除したら書き込めたのですがLEDは点灯せず。

スケッチとにらめっこしていますが、修正するところが見つかりません。



全て、4系統必要なのですね・・・・勉強になります。
一覧表は必要ですね。作成します。


本当に、ありがとうございます。差し上げるお礼ポイントが足りないです。

補足日時:2014/06/24 12:40
    • good
    • 0
この回答へのお礼

chie65535様

ありがとうございます。

{と}を追加したら動作しました。

ありがとうございました。
本当に勉強になりました。


これから、もっと勉強しますので、よろしくお願い致します。

お礼日時:2014/06/25 13:19

重要な追記。



割り込みルーチンの中で変化する変数には「volatile」を付けないといけません。

int PinFlag ;



volatile int PinFlag ;

と書かないといけません。

「volatile」は「割り込みの中で値が変化するから、毎回、ちゃんと値を調べないといけない」と言う修飾です。

例えば

int Flag ;

void loop()
{
Flag=0 ;
while(Flag) {
// Flagを一切使わない処理
}
}

と書いたら、最適化されて

int Flag ;

void loop()
{
Flag=0 ;
while(0) {
// Flagを一切使わない処理
}
}

になり、「while(0)の部分は絶対に実行されないから」と更に最適化されて

int Flag ;

void loop()
{
Flag=0 ;
}

になり、Flagに値を代入したあと使ってないので更に最適化され

int Flag ;

void loop()
{
}

になってしまう可能性があります。

もし、こうなってしまったら「ボタンもLEDも何も動かない。実行しても何もしない」と悩む事になります。

なので、割り込み内で値が変化する変数は「最適化するな」と指示しないといけません。

そのため、割り込みの中で値が変化する変数は

volatile int Flag ;

のように書かないといけません。

これを忘れると、思わぬ落とし穴にハマります。

この回答への補足

chie65535

すみません、その後ハマってしまっています。

このプログラムをLEONARDOで4系統で制御したいのですが上手くいきません。

入力は分割できたのですが出力が1個光っていると他のLEDが消えません。
で4個同時に消えるプログラムになってしまいました。

その後、LEDを消灯するプログラムも4分割したのですが全く動作しません。
TimeCountが4個有ると指定して各チャンネルに設定しないといけないのでしょうか?

大変申し訳ありません。
よろしければ、教えて下さい。



volatile int PinFlag ;
long TimeCount ;

void InterPin()
{
PinFlag = 1 ; // 割込み有ればON
}
void setup()
{
pinMode(2,INPUT) ; // 2番ピン付属ボタン入力
pinMode(3,INPUT) ; // 3番ピン付属ボタン入力
pinMode(0,INPUT) ; // 0番ピン付属ボタン入力
pinMode(1,INPUT) ; // 1番ピン付属ボタン入力
pinMode(13,OUTPUT) ; // 13番ピン付属LED出力
pinMode(12,OUTPUT) ; // 12番ピン付属LED出力
pinMode(11,OUTPUT) ; // 11番ピン付属LED出力
pinMode(10,OUTPUT) ; // 10番ピン付属LED出力
attachInterrupt(0,InterPin, CHANGE) ; // 2番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(1,InterPin, CHANGE) ; // 3番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(2,InterPin, CHANGE) ; // 0番ピンの割込みを指定(変化したら割り込み)
attachInterrupt(3,InterPin, CHANGE) ; // 1番ピンの割込みを指定(変化したら割り込み)
PinFlag = 0 ;
TimeCount = 0 ;
}
void loop(){
{
// 割込み有ればその時点の時刻を保存する
while(PinFlag) {
PinFlag = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(2)==HIGH) {
// 立ち上がりなのであれば
TimeCount = 0 ; // タイマー停止
digitalWrite(13,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount = millis() ; // 現在の時刻を保存
}
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(13,LOW) ; // LEDを消灯
}
}
}
{
// 割込み有ればその時点の時刻を保存する
while(PinFlag) {
PinFlag = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(3)==HIGH) {
// 立ち上がりなのであれば
TimeCount = 0 ; // タイマー停止
digitalWrite(12,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount = millis() ; // 現在の時刻を保存
}
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(12,LOW) ; // LEDを消灯
}
}
}
{
// 割込み有ればその時点の時刻を保存する
while(PinFlag) {
PinFlag = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(0)==HIGH) {
// 立ち上がりなのであれば
TimeCount = 0 ; // タイマー停止
digitalWrite(11,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount = millis() ; // 現在の時刻を保存
}
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(11,LOW) ; // LEDを消灯
}
}
}
{
// 割込み有ればその時点の時刻を保存する
while(PinFlag) {
PinFlag = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(1)==HIGH) {
// 立ち上がりなのであれば
TimeCount = 0 ; // タイマー停止
digitalWrite(10,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount = millis() ; // 現在の時刻を保存
}
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(10,LOW) ; // LEDを消灯
}
}
}
}

補足日時:2014/06/23 13:03
    • good
    • 0
この回答へのお礼

重ね重ね、ありがとうございます。
volatile int Flag ; の事を丁寧にありがとうございます。
本当に勉強になります。もう少し調べてみます。
今回のスケッチにもvolatile int PinFlag ;に変えました。

今の所、変える前でも変えても希望通りに動作しています。
変えておいた方が、忘れないのと勉強になるのでvolatile int PinFlag ;で行きます。


感謝します。
ありがとうございました。

お礼日時:2014/06/18 18:19

>すみません、問題が発覚しました。


>割り込みで設定した時間(1010ms)以上、ボタンを押しているとLEDが消えずに点灯したままになってしまいました。
>時間設定を長くする以外に方法有りますか

int PinFlag ;
long TimeCount ;

void InterPin()
{
PinFlag = 1 ; // 割込み有ればON
}
void setup()
{
pinMode(2,INPUT) ; // 2番ピン付属ボタン入力
pinMode(13,OUTPUT) ; // 13番ピン付属LED出力
attachInterrupt(0,InterPin, CHANGE) ; // 2番ピンの割込みを指定(変化したら割り込み)
PinFlag = 0 ;
TimeCount = 0 ;
}
void loop()
{
// 割込み有ればその時点の時刻を保存する
while(PinFlag) {
PinFlag = 0 ;
// 立ち上がりか立ち下がりか調べて
if (digitalRead(2)==HIGH) {
// 立ち上がりなのであれば
TimeCount = 0 ; // タイマー停止
digitalWrite(13,HIGH) ; // LEDを点灯
} else {
// 立ち下がりなのであれば
TimeCount = millis() ; // 現在の時刻を保存
}
}
// 設定秒間カウントしたらLEDを消灯する
if (TimeCount != 0) {
if ((millis() - TimeCount) >= 1010) {
TimeCount = 0 ;
digitalWrite(13,LOW) ; // LEDを消灯
}
}
}
    • good
    • 0
この回答へのお礼

ありがとうござます。
スケッチしていただき申し訳ありません。
勉強させていただきました。
実際に書き込んで長時間ボタンを押して話しても1010ms後に消えました。

本当にありがとうございました。
さらに勉強します。

お礼日時:2014/06/18 18:05

追記。



立ち上がりと立ち下りの両方を割り込みさせる(attachInterruptの3番目にCHANGEを指定すると)、割り込みは、同じルーチンに飛んで来るので、PinFlagで割り込みの有無を調べるだけでは足りません。

「割り込みの有無を表すPinFlag変数」の他に「立ち上がり、立ち下り、どっちの割り込みかを表す変数」が必要になるでしょう。

変数を使わない場合は、setupにpinMode(2,INPUT)を追加して、割り込みあったと判定した後で、digitalRead(2)の戻り値がLOWかHIGHか判定して、立ち上がり、立ち下りを区別して下さい。
    • good
    • 0

割込みを使う必要はないです。


ループの中で2番ピンがHIGHならPinFlagを1にするプログラムを追加するだけ。

この回答への補足

すみません、問題が発覚しました。

割り込みで設定した時間(1010ms)以上、ボタンを押しているとLEDが消えずに点灯したままになってしまいました。

時間設定を長くする以外に方法有りますか

補足日時:2014/06/18 16:45
    • good
    • 0
この回答へのお礼

ありがとうございます。

難しく考えすぎました。

{
if (digitalRead(2) == HIGH) { //スイッチの状態を調べる
digitalWrite(13,HIGH) ; //スイッチが押されているならLEDを点灯

Loopの下に、これを入れたら思い通りの動作しました。

本当にありがとうございました。

お礼日時:2014/06/18 15:57

Arduinoのハードウェアに詳しくないですが、ボタンが押されている状態を検出する手段がないと出来ません。

普通はポートの状態を読み取れる筈ですが。タイマールーチンにより定期的にボタンが押されている状態をチェックします。押されている限りLEDを点灯します。ボタン押下の割り込みで起動する必要はないように思います。キーボードのキースキャンなどと同じやり方です。
    • good
    • 0
この回答へのお礼

説明不足、申し訳ありませんでした。
信号が連続ONの時とパルスに時が有るのです。

ありがとうございました。

お礼日時:2014/06/18 15:58

プログラムを



・2番ピンの立ち上がり割り込み時

LEDの点灯と、TimeCountを0にする処理を行う

・2番ピンの立ち下がり割り込み時

現在時刻の保存だけを行う(TimeCountを0以外の値にする)

・メインループ

TimeCountが0でないなら、現在時刻とTimeCountを比較し、指定秒間に達したら、LEDを消灯してTimeCountを0にする処理を行う

と言う形にすれば良いです。

LEDが消灯されるのは「立下りのあと、指定した時間、何も割り込みが起きない時だけ」なので、2番ピンが不安定でチャタリングを起こしても、つまり、立ち上がりと立下りの割り込みが短時間に連続で入ってきても、点灯しっ放しになります。
    • good
    • 0
この回答へのお礼

ご丁寧に、ありがとうございます。
ただ、私は初心者でして「なんとなく」分かるのですがどうしたらいいのか・・・・

さらに、勉強してchie65535様のプログラムもスケッチしてみたいです。

本当に、ありがとうございました。

お礼日時:2014/06/18 16:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!