M5StickCPlusでプログラミングpart.2

どうもやなです。今回も引き続きM5StickCPlusでプログラミングをしていこうと思います。まあ電子工作と何が違うんだと言われれば、一応ソフトよりではあるので大目に見ていただければ……

今回はボタンを使いこなそうず

今回はスイッチの一つであるボタンを使って、プログラミングしていこうと思います。
また ”ボタン” のほかに新しい内容として、

  1. 変数の概念

  2. 変数の型

  3. IF文

を学ぼうと思います。れつごー

押しボタンって2種類あんねん

まず押しボタンの動作に2つの種類があることをご存じでしょうか。
モーメンタリとオルタネイトです。「なんそれ?」って感じですが、どちらとも普段私たちが使い慣れているものです。

  • モーメンタリ動作
    押している間だけがON
    になるものです。身近な例でいうとキーボードとかですかね。(ちょっと違うけど)

  • オルタネイト動作
    ボタンを押すたびにONとOFFが切り替わる物を指します。スマホの電源は押すたびに画面が付いたり消えたりするでしょ、あれです。

サンプルコードだ、まずは動かそう

以下にモーメンタリとオルタネイト両方のサンプルコードを載せます。
まずはどっちも実際に書き込んで触ってください!どのような違いがあるのかが一目でわかると思います。中身に関してはまた後で解説します。

モーメンタリ

// ボタン モーメンタリ動作

int led_pin = 10;  // LEDのピン番号
int buttonA = 37;  // ボタンのピン番号

void setup() {
  pinMode(led_pin, OUTPUT);
  pinMode(buttonA, INPUT_PULLUP);
}

void loop() {
  if (digitalRead(buttonA) == HIGH) {
    // buttonAがHIGH(押されている)であれば実行する
    digitalWrite(led_pin, HIGH);
  }
  else {
    // 上のIF文でなければ実行する
    digitalWrite(led_pin, LOW);
  }
  delay(50);
}

オルタネイト

// ボタン オルタネイト動作

int LED = 10;
int BUTTON = 37;

int val = 0; // 入力ピンの状態を記憶しておく用
boolean state = false; // LEDの状態(0ならオフ、1ならオン)

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
}

void loop() {
  // ボタンの状態を変数valに入れる
  val = digitalRead(BUTTON);

  delay(50); // バウンシング解消用の遅延

  // ボタンの状態が変化したか?(直前がLOWで、かつ今はHIGHであるか)
  if ((digitalRead(BUTTON) == HIGH) && (val == LOW)) {
    state = !state;
    digitalWrite(LED, state);
  }
}

今回の学ぶポイント

今回は変数とIF文が新しく出てきたと思います。まずはそこから超軽く学びます。大まかに3つあるので1つずつ学んでいきましょう!

1. 変数ってなんぞや

簡単に言ってしまえば入れ物、箱。一時的に数字やら文字やらを一時的に保存し、あとでまた使いたい!って時におすすめです。
前回くそ真面目にLEDのピン番号を書いていたと思います。

↓↓↓ 前回のコード ↓↓↓

// LEDをチカチカさせるコード、通称 "Lチカ"

// setup関数は最初の一回だけ実行される
void setup() {

  pinMode(10, OUTPUT);    // 指定のピンを出力モードにする

}

// loop関数は無限にループするところ(ここに動作のメインを書く)
void loop(){

  // 指定したピンに、5V or 0Vの電圧を入力するイメージ
  // delayは動作を止めるもの。カッコの中にミリ秒で指定する → 1秒ならdelay(1000)
  digitalWrite(10, HIGH);
  delay(1000);
  digitalWrite(10, LOW);
  delay(500);

}

別に動作には支障はないのですが、もしピン番号が変わった!って時にどうします?その10って数字全部を書き換えなければなりません。だるすぎ。
そんな時に役立つのが変数です。

あらかじめ10という数字を入れた箱(led_pin)を用意し、LEDを光らせる処理ごとに10の代わりにled_pinを書くことでのちの変更がとっても楽になります。また何の数字がも一目でわかることもかなり大事なところです。

2. 変数の型

次に変数の型について伝えておきます。先ほどled_pinという変数がありました。これは整数しか入れられないです。これはint型です。基本変数は使う用途によって型を変えて適切なものを入れていきます。

  • int型:整数

  • float型:浮動小数点

  • char型:文字(一文字)

  • boolean型:真理値(TrueかFalse)

  • string型:文字列(これだけクラスだが他と同じように使える)

などなど。これ以外にもありますし、ほかの言語だとより型があったりします。

3. IF文ってなんぞや

日本語で言うと「もし”ほにゃらら”が起きたら、実行する」って感じですかね。今回だと「buttonAが押されたら、LEDを光らせる」とかですね。
使い方は、 if (条件) { 条件が正しかったら実行する } 

// 例:ボタンが押された時の処理

if (digitalRead(buttonA) == HIGH) {
  // buttonAがHIGH(押されている)であれば実行する
  digitalWrite(led_pin, HIGH);
}

ここで上の条件に当てはまらなかった時に実行したい場合は "else" を使います。使い方は先ほどと少し違い条件が入らないため、下のようになります

if (条件) {
  "条件が正しかったら、実行したい処理"
}
else {
  "条件が正しくなかったら、実行したい処理"
}

とりあえずここまで覚えていれば大丈夫です。

今回のプログラムについて

中身について説明していきます。今回新しく使った関数はdigitalRead()pinMode(buttonA, INPUT_PULLUP)呼ばれるものです。

digitalRead(ピン番号)

どんな動作をするかというと、括弧の中で指定されたピンがHIGHかLOWかを判定します。簡単に言ってしまえば、スイッチが押されていたらHIGH押されていなかったらLOWって感じでとりあえずは大丈夫です。

pinMode(ピン番号, INPUT_PULLUP)

引数の二つ目にinputと書いてあります。これはその名の通り、outputの反対で信号の入力を受け付けるモードになります。入力信号があればその都度値に変換したりします。

プルアップについては下の記事を読むとわかりやすいです
(ボタンを使うための特別なものと認識してもらえれば、とりあえずOK)

https://burariweb.info/electronic-work/arduino-learning/digital-input-pullup-pulldown.html

ボタンのピン

さて、実際にボタンはどうやって使うのかって感じですが、今回もM5StickCPlusに内蔵されているボタンを使用します。
ボタンは3つあり、Aボタン、Bボタン、電源ボタンです。

ボタンの場所と名称

電源ボタンは長押しすることで電源を切ることができます。またつけたい場合は一回押せばつきます。

またA, BのボタンはそれぞれG37, G39に繋がっており、LEDと同様ピンを指定することで使うことができます。

ボタンのピン

今回は画面の下側についている大きいボタン(Aボタン)だけ使いますが、ピンの番号を変えたら簡単にBボタンも使えるのでぜひ試してください!

番外編:オルタネイト動作のコード

モーメンタリのコードですが、IF分の説明でもあった通りです。

オルタネイト動作が少し厄介なので頑張ってください
まずは今回使う変数についてです。使うピン番号状態を保存しておく変数がそれぞれ2つずつです。

int LED = 10;
int BUTTON = 37;

int val = 0; // 入力ピンの状態を記憶しておく用
boolean state = false; // LEDの状態(falseならOFF、trueならON)

そしてループするところが下のところです。setup()に関しては同じなので割愛します。やってることはピンの初期設定だけなので

void loop() {
  // ボタンの状態を変数valに入れる
  val = digitalRead(BUTTON);

  delay(50); // バウンシング解消用の遅延

  // ボタンの状態が変化したか?(直前がLOWで、かつ今はHIGHであるか)
  if ((digitalRead(BUTTON) == HIGH) && (val == LOW)) {
    state = !state;
    digitalWrite(LED, state);
  }
}

ループの初めでボタンの状態を持ってきます。その状態を変数valに保存します。保存したら少しの間だけ待ちます、ボタンの状態が変わるのをここで待ちます。

そしたらそのあとのIF文で、LEDを光らせるかどうかを決めます。LEDの状態が変わってほしいときは要するにボタンが押された時です。それをプログラム的に表すとIF文の中のような処理になるわけですね。

// ボタンの状態が変化したか?(直前がLOWで、かつ今はHIGHであるか)
if ((digitalRead(BUTTON) == HIGH) && (val == LOW)) {

コメントでも補足していますが、押された瞬間というのは、ボタンの状態において少し前が押されておらず、今が押されている状態のことを指します。
もっというとちょっと前まで電気的にLOWだったが、今はHIGHって感じ。

この状態が変化した時の処理はどこでも応用できるのでぜひ覚えましょう!

Point:IF文の条件が(条件1)&&(条件2)となってます。これは条件1と条件2がどっちも当てはまっている場合に、実行されます。

LEDを光らせる処理

最後にLEDを光らせる処理ですが、変数stateを用いてONOFFを実現しています。
変数stateはboolean型で定義しました。先ほどはint型という整数だけが入れられる箱でしたが、今回はTrueとFalseだけが入る箱です。

下では一行目で "state""!state" を入れています。これはstateと逆のものを同じstateに入れ直してるイメージです。つまりTrueが入っていたらFalse、Falseが入っていたらTrueを入れます。

state = !state;
digitalWrite(LED, state);

後は最後にdigitalWriteの二つ目の引数にstateを入れることで、実行するたびに点灯→消灯→点灯→消灯→……と交互にすることができます!

まとめ

今回は新しいものが多く、説明が難しかったので読みにくかったかもしれません。しかしプログラミングにおいて重要な要素である変数と型、IF文について学びました。これらはどの言語でも共通で使うのでぜひ覚えておいて損はありません。

次回もブザーや画面などを用いつつ、プログラミングで重要なものをやっていこうと思います。また今回のプログラムも自分でアレンジしてみてください。

今回も拙い文章ではありましたが、ご覧いただきありがとうございました。ではまた

この記事が気に入ったらサポートをしてみませんか?