質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
IDE

IDE、統合開発環境((Integrated Development Environment)とは、テキストエディタ以上の機能を提供して、ソフトウェア開発を効率をあげるコンピュータプログラムを指す。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

3回答

619閲覧

Arduino IDE 割り込み で-1をかける方法以外があればご教授ください。

norisans

総合スコア5

IDE

IDE、統合開発環境((Integrated Development Environment)とは、テキストエディタ以上の機能を提供して、ソフトウェア開発を効率をあげるコンピュータプログラムを指す。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2020/03/27 13:18

前提・実現したいこと

皆様、アイデアをお願いいたします。

点滅など、delayが継続している途中で、割り込みができて、違う動作をさせたいと考えています。
試行錯誤して、スイッチが押される毎に、aに-1をかけて、+と-ごとに動作を変える方法を考えました。
以下は、1の時は消灯が長いLED9と、-1の時は点灯が長いLED9というif文のサンプルです。

しかし、この割り込みは、小学生と扱って行きたいのです。
実は、-1は中学生で習うので -1を使わない方法を探しています。
もし、アイデア等があれば、皆様ご教授を頂ければと思います。
よろしくお願いいたします。

該当のソースコード

Arduino

1int a; 2void setup() { 3 pinMode(9, OUTPUT); 4 attachInterrupt(0, blink, FALLING); //割り込み用 0=2番ピンでblink発動 5 Serial.begin(9600); //変数の値を表示 6 a=1; 7} 8void loop() { 9 Serial.println(a); 10if(a==-1){ 11 digitalWrite(9,HIGH); 12 delay(800); 13 digitalWrite(9,LOW); 14 delay(100); 15} 16if(a==1){ 17 digitalWrite(9,HIGH); 18 delay(100); 19 digitalWrite(9,LOW); 20 delay(800); 21} 22} 23void blink() { //押される度に -1をかけることで、aが1と-1になる 24 a=a*(-1); 25} 26

試したこと

2番ピンの割り込み用スイッチが押される毎に、aに-1がかけられ、1と-1の値ごとに、光り方が変わります。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

小学校3年生で剰余、つまり割り算のあまりを習うはずなので、%演算子を使うのもいいと思います。

たとえば、割り込みで呼ばれる側で

C

1a = a + 1; 2a = a % 2;

と記述すれば、aがとりうる値は01のいずれかです。

ちなみに、上の二行はもっともっと簡素に書けますが、小学生でも理解できるようにあえて冗長に書いています。

剰余を使った計算というのは意外に多いのですが、その便利さに気づかないまま「こんなん何に使うの」で終わっているのも事実だと思いますので、振り返りの良い機会になるのではないでしょうか。

投稿2020/03/27 15:20

TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

norisans

2020/03/27 23:25

TsukubaDepot様 0を代入すれば、 0+1→1 1%2→1 1を代入すれば 1+1→2 2%2→0 なんと!!!凄い。 紹介いただいた剰余のページも眼から鱗の事ばかり。。 これもいけそうですね!!ご教授ありがとうございます!
TsukubaDepot

2020/03/28 00:01

方法はひとつではないので、生徒さんの理解度や興味に応じて使い分けるのがいいのではないでしょうか。
guest

0

ベストアンサー

true とfalse、あるいは1と0ではどうでしょう

a= !a;

あるいは

if(a==0) a=1;else a=0;

投稿2020/03/27 13:38

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

norisans

2020/03/27 13:46

早速のお返事ありがとうございます。レスポンスが早くて驚いております。。 boolean型というやつですね。。実は使ったことがなかったので・・・。これは小学生でも使えそうですね!! ありがとうございます!
y_waiwai

2020/03/27 13:50

真と偽、そこからブール代数へと話を広げていきましょう
norisans

2020/03/27 13:52

プログラムに導入したら、すぐに動きました!!! boolean a=true; としておいて、 割り込み時に a=!aですね。 そして、if文で、trueとfalseで分けるという事で・・・ なんて簡単なのでしょうか!!ありがとうございます。
guest

0

とりあえずやりたいことは出来たようなので余計なことを言うと、
-1よりも心配しなきゃいけないことが一杯ある気がします。

aなんていう変数名じゃなくて意味のある名前を使うこととか、
2つしか状態がないのならif()~else~で処理すべきじゃないかとか
似た処理をふたつならべることの是非とか
チャタリングへの対応とか

a=a*(-1);なんてことさえしなければ、小学生だって単純な負の数ぐらい聞きかじっているでしょうし

(そもそも私だったら割り込み使わないなぁ)


コメント頂きました。

今回想定しているのが、

①delayを使ってLEDの点滅を制御。歩行者信号機で、青点灯→点滅→赤 のような感じです。
②スイッチが押されたら、①の青点灯のdelayを待たずに割り込んで、点滅→赤
のようなプログラムなのですが、割り込みを使わないでできる方法があれば、教えてくださいませ。

とのことですので、サンプルを書きました。青点灯10秒->青点滅5秒->赤点灯10秒を繰り返します。それぞれの途中でボタンSWを押す(ピン-GND間短絡)と、時間を待たずに次の状態に遷移します。割り込みは使っていません。

Arduino

1const int BUTTON = 10;//ピンアサインは私の環境に合わせています。適宜変更して下さい 2const int GREEN = 2; 3const int RED = 3; 4 5const int DLY_UNIT = 10;//1ループの時間(ミリ秒) 6const int PERIOD_GREEN = 10 * 1000 / DLY_UNIT;//緑点灯期間(DLY_UNIT単位) 7const int PERIOD_BLINK = 5 * 1000 / DLY_UNIT;//緑点滅期間 8const int PERIOD_RED = 10 * 1000 / DLY_UNIT;//赤点灯期間 9const int BLINK_CYCLE = 0.5 * 1000 / DLY_UNIT;//緑点滅周期 10int count = 0; //時間を計るための変数 11const int CHATFILTER = 100 / DLY_UNIT; //チャタリング除去時間 12bool buttonHistory[CHATFILTER];//チャタリング除去のための履歴 13 14enum STATUS { //LED状態変数 15 STAT_GREEN, 16 STAT_BLINK, 17 STAT_RED 18} stat; 19 20void setup() { 21 for (int i = 0; i < CHATFILTER; i++) { 22 buttonHistory[i] = true; 23 } 24 pinMode(GREEN, OUTPUT); 25 pinMode(RED, OUTPUT); 26 pinMode(BUTTON, INPUT_PULLUP); 27 stat = STAT_GREEN; 28 Serial.begin(115200); 29} 30 31bool checkButtonOn() {//ボタンが「押された」ことを検出する 32 static bool prevButton = true; 33 bool currentButton = true; 34 bool isButtonStable = true; 35 bool ret = false; 36 currentButton = digitalRead(BUTTON); 37 for (int i = 1; i < CHATFILTER; i++) { 38 if (currentButton != buttonHistory[i - 1]) { 39 isButtonStable = false; 40 } 41 buttonHistory[i] = buttonHistory[i - 1]; 42 } 43 buttonHistory[0] = currentButton; 44 if (isButtonStable) { 45 ret = prevButton != currentButton && prevButton; 46 prevButton = currentButton; 47 } 48 return ret; 49} 50 51void loop() { 52 bool green = false; 53 bool red = false; 54 bool isButtonTurnedOn = checkButtonOn(); 55 Serial.println(isButtonTurnedOn); 56 switch (stat) {//状態によって動作を振り分ける 57 case STAT_GREEN: 58 green = true;//緑の点灯処理 59 if (count > PERIOD_GREEN || isButtonTurnedOn) {//次に遷移する条件 60 count = 0;//時間クリア 61 stat = STAT_BLINK;//次の状態へ 62 } 63 break; 64 case STAT_BLINK: 65 green = (count / BLINK_CYCLE) & 1; 66 if (count > PERIOD_BLINK || isButtonTurnedOn) { 67 count = 0; 68 stat = STAT_RED; 69 } 70 break; 71 case STAT_RED: 72 red = true; 73 if (count > PERIOD_RED || isButtonTurnedOn) { 74 count = 0; 75 stat = STAT_GREEN; 76 } 77 break; 78 default: 79 stat = STAT_GREEN; 80 } 81 digitalWrite(RED, red); 82 digitalWrite(GREEN, green); 83 delay(DLY_UNIT); 84 count++; 85}

この程度のプログラムの場合、割り込みを使う使わないは本質ではありません。なんなら、ボタンの検出部分を割り込みを使ったものに置き換えるのも大した手間ではないでしょう。
要は、長時間のdelay()がプログラムの動作を阻害するので、それを短時間のdelay()の繰り返しに置き換えてやる、ということです。あるいは、細切れのdelay()ではなくmillis()を使って時間を計ってもいいですけれど、とにかく長時間のdelay()を使わないことですね。

投稿2020/03/27 14:11

編集2020/03/28 00:58
thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

norisans

2020/03/27 14:32

thkana様 ありがとうございます。 aでなくとも、もちろん良いと思っております。必要に応じて、変数名は使い分けられればよいかと考えています。 ご指摘の中で教えていただきたいのが、 if elseのみで、delayなどで動作をさせるプログラムでの割り込みは可能でしょうか?? 今回想定しているのが、 ①delayを使ってLEDの点滅を制御。歩行者信号機で、青点灯→点滅→赤 のような感じです。 ②スイッチが押されたら、①の青点灯のdelayを待たずに割り込んで、点滅→赤 のようなプログラムなのですが、割り込みを使わないでできる方法があれば、教えてくださいませ。
thkana

2020/03/28 00:41

> aでなくとも、もちろん良い aは良くない、というつもりだったのですが伝わりませんでしたか...「動けばいい」ではなく、ソースリストもドキュメントの一部という考えから、変数名は(関数名等、その他のシンボルも)「名が体を表す」ようにすべきです。 > ご指摘の中で教えていただきたいのが、 それ以外のこともちゃんと伝わっているのか不安ですが... > if elseのみで、delayなどで動作をさせるプログラムでの割り込み すみません、文章に書いてあることが読み取れません。 私が書いた回答でif()~else~云々と言っているのは、質問のプログラムが if(条件A) if(!条件A) という構造になっていることへの指摘で、その部分にはdelayとか割り込みは関係しません。 if()~ else~とdelayと割り込みのどのような関わり方について知りたいのでしょうか。 > 今回想定しているのが プログラムに関わるので、回答を編集して記載します。
norisans

2020/03/30 09:35

thkana様 > aでなくとも、もちろん良い aは良くない、というつもりだったのですが伝わりませんでしたか...「動けばいい」ではなく、ソースリストもドキュメントの一部という考えから、変数名は(関数名等、その他のシンボルも)「名が体を表す」ようにすべきです。 →なるほど。。「ドキュメントの一部」という意識はあまりなかったので、きちんと名前をつけるようにします。ご教授ありがとうございます。 ご提示いただいたプログラムについて →delayではなく、countの積み重ねをする中で、ボタンが押されたどうかの判定を受け付けるという事ですね。 私自身もロボコンなどに出る時にcount等を使うのでdelayの使いにくさはご指摘いただき、さらに納得です。 様々ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問