自作武器を作ろうず

<!--リトルカブにカブ90(HA02)のエンジン積んで,ペットボトルロケットでロケットランチャーを作り,ChromebookでETロボコン出て,Arduinoでウンコ妨害装置る沖縄の学生のブログです。院生になりました-->


DIPロータリースイッチの値を10進数の0~16に変換する「ダサい例」

スポンサードなんとか

買ったスイッチはこれ。
akizukidenshi.com


   0~9,A~F で合計 16 の値を取ることができるロータリースイッチを買ったのですが,シリアルモニタに"0010"って表示させることには成功したものの,肝心の「value = 2」って感じでデータとして扱うまでに一苦労しました。忘れないうちに書いときます。





手順1,シリアルモニタにロータリースイッチの状態を表示させる。

  これは簡単にできました。DIPロータリースイッチの使い方 [Arduino]様の記事*1そっくりそのまま真似したら出来ましたので本稿では割愛します。



手順2,ロータリースイッチのONとOFFの羅列を,10進数(0~15)に変換する

【2017/11/18 加筆】teppodone.hatenadiary.jp
↑こっちのスマートな書き方しましょう。

こっから下のやり方は悪い例です。こんなお手本のようなクソダサ冗長メンドクサコード書いてはいけません。



  こっからが本題です。ロータリスイッチの1番ピン,2番ピン,4番ピン,8番ピンで,それぞれ 0 または 1 の状態が出力されますが,これを long型の10進数( 0~15)で表します。

以下,例として

  • 8番ピン…0
  • 4番ピン…0
  • 2番ピン…1
  • 1番ピン…0
…すなわち2進数の「0010」の状態から, 10進数の「2」に変換します。







こんなコードになりました。

/* * * * * * * * * * *
 * description : DIPロータリースイッチの値を10進数に変換するコード。
 * author: teppodone (http://teppodone.hatenadiary.jp)
 * note: https://www.petitmonte.com/robot/howto_rotary_switch.html 様と全く同じ回路(ピン番号も同じ)を組んでいることを想定しています。

 これをコピペしてコンパイルして,スイッチかちかち回すとシリアルモニタに今の状態が表示されるはずです多分。
*/

#include <stdlib.h>

void setup() {
Serial.begin(9600);
  pinMode(11,INPUT);
  pinMode(2,INPUT);
  pinMode(4,INPUT);
  pinMode(8,INPUT);
}

void loop() {
  //手順2-1,Stringクラスのコンストラクタを生成し,各ピンの状態を文字列に変換して結合する。
  String switchStateString = String(String(digitalRead(8))+String(digitalRead(4))+String(digitalRead(2))+String(digitalRead(11)));

  //手順2-2, StringクラスのtoCharArray()メソッドを使って,StringクラスからChar型に変換する。
  char buf[100];
  switchStateString.toCharArray(buf,switchStateString.length()+1);

  //手順2-3, Char型の"0010"を,strtol()を使ってlong型の10進数「2」に変換する。
  long switchState = strtol(buf, NULL, 2);

  Serial.print(switchState);

  switch(switchState){
  case 0:
  Serial.println("ぜろ");
  break;

  case 1:
  Serial.println("いち");
  break;

  case 2:
  Serial.println("に");
  break;

  default:
  Serial.println("たくさん");
  break;
  }

  delay(1000);
}


そしてコレが実行結果。

f:id:teppodone:20171115234547p:plain
上記コードの実行結果


  上記のコードを3つの手順に区切って説明します。



手順2-1,Stringクラスのコンストラクタを生成し,各ピンの状態を文字列に変換して結合する。
   各々の 0または1の状態を,一度Stringクラス(文字列型?)に変換し,結合します。

  String switchStateString = String(String(digitalRead(8))+String(digitalRead(4))+String(digitalRead(2))+String(digitalRead(7)));

   これで,「8番ピンが0」「4番ピンが0」「2番ピンが1」「1番ピンが0」の状態が,Stringクラスの"0010" という文字列になりました。



手順2-2, StringクラスのtoCharArray()メソッドを使ってChar型に変換する。
  手順2-3で出てくる strol() を使うためには,Stringクラスの"0010"をchar型の”0010”に変換する必要があります。toCharArray()を使ってStringクラスをchar型に変換します。

 char buf[100];
  switchStateString.toCharArray(buf,switchStateString.length()+1);

  これで,「Stringクラスの”0010”」が「char型の"0010"」になりました*2



手順2-3, Char型の"0010"を,strtol()を使ってlong型の10進数「2」に変換する。
  #include <stdlib.h>が必要みたいです。お忘れのないように。

 #include <stdlib.h>

//~(中略)~

  long switchState = strtol(buf, NULL, 2);

   コレで変数switchStateには,スイッチの状態が0~15で格納されるようになりました。
Serial.print(switchState); で,スイッチの状態が0~15で表示されてるのがわかるかと思います。


   switch case文の条件に使うなり煮るなり焼くなり好きに使えます。めでたしめでたし。



…ってか面倒くせぇ

  他にもっと楽な方法ないの??誰か氏おしえてください。

【2017/11/18 加筆】
  あります。コメントにて沖川さんに教えていただきました。
上記のお手本のようなクソダサ冗長メンドクサコード書いてはいけません。
teppodone.hatenadiary.jp
↑こっちのイケメンな書き方しましょう。沖川さん本当にいつも有難うございます。。。








日記

  最近気づいたのですが誠に恐ろしいことに,当ブログ「自作武器を作ろうず」はもうすぐ満5歳。創立6年目に突入します。これも皆様の支え合ってこそです。有難うございます。

来週あたり 5th anniversary みたいな記事書きます。

*1:DIPロータリースイッチの使い方 [Arduino],2017/11/14閲覧

*2: switchStateString.length()+1ですが, +1 が無いと3桁になってしまいます。原因わかりません。char型の末尾のヌル文字1文字が悪さしてるということでしょうか?