今回は、プログラムを作る流れについて紹介し、前回の記事「7セグ回路を作ってみた(Part2 実装・動作確認)」の動作確認に用いたプログラムについて解説します。

プログラムの設計

まずはどんなプログラムを作るかを考える必要があります。

プログラムの大まかな処理内容は、以下の二点になります。
①7セグでカウントアップを表現する
②タクトスイッチが押される度に、ドットの点灯・消灯を切り替える

大まかな処理内容から直接コードが書ける人は必要ありませんが、フローチャートを作成するとよりプログラムを理解しやすくなり、書きやすくなります。
以下の図は、今回の処理内容を表したフローチャートです。

使用した7セグは2桁のため、ループ1では0-99の値で繰り返します。
セグメントの制御は一瞬で終わるため、カウントアップが高速で進んでしまいます。そこでループ2を作成し、同一の処理を繰り返すことで高速で進んでしまう問題を解決しました。

割り込み処理とは、通常のプログラムを強制的に中断し、別のプログラムを実行する処理方法です。割り込み終了後は、元のプログラムが再開されます。カウントアップしている途中でタクトスイッチが押されたら、D.P.の状態を反転しなければならないのでこの処理方法を実装しました。
D.P.はデシマルポイントの略で小数点を指します。

プログラム内容の解説

さきほどのフローチャートを元にプログラムの内容が整理できたら、実際に以下のコードを書きます。

 1. boolean Number[10][7] = {
    // 0  1  2  3  4  5  6  pin/i
 2.   {0, 0, 1, 0, 0, 0, 0},  //0
 3.   {0, 1, 1, 1, 0, 1, 1},  //1
 4.   {1, 0, 0, 1, 0, 0, 0},  //2
 5.   {0, 0, 0, 1, 0, 1, 0},  //3
 6.   {0, 1, 0, 0, 0, 1, 1},  //4
 7.   {0, 0, 0, 0, 1, 1, 0},  //5
 8.   {0, 0, 0, 0, 1, 0, 0},  //6
 9.   {0, 1, 1, 0, 0, 1, 0},  //7
10.   {0, 0, 0, 0, 0, 0, 0},  //8
11.   {0, 0, 0, 0, 0, 1, 0}   //9
12. };

13. volatile boolean dot = 1;

14. void setup() {
15.   pinMode(0, OUTPUT);
16.   pinMode(1, OUTPUT);
17.   pinMode(2, OUTPUT);
18.   pinMode(3, OUTPUT);
19.   pinMode(4, OUTPUT);
20.   pinMode(5, OUTPUT);
21.   pinMode(6, OUTPUT);
22.   pinMode(7, OUTPUT);
23.   pinMode(8, OUTPUT);
24.   pinMode(9, OUTPUT);
25.   pinMode(10, INPUT);
26.   attachInterrupt(10, Interrupt(), FALLING);
27. }

28. void loop() {
29.   for (int num = 0; num < 100; num++) {
30.     for (int Delay = 0; Delay < 200; Delay++) {
31.       digitalWrite(8, LOW);
32.       digitalWrite(7, HIGH);
33.       for (int i = 0; i < 7; i++) {digitalWrite(i, Number[num / 10][i]);}
34.       delay(1);
35.       digitalWrite(8, HIGH);
36.       digitalWrite(7, LOW);
37.       for (int i = 0; i < 7; i++) {digitalWrite(i, Number[num % 10][i]);}
38.       delay(1);
39.       digitalWrite(9, dot);
40.     }
41.   }
42. }

43. void Interrupt() {dot = !dot;}

プログラムの各部分について説明します。

 1. boolean Number[10][7] = {
    // 0  1  2  3  4  5  6  pin/i
 2.   {0, 0, 1, 0, 0, 0, 0},  //0
 3.   {0, 1, 1, 1, 0, 1, 1},  //1
 4.   {1, 0, 0, 1, 0, 0, 0},  //2
 5.   {0, 0, 0, 1, 0, 1, 0},  //3
 6.   {0, 1, 0, 0, 0, 1, 1},  //4
 7.   {0, 0, 0, 0, 1, 1, 0},  //5
 8.   {0, 0, 0, 0, 1, 0, 0},  //6
 9.   {0, 1, 1, 0, 0, 1, 0},  //7
10.   {0, 0, 0, 0, 0, 0, 0},  //8
11.   {0, 0, 0, 0, 0, 1, 0}   //9
12. };

1-12行目では、0-6番ピンに接続されている各セグメントのカソードに出力する値をブーリアン型の二次元配列で定義しています。
ブーリアン型とは、True(真)とFalse(偽)の2種類の値しか代入できないデータ型のことです。なお、プログラム内ではTrueは1、Falseは0で表記されます。

13. volatile boolean dot = 1;

13行目では、ブーリアン型でD.P.用の変数を定義しています。この変数は割り込み処理内で使うため、修飾子としてvolatileキーワードを設定しています。なぜこの修飾子が必要なのかは分かっていませんが、公式レファレンスに付けるべきと書いてありました。詳しくは以下の公式レファレンスを読んでください。

参照:Arduino Reference(attachInterrupt())

15.   pinMode(0, OUTPUT);
16.   pinMode(1, OUTPUT);
17.   pinMode(2, OUTPUT);
18.   pinMode(3, OUTPUT);
19.   pinMode(4, OUTPUT);
20.   pinMode(5, OUTPUT);
21.   pinMode(6, OUTPUT);
22.   pinMode(7, OUTPUT);
23.   pinMode(8, OUTPUT);
24.   pinMode(9, OUTPUT);
25.   pinMode(10, INPUT);

15-25行目では、pinMode関数で0-10番ピンの入出力を設定しています。
ここからsetup関数に入っています。
setup関数とは、ボードに電源を入れた時やリセットした時、一度だけ実行される関数です。関数名の通り、基本的に初期設定をここに書きます。

26.   attachInterrupt(10, Interrupt(), FALLING);

26行目では、割り込み処理の初期設定をしています。第一引数はトリガーとするピン番号、第二引数は割り込み時実行する関数、第三引数はトリガーのモードを設定するようになっています。
トリガーのモードには、
LOW(ピンがLOWのとき)、CHANGE(ピンの状態が変化したとき)、RISING(ピンの状態がLOWからHIGHに変わったとき)、FALLING(ピンの状態がHIGHからLOWに変わったとき)の4種類があります。
今回はFALLINGを使いました。
ここまでがsetup関数になります。

29.   for (int num = 0; num < 100; num++) {

29行目は、フローチャートのループ1にあたるfor文です。
ここからloop関数に入っています。
loop関数とは、setup関数が実行された後、その名の通り繰り返し実行される関数です。

30.     for (int Delay = 0; Delay < 200; Delay++) {

30行目は、フローチャートのループ2にあたるfor文です。

31.       digitalWrite(8, LOW);
32.       digitalWrite(7, HIGH);

31,32行目では、上位桁を制御するためにアノードを切り替えています。

33.       for (int i = 0; i < 7; i++) {digitalWrite(i, Number[num / 10][i]);}

33行目では、digitalWrite関数で各セグメントのピンに対してLEDのON/OFFを設定しています。Numberの要素を指定するために、変数numを10で割ることで上位桁を取り出しています。

34.       delay(1);

38.       delay(1);

34,38行目では、各桁の制御後は切替前に一瞬止めるように制御しています。

35.       digitalWrite(8, HIGH);
36.       digitalWrite(7, LOW);

35,36行目では、下位桁を制御するためにアノードを切り替えています。

37.       for (int i = 0; i < 7; i++) {digitalWrite(i, Number[num % 10][i]);}

37行目では、digitalWrite関数で各セグメントのピンに対してLEDのON/OFFを制御しています。Numberの要素を指定するために、変数numを10で割った余りを使って下位桁を取り出しています。

39.       digitalWrite(9, dot);

39行目では、D.P.のON/OFFを制御しています。デフォルトではOFFになっていますが、割り込み処理が実行されることで変数の値が変わるためONになります。
ここまでがloop関数になります。

43. void Interrupt() {dot = !dot;}

43行目では、割り込み処理の内容になります。「!変数」でブーリアン型は1と0が反転するため、それを用いています。

テスト

実運用などを考慮したプログラムを作っている場合は、運用中にバグが起きてはいけないため、複数の視点や条件から判定を行うテストの重要性が高くなります。

今回はマイコンボードで動かすプログラムなので、実際に書き込むことで動作のテストが行うことができます。

for文を1行で書く場合は、後の追加で複数行に渡る可能性があるので、波括弧{}で括ることをおすすめします。
インデントや空白を調整することで可読性を上げることも大切です。
このようなことが欠陥を減らす技術として活きていきます。

The following two tabs change content below.

なかひろ

高専3年生です。 普段はプログラムいじってますが、最近は基板設計などもかじってます。 よろしくお願いします!