質問: 'off01'){ digitalWrite(LED_PIN, LOW); //LEDを消灯させた後okを返信 Serial.print("ok\n"); Serial.flush(); } } ```
回答: 最初の間違いは「文字リテラル(定数)」と「文字列リテラル」の区別が出来ていないこと。文字リテラル'A'は単に数値65の意味(ASCIIコード環境下。なお、''の中に複数の文字を入れてもエラーにはならないことが多いですが、その使い方は通常しない、と思っておいていいです。それでも本気で知りたければその旨聞いて下さい)。一方、文字列リテラル"A"はどこかにデータ'A''\0'を置いたそのアドレス(ポインタ)の意味になります。今回は文字列として比較するのですから、比較対象は文字列リテラル。 で、文字列の中身の比較をするのならstrcmp()関数を使うのがまず第一案。 strcmp()関数は、第1/第2パラメータの文字列が等しければ0を返すので `if(strcmp(dat,"on01")==0){ //datの中身が"on01"に等しければ` とします。 なお、`dat=="on01"`は文字列の在り処の比較なので、意図した動きにはなりません。 でも、せっかく文字列型が用意されているのだから使わなきゃもったいないし、String型を使うのならもっと使い込まなきゃもったいない。 まず。 String型に対する==演算子はArduinoでは文字列の中身の比較をちゃんと(?)やってくれます。 を読めば、 > > The operator == and the method equals() perform identically. > > > と書いてあります。つまり `if(String(dat)=="on01"){`で先のstrcmp版と同様の結果が得られます。String::equals()で書きたいのなら別に止めませんが... で、Stringを使うと、文字列の格納スペースとか、最後に'\0'をつけることとかは基本的には気にする必要がなくなります。なので、datをそもそもString型にして `String dat="";` として宣言すれば、countの管理は不要。さらにcがchar型の値とすれば `dat+=c;` で文字列を成長させることが出来ます。また、やりたければ行頭や行末のホワイトスペース(スペース、改行、水平タブ)を除去するtrim()を使って`dat.trim()`なんてことも出来ます。 先程の比較も、わざわざString型のオブジェクトを生成する必要もなく、 `if(dat=="on01"){`でOK。 速度やメモリ容量に厳しいプログラム(あるいはC言語の基礎修行)でないのなら、String型を使っちゃえばよいのでは。 つぎに。 全体の構成の話ですが、現状は ``` 1文字受信して 文字列を成長させて コマンド検出/実行 ``` という構成になっています。でも、コマンド検出/実行は、文字列が確定してからやるものではないでしょうか? ``` 1文字受信して コマンド文字列確定? ならば コマンド検出/実行 でなければ 文字列成長 ``` 成長中の文字列を覗くから、途中で実行しちゃうみたいな現象が起こるのです。 話は変わって、 Serial.flush();。多分、OS環境下のCでprintf()がデータをバッファに貯めることがあるという話を聞きかじってそれを真似たものだと思いますが、それはあくまでその処理系でのprintf()関数の話。ArduinoのSerial::flush()は全く別の意味、用途を持っています。その意味、用途を以てここに使っているのですか? まぁ、この場合使っても害はなさそうですが... もう一点、Serial.print("文字列\n"):としているのはなぜでしょう? 特別な意図が無いのなら、Serail.println("文字列");とした方がよろしいかと思います。これも大きな害はないですけれど。 そんなこんなを盛り込むと、loop()関数の一例としてはこんなところでは。 ``` //入力された文字を入れる変数 String dat = ""; void loop() { //文字列を読み込む if (Serial.available()) { char c = Serial.read(); if ( c == '=') { // 終了文字を受信した場合 //dat.toLowerCase();//必要に応じて。全部小文字に変換 Serial.println(dat); //出力 //読み込んだ文字が「on01」のときシリアルモニタに「ON」を送り、LEDを点灯させる if (dat == "on01") { digitalWrite(LED_PIN, HIGH); //LEDを点灯させた後okを返信 Serial.println("ok"); } else //読み込んだ文字が「off01」のときシリアルモニタに「OFF」を送り、LEDを消灯する if (dat == "off01") { digitalWrite(LED_PIN, LOW); //LEDを消灯させた後okを返信 Serial.println("ok"); } else //入力確認 //読み込んだ文字が「in01」のとき if (dat == "in01") { //DIN_PINの状態をon/offで返信 int value; value = digitalRead( DIN_PIN ); if ( value == HIGH ) { //HIGHがOFF,LOWがON Serial.println("off"); } else { Serial.println("on"); } }else{ Serial.println("Command ERROR."); } dat = ""; } else { if (dat.length() < 5) {//これ以下でないとコマンドに絶対に一致しないのでデータを保存する意味がない。 dat += c; //dat.trim();//必要に応じて。前後のホワイトスペース文字を除く } } } } ```