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

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

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

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

Q&A

解決済

1回答

1138閲覧

Arduino Nano キッチンタイマー作成

yama_u

総合スコア16

Arduino

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

0グッド

0クリップ

投稿2023/01/29 08:30

前提

タイトルの通り、Arduinoとマイコンボードを利用して、キッチンタイマーを作成しています。

実現したいこと

A2ボタンを押したときに、カウントダウンを開始させたい。
つまり、if (st==0)内のswitch文のcase 0:(144行目)を実行したい。ちなみに、case 1:case 2:は実行される。

発生している問題・エラーメッセージ

カウントダウンが開始されない。つまり。st=1に切り替わらない。analogRead()を使っていることに関しては指摘しないでほしいです。仕様で決められているので。
ちなみに、switch文の内容をiで条件分岐せずに、for文に直接書く(つまり、i=0~3毎回実行する)となぜかcase 0 の内容が実行されます。

該当のソースコード

20~102行目はエラーとはあまり関係ないです。

c

1#define SEG_G 3 2#define SEG_F 4 3#define SEG_E 5 4#define SEG_D 6 5#define SEG_C 7 6#define SEG_B 8 7#define SEG_A 9 8#define SEG7_BIN0 10 9#define SEG7_BIN1 11 10 11#include <TimerOne.h> 12#include "pitches.h" 13 14unsigned int timecount = 0; 15byte st = 0; // ステータス0~2 16// 0:時間設定用モード(起動時) 17// 1:カウントダウン開始 18// 2:カウントダウン終了。1度Beepが鳴ると、時間設定用モードに切り替わる。 19 20struct note { 21 unsigned int frequency; 22 unsigned long duration; 23}; 24 25struct note melody[] = { 26 {NOTE_D5, 500} 27}; 28 29void setup() { 30 // 7SEG用pinの設定 31 pinMode(SEG_G, OUTPUT); 32 pinMode(SEG_F, OUTPUT); 33 pinMode(SEG_E, OUTPUT); 34 pinMode(SEG_D, OUTPUT); 35 pinMode(SEG_C, OUTPUT); 36 pinMode(SEG_B, OUTPUT); 37 pinMode(SEG_A, OUTPUT); 38 39 // 欠けているピンの設定を行う 40 pinMode(SEG7_BIN1, OUTPUT); 41 pinMode(SEG7_BIN0, OUTPUT); 42 43 pinMode(2, OUTPUT); 44 45 pinMode(16, INPUT); //A2 モード切り替え用ボタン 46 pinMode(17, INPUT); //A3 インクリメント 47 pinMode(A6, INPUT); // デクリメント 48 pinMode(A7, INPUT); 49 Serial.begin(9600); 50 51 Timer1.initialize(1000000); 52 Timer1.attachInterrupt(count_down); 53 Serial.begin(9600); 54} 55 56void write_a_digit(byte digit, byte data) { 57 58 // 2bit で表示桁を指定するためのエンコード 59 static const byte SEG7_DIG0[] = {1, 0, 1, 0}; 60 static const byte SEG7_DIG1[] = {1, 1, 0, 0}; 61 62 // 2bit で表示桁を指定 63 digitalWrite(SEG7_BIN0, SEG7_DIG0[digit]); 64 digitalWrite(SEG7_BIN1, SEG7_DIG1[digit]); 65 66 // 対応する数字  0 1 2 3 4 5 6 7 8 9 67 static const byte SEG_GP[] = {0, 0, 1, 1, 1, 1, 1, 0, 1, 1}; 68 static const byte SEG_FP[] = {1, 0, 0, 0, 1, 1, 1, 0, 1, 1}; 69 static const byte SEG_EP[] = {1, 0, 1, 0, 0, 0, 1, 0, 1, 0}; 70 static const byte SEG_DP[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 1}; 71 static const byte SEG_CP[] = {1, 1, 0, 1, 1, 1, 1, 1, 1, 1}; 72 static const byte SEG_BP[] = {1, 1, 1, 1, 1, 0, 0, 1, 1, 1}; 73 static const byte SEG_AP[] = {1, 0, 1, 1, 0, 1, 1, 1, 1, 1}; 74 75 if (data < 10) { // 0~9 の時はその数字を表示 76 digitalWrite(SEG_G, SEG_GP[data]); 77 digitalWrite(SEG_F, SEG_FP[data]); 78 digitalWrite(SEG_E, SEG_EP[data]); 79 digitalWrite(SEG_D, SEG_DP[data]); 80 digitalWrite(SEG_C, SEG_CP[data]); 81 digitalWrite(SEG_B, SEG_BP[data]); 82 digitalWrite(SEG_A, SEG_AP[data]); 83 } else { // 10 以上の時は数字でも文字でも無いパターンを表示 84 digitalWrite(SEG_G, 1); 85 digitalWrite(SEG_F, 0); 86 digitalWrite(SEG_E, 0); 87 digitalWrite(SEG_D, 1); 88 digitalWrite(SEG_C, 0); 89 digitalWrite(SEG_B, 0); 90 digitalWrite(SEG_A, 1); 91 } 92} 93 94void clear_7seg() { 95 digitalWrite(SEG_G, 0); 96 digitalWrite(SEG_F, 0); 97 digitalWrite(SEG_E, 0); 98 digitalWrite(SEG_D, 0); 99 digitalWrite(SEG_C, 0); 100 digitalWrite(SEG_B, 0); 101 digitalWrite(SEG_A, 0); 102} 103 104void count_down() { 105 if (st == 1) { 106 timecount--; 107 } 108} 109 110 111void loop() { 112 static unsigned long clicked = 0; // スイッチ押し始めの時刻 113 static unsigned long last_beat = 0; // キーリピートした時刻 114 unsigned int now; // 現在時刻 115 unsigned int tmp; // 10 進数に変換するための一時変数 116 int tmp_sw[4]; // 一時的に読み取った値を保持 117 byte current_sw[4] ; // 現在のスイッチの状態を保持 118 static byte last_sw[] = {0, 0, 0, 0}; // 一つ前のスイッチの状態を保持 119 static byte digit[] = {0, 0, 0, 0}; // 各スイッチに対応する値を保持 120 byte i; // ループ制御変数 121 const unsigned long repeat_delay = 1000; 122 const unsigned long interval = 200; 123 124 now = millis(); // 現在時刻を記憶 125 126 // 統一して扱うために全てアナログで読む。 127 // index と表示位置の関係は一対一。 0 右端の桁、3 左端の桁 128 tmp_sw[0] = analogRead(A2); 129 tmp_sw[1] = analogRead(A3); 130 tmp_sw[2] = analogRead(A6); 131 tmp_sw[3] = analogRead(A7); 132 133 if (st == 0) { 134 for (i = 0; i <= 3; i++) { // 全てのタクトスイッチ(桁)について 135 // 読み取った値が閾値以上なら current_sw[i] の値を 1 にする。 136 if (200 <= tmp_sw[i]) { 137 current_sw[i] = 1; 138 } else { 139 current_sw[i] = 0; 140 } 141 last_sw[i] = current_sw[i]; // 一つ前のキーの値を今の値で更新 142 143 switch (i) { 144 case 0: 145 if (last_sw[i] == 0 && current_sw[i] == 1) { 146 // カウントダウン開始 147 st = 1; 148 } 149 break; 150 151 case 1: 152 if (last_sw[i] == 0 && current_sw[i] == 1) { 153 // timecountのインクリメント 154 timecount += 1; 155 clicked = now; 156 } 157 if (last_sw[i] == 1 && current_sw[i] == 1) { 158 if ( repeat_delay <= now - clicked && interval <= now - last_beat ) { 159 timecount += 1; 160 last_beat = now; 161 } 162 } 163 break; 164 165 case 2: 166 if (last_sw[i] == 0 && current_sw[i] == 1 && timecount > 0) { 167 // timecountのディクリメント 168 timecount -= 1; 169 clicked = now; 170 } 171 if (last_sw[i] == 1 && current_sw[i] == 1 && timecount > 0 ) { 172 if ( repeat_delay <= now - clicked && interval <= now - last_beat ) { 173 timecount -= 1; 174 last_beat = now; 175 } 176 } 177 break; 178 } 179 } 180 } 181 182 if ( st == 1) { 183 if (last_sw[0] == 0 && current_sw[0] == 1 && timecount > 0) { 184 // 時間設定モードになる 185 st = 0; 186 } 187 } 188 189 190 /**********************************************************/ 191 /***** ここで count の値を 4 桁の 7segment LED に表示 *****/ 192 /**********************************************************/ 193 tmp = timecount % 3600; 194 195 unsigned int minu = tmp / 60; 196 digit[3] = minu / 10; 197 minu -= digit[3] * 10; 198 digit[2] = minu; 199 200 unsigned int sec = tmp - minu * 60; 201 digit[1] = sec / 10; 202 sec -= digit[1] * 10; 203 digit[0] = sec; 204 205 if (st == 1 && timecount == 0) { 206 st = 2; 207 if (st == 2) { 208 tone(2, melody[0].frequency); // 音を出力 209 delay(melody[0].duration); 210 noTone(2); 211 st = 0; 212 } 213 } 214 215 for (i = 0; i <= 3; i++) { // ここがダイナミック点灯の部分 216 write_a_digit(i, digit[i]); // 一桁出力 217 delay(1); 218 clear_7seg(); // 一度全セグメントを消灯する。 219 // delayMicrosecond(10); 220 } 221}

試したこと

文法ミスがないか、またロジックに変な箇所がないかの確認をしました。
ボードに数字は正しく点灯されていることの確認もしました。

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

Arudino 1.8.19
Windows10

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

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

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

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

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

guest

回答1

0

ベストアンサー

141行目で、 last_sw[i] と current_sw[i] の値を同じにしているので、 case 0 の中の 条件が成立することはないからではないでしょうか。

c++

1 last_sw[i] = current_sw[i]; // 一つ前のキーの値を今の値で更新 2 switch (i) { 3 case 0: 4 if (last_sw[i] == 0 && current_sw[i] == 1) { 5 // カウントダウン開始 6 st = 1; 7 } 8 break;

投稿2023/01/29 08:42

TakaiY

総合スコア12765

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

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

yama_u

2023/01/29 08:44

そうでした。キーの更新はswitch文の後でした。ありがとうございます。
yama_u

2023/01/29 08:50

すいません、`last_sw[i] = current_sw[i];`をfor文内のswitch文が閉じた後に書いたのですが、結果が変わりませんでした。。
TakaiY

2023/01/29 09:20 編集

指摘したように、状態の変化とその状態になったときにどのような動作をするかについて、ログを仕込むなどして確認してみるのがいいのではないこと思いますよ。 たとえば、ちょっと見ただけで、133行目 if (st == 0) があって判定で st = 1 と したとすると、182行目の if (st == 1) も同レベルなので、ここに入ってしまいますけどいいんですか?、いろいろありそうです。
yama_u

2023/01/29 09:26

はい、if (st==1){}が原因でした。見直してみます。
yama_u

2023/01/29 09:49

if(st==0||st==1)のくくりにs==0とs==1のif文を入れ、countdown()が始まると、boolean型のisCountDownというグローバル変数がtrueになり、s==1の条件にisCountDownを追加して、カウントダウンが始まったあとにA2ボタンを押すと、再度st==0(時間設定モード)に戻るようにしたところ、上手く実装できました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問