小人さんぽいもの
前回の、Arduino NANO(互換機)
で小さい本体をながめているうち、小学生をちょっと不思議がらせるような「中に小人さんがいるっぽい」もの作りたいなと思ったんですね。(実は別の人が離れたところからこっそりスマホでコントロールするやつです。)前回、LCDに出力することをやっています。あとBluetooth HC-05をつないで、「スマホから送られてきた情報を表示する」でいいわけです。
HC-05のつなぎ方についてはこちら。
ひとまず組み上げました。
ただし、テスト段階では MEGAを使っておいて、最後にNANOに置き換えます。
あと、I2Cについては
にあるように、
(UnoやNanoでは A4 (SDA), A5 (SCL)ですが、)
Mega2560は 20 (SDA), 21 (SCL)なので
こんな具合。
でも、USBハブを介してPCにつないでみたら、どうもLCDの表示が不安定。いつもの「電源容量が足りない問題」のようです。
テスト段階でLCDの電源はPCと別系統からとることにしました。
だんだんごちゃごちゃしてきたけれど、これでLCDの表示は安定しました。
スケッチの方は、最初こんな感じで書いてみました。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
void setup() {
lcd.init();
lcd.backlight();
Serial2.begin(9600);//38400ではない
}
void loop() {
if(Serial2.available() > 0){
lcd.print(Serial2.read());
}
}
Bluetoothの HC-05に繋がっているSerial2(MEGAの場合)から受信した内容をそのままLCDに送ります。
これで例えばスマホからBluetoothでabと送信すると
アスキーコードでa が97,bが98 CRが13 LFが10ですな。
文字列で受信したいので、readStringUntilという関数を使います。
この関数は終端文字を指定するんですけど、扱いやすいようにLFだけにしました。スマホ側のBluetoothターミナルソフト(私の場合はKai Morichさんの「Serial Bluetooth Terminal」を使っています)
で
この設定を「CR+LF」から「LF」に変更しました。これでもう一回先ほどのスケッチを実行して「ab」を送信。
無事「97981310」(a b CR LF)が「979810」(a b LF) になりました。終端文字に'\n'を指定して
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
void setup() {
lcd.init();
lcd.backlight();
Serial2.begin(9600);//38400ではない
}
void loop() {
if(Serial2.available() > 0){
lcd.clear();
lcd.print(Serial2.readStringUntil('\n'));
}
}
これで
文字列が送られてくるたびに、表示をクリアしてその文字列を表示するようになり、ひとまずこれで目的は達しました。
ただですね、折角、1行16文字、2行で32文字まで表示できるLCDなのに、17文字以上入れると、うしろが切れちゃいます。どうやらこのLCD、内部的には1行40文字のようです。40文字を超える長い文字列を入れると2行目にその後の文字列が表示されるんですけど、17文字目からそこまでは見えません。これではもったいないので17文字目から32文字目を2行目に表示(あとは無視)するように書きかえてみます。受信した文字列を17文字目で切り分けます。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
String receiveStr;
void setup() {
lcd.init();
lcd.backlight();
Serial2.begin(9600);//38400ではない
}
void loop() {
if(Serial2.available() > 0){
lcd.clear();
receiveStr=Serial2.readStringUntil('\n');
lcd.setCursor(0, 0);
lcd.print(receiveStr.substring(0,16));
lcd.setCursor(0, 1);
lcd.print(receiveStr.substring(16,32));
}
}
長い文字列(32文字まで)もOKになりました。
さて、MEGAだとかさばる
ので、NANOにしましょう。ただ、すぐできるかと思いきや、手持ちのNANO(互換機)のSerial RXピン(2番)がなんかおかしい。TXピンからの信号は出ているんですがRXピンに来た信号を読んでいないみたいでした。USBポートでPCとの通信はできているので、Serial受信機能が丸ごと壊れているわけではないんでしょうけど。同じ機種の予備があればこの個体の問題かどうか比較検証できるんですけど、台湾は、ステイホームが呼び掛けられている最中なので買いに行くのももままなりません。
仕方が無いので、かわりになんとなくあまり使いたくなかったSoftwareSerialを試すことにしました。デジタル11番ピンをRX、10番ピンをTXにします。
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
LiquidCrystal_I2C lcd(0x27,16,2);//アドレス0x3Fの場合もある。
SoftwareSerial mySerial(11, 10); //RX, TX
String receiveStr;
void setup() {
lcd.init();
lcd.backlight();
mySerial.begin(9600);//38400ではない
}
void loop() {
if(mySerial.available() > 0){
lcd.clear();
receiveStr=mySerial.readStringUntil('\n');
lcd.setCursor(0, 0);
lcd.print(receiveStr.substring(0,16));
lcd.setCursor(0, 1);
lcd.print(receiveStr.substring(16,32));
}
}
これで、目的は達成しました。
スマホ用モバイルバッテリーからの給電で、無線通信できています。こんな具合。隣の部屋からでも操作できました。
だいぶすっきりしたかと思います。
ちょうど、紅茶の紙箱が空いたので入れてみました。
「箱の中の小人さんがなんでも答えてくれるよ」
「日本の首都は?」
今回、安定した文字列の送受信を行うことができると確認できたので、ラジコンなどの細かい制御にも応用できそうだと、夢は広がります。
拡大