PASのブログ

PASの中の人が書く雑記ブログです。

アナマル.8 4chにしてみた。

みなさんこんにちは。 出来る限り平易に書こうとしていますが、平易すぎてペースが遅くありませんか? コメント等お待ちしております。

アナマル.6にて、スイッチが正しく反応するようになりましたので、4ch化していきます。

早速コードを書く。

前回までに作ったコードを並列に並べれば、4ch化は容易に行なえます。 まずはその方法で書いていきましょう。

ちなみに、今回実験用として使うのはこれです。

f:id:pas_fx:20200607113549j:plain
4chバージョンの実験ボード

まず、前回と同じように1chで、かつ、負論理になるように書き換えます。

//SW3
//sw2の負論理版



const int SW1 = A0;
const int LED1 = 7;
int state = 0; //ONOFFの状態を保存
int val = 0; //スイッチの状態を保存
int old_val = 0; //前回の状態を保存

void setup() {
  pinMode(LED1, OUTPUT); //LEDはとりあえず基板上のものを設定。
  pinMode(SW1,INPUT_PULLUP);//A4をデジタルポート入力でプルアップ。
  
}

void loop() {
  val = digitalRead(SW1); //スイッチの状態をvalに入れる
    
  if((val == 1) && (old_val == 0))  
    {
      state = 1 - state; // stateをひっくり返す。
      delay(10);// 10ms待つ。
    }

  old_val = val;  // 処理が済んだので前回の状態にvalをコピーする。

  if(state != 1)
  {
   digitalWrite(LED1, HIGH);   // LEDへの信号をHIGH(点灯)
  }
  else
  {
  digitalWrite(LED1, LOW);    // LEDへの信号をLOW(消灯)
  }

}

変更点は

const int SW1 = A0;
const int LED1 = 7;

と、それに付随して、LED_BILTONをLED1に書き換えた部分。
もう一箇所は、if(state != 1)です。!=は、「イコールでないなら」という意味です。
これで試してみますと、無事動作しました。

さて、ここで気付いたことがありました。
電源投入直後、LED1が点灯しています。
点灯は、リレーONですので、これは困ります。

なので結局はif(state == 1)のままで良いようですね(笑)

さて、これを4つ並べれば良いのですが、メンテナンス性が良くないので配列を使おうと思います。

配列とは

配列とは、複数の変数を1つにまとめたもので、 型名 配列名[要素数]; と書きます。 例えば、学校で1クラス50人の点数を管理する場合、

int tensuu1 =0;
int tensuu2 =0;
・
・
・
int tensuu50 =0;

と、書いても間違いではないのですが、

int tensuu[50] = {0};

と書くことで、変数(数字を入れる器)が50個出来ます。 これを利用します。

//SW3
//sw2の負論理版
//変数を配列に


const int SW[4] = {A0,A1,A2,A3};
const int LED[4] = {7,6,5,4};
int state[4] = {0}; //ONOFFの状態を保存
int val[4] = {0}; //スイッチの状態を保存
int old_val[4] = {0}; //前回の状態を保存

void setup() {
  pinMode(LED[1-1], OUTPUT); //LEDはとりあえず基板上のものを設定。
  pinMode(SW[1-1],INPUT_PULLUP);//A4をデジタルポート入力でプルアップ。
  
}

void loop() {
  val[1-1] = digitalRead(SW[1-1]); //スイッチの状態をval[1-1]に入れる
    
  if((val[1-1] == 1) && (old_val[1-1] == 0))  
    {
      state[1-1] = 1 - state[1-1]; // state[1-1]をひっくり返す。
      delay(10);// 10ms待つ。
    }

  old_val[1-1] = val[1-1];  // 処理が済んだので前回の状態にval[1-1]をコピーする。

  if(state[1-1] == 1)
  {
   digitalWrite(LED[1-1], HIGH);   // LEDへの信号をHIGH(点灯)
  }
  else
  {
  digitalWrite(LED[1-1], LOW);    // LEDへの信号をLOW(消灯)
  }

}

今回は変数が多いので

const int SW[4] = {A0,A1,A2,A3};  
const int LED[4] = {7,6,5,4};  
int state[4] = {0}; //ONOFFの状態を保存  
int val[4] = {0}; //スイッチの状態を保存  
int old_val[4] = {0}; //前回の状態を保存  

5つ配列に変更しました。 loop()内の、[1-1]は、本来は[0]と書けば済みますが、わかりやすくするために[1-1]と書いてます。

配列は0から始まるためですので、注意してください。

//SW3
//sw2の負論理版
//変数を配列に
//スイッチ制御を関数として独立


const int SW[4] = {A0,A1,A2,A3};
const int LED[4] = {7,6,5,4};
int state[4] = {0}; //ONOFFの状態を保存
int val[4] = {0}; //スイッチの状態を保存
int old_val[4] = {0}; //前回の状態を保存
int a;
int count = 0; // 1周ループしたら+1


void setup() {
  Serial.begin(9600);
  pinMode(LED[0], OUTPUT); 
  pinMode(LED[1], OUTPUT);
  pinMode(LED[2], OUTPUT);
  pinMode(LED[3], OUTPUT);
  pinMode(SW[0],INPUT_PULLUP);
  pinMode(SW[1],INPUT_PULLUP);
  pinMode(SW[2],INPUT_PULLUP);
  pinMode(SW[3],INPUT_PULLUP);
  
}

void loop() {
  
  a = count % 4;
  sw(a);
  count = count + 1;
  Serial.print(a,DEC);
  
}

void sw(int num){
  val[num] = digitalRead(SW[num]); //スイッチの状態をval[num]に入れる
    
  if((val[num] == 1) && (old_val[num] == 0))  
    {
      state[num] = 1 - state[num]; // state[num]をひっくり返す。
      delay(10);// 10ms待つ。
    }

  old_val[num] = val[num];  // 処理が済んだので前回の状態にval[num]をコピーする。

  if(state[num] == 1)
  {
   digitalWrite(LED[num], HIGH);   // LEDへの信号をHIGH(点灯)
  }
  else
  {
  digitalWrite(LED[num], LOW);    // LEDへの信号をLOW(消灯)
  }

}

このようにしました。loop()がかなり短くなりましたね。 これは、関数という仕組みを使っています。

関数とは

関数とは、既に使っている、 void setup() void loop()

などと同じく、一つのプログラムの塊のことです。
今回のように、同じようなことを繰り返す処理というのはマイコンの場合よくあることなのですが、それを全てloop()の中に書いていくと、ごちゃごちゃしますし、同じことを書くことにもなります。なおかつ、シンタックスエラー(文法上の間違い)や、それのデバッグ(修正)にも労力がかかります。

そこで、例えばこんなことをします。

void setup() {
Serial.begin(9600);
}

void loop() {
int a = sum(2,3);
Serial.print(a, DEC);
}

int sum(int x, int y){
int z = x + y;
return z;
}

これを書き込み、ArduinoIDEの、ツール→シリアルモニタ、で見ると、答えの「5」が延々と書かれます。

シリアルモニタの説明は後日にするとして、関数を説明します。

本来、やりたいことはa = 2+3を計算させてaの値を得ることです。 1回だけならloop()に直接打てばいいのですが、足し算を何十回もするプログラムがあるかもしれません。 そのために、sum()という関数を今回新たに作ります。

int sum(int x, int y)

まず頭のintについては、戻り値と言いまして、呼び出し元に戻す数のデータ型です。整数を戻すので、intにします。
次のsumというのは、一定のルールを守れば自由に決められます。(ここはマイコンによっても違うのでちょっと自信がないです。Arduinoには制約がないかもしれません。)
(int x, int y)は、呼び出し元から2つの整数を渡します、ということです。この渡す数を、引数といいます。
最後に{}の中に処理を書き、返り値はreturn ○○;と返します。

さて、今回のプログラムでは、void sw(int num)としています。
loop()で、0,1,2,3,0,1,2,3....と数えて、数を引数として渡します。
既に、先程、必要な変数は配列にしていますので、引数を利用しやすくなっています。

続きは次回

現段階で、4つのスイッチで4つのLEDのオルタネート動作に成功しましたが、コード解説の一部がまだ終わっていません。

  a = count % 4;
  sw(a);
  count = count + 1;

この部分と、シリアルモニタを使ったデバッグの方法を次回は解説します。