Atom Liteで距離計測 ~ 表示はM5StickCで!
前回、M5StickCにHC-SR04を接続して距離計測を行いましたが、距離センサーと表示部が繋がっているため、離れた場所の距離計測ができない問題がありました。
そこで今回は、距離センサーと表示部を独立させます。具体的には、距離センサーをAtom Liteで処理して、表示部をM5StickCに任せます。二つの間は、UDPソケット通信でリンクします。
それでは、やってみましょう。
※実際のテストで使っているプログラムは、さらに機能追加しています。そのため、ここで載せているプログラムは、抜粋して且つ適度修正しています。もし、間違いがありましたらご連絡ください。
1.Atom Lite側のプログラム
ポート番号は、Atom Liteが60001、M5StickCが60002を使用することにします。Atom LiteのGPIOは、23番と33番を使用します。
#include "M5Atom.h"
#include <WiFi.h>
#include <WiFiUDP.h>
const char* ssid = "XXXXXXXX"; // Wi-FiのSSID
const char* password = "XXXXXXXX"; // Wi-Fiのパスワード
const int m5StickCPort = 60002; // M5StickCのポート
const int atomPort = 60001; //Atomのポート
WiFiUDP udp;
const char *m5StickCIPAddress = "192.168.XX.XXX"; // M5StickCのIPアドレス
#define S_SEND 23 // 音波の送信
#define S_RECEIVE 33 // 音波の受信
int counts;
int distance;
void print_wifi_state(){
delay(100);
Serial.println("Wi-Fi接続完了");
Serial.println(WiFi.localIP());
delay(100);
}
void setup_wifi(){
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("\nWi-Fi 接続開始");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
}
print_wifi_state();
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
M5.begin();
delay(100);
setup_wifi();
udp.begin(atomPort);
pinMode(S_SEND, OUTPUT);
pinMode(S_RECEIVE, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(S_SEND, HIGH);
delayMicroseconds(10);
digitalWrite(S_SEND, LOW);
counts = pulseIn(S_RECEIVE, HIGH);
distance = (int)(counts * 0.017);
char distancestr[16] ;
uint8_t distancebytes[16] ;
sprintf(distancestr, "%d", distance) ;
memcpy(distancebytes, distancestr, 16) ;
Serial.println("Distanse=");
Serial.println(distancestr);
udp.beginPacket(m5StickCIPAddress, m5StickCPort);
udp.write(distancebytes, sizeof(distancebytes));
udp.endPacket();
delay(500);
}
char型をuint8_tに変換する処理でキャストエラーが出て、対処していますが、良いやり方ではないでしょう。もっといい方法があると思うので、対応してみてください。(memcpyなんて、いつから使っていなかったか分かりません。C言語初期には良く使いました)
2.M5StickC側のプログラム
距離センサーの処理はAtom Liteに任せたので、あくまでも表示のみの処理になります。
#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#define BUFSIZE 1024
const char* ssid = "XXXXXXXX"; // Wi-FiのSSID
const char* password = "XXXXXXXX"; // Wi-Fiのパスワード
const int port = 60002;
WiFiUDP udp;
void print_wifi_state(){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(YELLOW);
M5.Lcd.setCursor(3, 3);
M5.Lcd.println("WiFi connect");
M5.Lcd.print("IP address: ");
M5.Lcd.println(WiFi.localIP());
M5.Lcd.print("Port: ");
M5.Lcd.println(port);
}
void setup_wifi(){
M5.Lcd.setTextColor(RED);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(3, 3);
M5.Lcd.print("Connecting to ");
M5.Lcd.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
M5.Lcd.print(".");
}
print_wifi_state();
udp.begin(port);
}
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
setup_wifi();
M5.Lcd.setTextSize(1);
}
void split(String data, String *lines){
int count = 0;
int datalength = data.length();
for (int i = 0; i < datalength; i++) {
char onec = data.charAt(i);
if ( onec == ',' ) {
count++;
if ( count == 2) {
break ;
}
}
else {
lines[count] += onec;
}
}
}
void loop() {
char packetBuffer[BUFSIZE];
String lines[2] ;
// M5.update();
int packetSize = udp.parsePacket();
if (packetSize){
int len = udp.read(packetBuffer, packetSize);
if (len > 0){
packetBuffer[len] = '\0';
}
split(packetBuffer, lines) ;
Serial.println("Distanse=");
Serial.println(lines[0]);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.setCursor(0, 10, 7);
M5.Lcd.printf("%03d", lines[0].toInt());
M5.Lcd.setCursor(110, 35, 4);
M5.Lcd.print("cm");
}
}
AtomLiteから送られた文字列をsplit関数で分けていますが、距離しか送られてこないので本来は必要ありません。
3.grove端子を使う場合
grove端子を使う方がスッキリします。以下の変更をしてください。
define S_SEND 32 // grove
define S_RECEIVE 26 // grove
4.車の後方センサーなどに使えそう!
冒頭の写真のとおり、センサー部と表示部を分けることができました。これなら、距離センサーを車の後ろに付けて、バックした時の壁までの距離を表示部で確認するといったことができます。
個人的には車間距離の計測をしたいのですが、高精度な距離センサーが必要でしょう。また、車速と合わせて衝突警報も出したいところですが、個人レベルの作成ではかえって危険に陥りそうです。
それでも、今回の仕組みは防犯にも使えそうです。Atom Liteの部分をM5Stampにするなどすれば、実践的な装置も作れるのではないでしょうか。