「Lチカ」プログラムを終えたばかりの方にはいきなりですが「IoT」やりましょう♪
とはいっても「IoTってなに?」の方もいると思いますので簡単に説明を
例えば、電動で動く車のおもちゃの場合、スイッチを入れて床に置くと壁にぶつかるまで走り続けます。
これに「IoT」の技術を組み込むと、スマホで動作/停止を制御できたり、壁にぶつかりそうになったらスマホへ通知して停止したり回避したりすることもできます。
前進だけじゃなく、前後左右に動くものなら、スマホで操作するラジコンにもなりますし、カメラを取り付ければスマホ画面を見ながら床下探検なんてこともできますね。
家の中だと、照明や家電のON/OFFをスマホから一括操作できたり、電力メータを付ければ電力の使用状況を管理して節電に役立てられたりします。
産業用途なら複数の製造ライン上の生産数を一括管理したり、装置の稼働状況を監視して、製造工程の無駄を見つけて作業改善にも役立てられます。
機械の故障や異常(温度、過電流等)が発生した場合は機械を停止させ、その時の状態を担当者へ通知することで、ライン停止を最小限にし再稼働させることができます。
本格的にやるとなるとプログラムもそれなりに複雑で、実際はデータを収集する周辺機器が必要になったりするので、テストプログラムとしてまずはあれですね。
やっぱりやります「スマホでLチカ!」
「IoT」でもやっぱり基本は「Lチカ」ですね。本体のON/OFFボタンでLEDが点灯/消灯しますが、同じようにスマホのON/OFFボタンでも操作できるようにしたものです。LEDの状態はスマホ上で確認可能です。
ローカル接続でJavaScript「fetch」を使用した実用版Wi-Fi遠隔操作の方法は以下リンクで紹介してます。
1.「ATOM LITE」で簡易IoT
「ATOM LITE」 にいろいろ接続してスマホから操作する簡易「IoT」です。
いろいろ接続した写真がこちら(スマホは使い道を模索していたiphon4s)
電源を入れると「ATOM LITE」がアクセスポイントモードで起動します。液晶画面に「SSID」と「PASSWORD」「IPアドレス」が表示されるので、スマホのWiFi接続先選択から「SSID」の「logikara」を選択し「PASSWORD」の「atomlite」を入力すると「ATOM LITE 」と接続されます。
次にブラウザを立ち上げて、アドレスバーに「IPアドレス」の「192.168.4.1」を入力するとスマホに操作画面が表示されます。
スマホ側の「ONボタン」と本体側の「青ボタン」は連動していて、押すと「青色LED」が点灯
スマホ側の「OFFボタン」と本体側の「赤ボタン」は連動していて、押すと「青色LED」が消灯
スマホ画面の「LED」「電圧」「カウント数」は本体の「ATOM LITE 」側の情報を1秒ごとに更新して表示します。
2.各部の動作詳細
青ボタンを押すと青色LEDが点灯し液晶表示の「LED」が「ON」になります。
青ボタンを押している間は液晶表示の「SW0」が「ON」になりボタンを離すと「OFF」になります。
赤ボタンを押すと青色LEDが消灯し液晶表示の「LED」が「OFF」になります。
赤ボタンを押している間は液晶表示の「SW1」が「ON」になりボタンを離すと「OFF」になります。
「ATOM LITE 」の本体ボタンを押すと赤色LEDが点灯し、押した回数がカウントされます。
押すごとに液晶表示の「CNT」の数字が増えて、スマホ画面の「カウント数も」同じ値を表示します。
ボリュームを回すと本体へのアナログ入力電圧が変化します。
液晶画面の「AN0」の左側はアナログ入力値で右側は電圧(V)に換算した値です。
3.使用したもの(部品リスト)
使用した部品リストは以下になります。
ジャンパーワイヤーやピンヘッダ、抵抗内蔵LED等は「秋月電子通商」さんの方が必要な数量、色だけ購入できて送料(600円)を考えても別で購入するのがお得だと思います。
詳細は下の部品表を参照してください。(価格は変更されている可能性があります。)
品名 | 型式等 | 購入先 | 価格 |
---|---|---|---|
ピンヘッダ | 1×40(40P) [ C-00167 ] | 秋月電子通商 | 35円 |
ジャンパーワイヤー | ブレッドボード・ジャンパーワイヤ 14種類×10本 [ P-00288 ] | 秋月電子通商 | 400円 |
抵抗内蔵LED | 抵抗内蔵5mmLED 5V 赤:[ I-06245 ] 青:[ I-06247 ] | 秋月電子通商 | ※色により異なる 1パック(10個)120円~200円 1個15円~25円 |
「M5シリーズ」のユニットを固定するのにはレゴ(テクニック)が「便利です。
各ユニットには2か所の穴が開いているものがほとんどで、この穴にレゴ(テクニック)の「コネクターペグ」等が差し込めます。「リフトアーム」や「プレート」を組み合わせることでいろんな形をつくれます。
4.本体と各ユニットの配線
各ユニットとの配線はブレッドボードを使用します。(雑で申し訳ないですが紹介します。)
「ATOM LITE」を外した状態が下の写真です。「ATOM LITE」裏の端子に合わせてピンヘッダをブレッドボードに差し込んでジャンパー線を写真のように配線して、GROVE付き配線を使用して各ユニットと接続します。
5.プログラム
プログラムも貼っておきますが無駄に長いです。1/3ぐらいは液晶表示のプログラムです。
このプログラムは以下の記事で紹介しているものを組み合わせて作られています。
各プログラムの理解のために確認してみましょう。
#include <M5Atom.h>
#include <M5UnitOLED.h> //M5GFXライブラリ使用
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
// サーバー設定ポート80で接続
WebServer server(80);
// アクセスポイント設定
const char ssid_AP[] = "logikara"; //SSID
const char pass_AP[] = "atomlite"; //パスワード(8文字以上)
// OLED設定(M5GFX)
M5UnitOLED display(26, 32, 400000); // 任意の端子でI2Cを使用する場合(SDA, SCL, FREQ)
M5Canvas canvas(&display);
// FastLED(CRGB構造体)設定
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
return (CRGB)((r << 16) | (g << 8) | b);
}
// 入出力ピン番号設定
#define INPUT_PIN0 25 //入力ピン(外部ボタン)
#define INPUT_PIN1 21
#define OUTPUT_PIN0 22 //出力ピン(LED)
#define OUTPUT_PIN1 19
#define AN_PIN0 33 //アナログ入力ピン
// グローバル変数設定
float an_val0; //アナログ入力値格納用
float anv0; //アナログ入力電圧換算
bool sw_sig0; //外部青ボタン信号
bool sw_sig1; //外部赤ボタン信号
bool btn_sig0; //ブラウザONボタン信号
bool btn_sig1; //ブラウザOFFボタン信号
char led[] = "OFF"; //LED状態(ON/OFF)格納用配列
int count = 0; //カウント数格納用
// htmlメイン画面データ
String html = "";
void htmlData() {
html = "\
<!DOCTYPE html><html lang=\"jp\"><head>\n\
<meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\
<meta http-equiv=\"refresh\" content=\"1; URL=/\">\n\
<title>REMOTE-CONTROLLER</title>\n\
<style>\n\
body{font-family: sans-serif; background-color: #22578b; max-width: 480px; margin: 0 auto; align-items: center;}\n\
h1 {color:#ffffff; text-align: center; font-size: 28px; margin: 10px auto;}\n\
div {display: flex; flex-direction: row; justify-content: center;}\n\
.btn {height: 70px; width: 100px; color: rgb(44, 43, 43); background-color: #dddde9; font-size: 18px; font-weight: bold; border-radius: 7%; margin: 0 10px; -webkit-appearance: none;}\n\
td {width: 110px; color:#ffffff; text-align: center; font-size: 18px;}\n\
</style></head><body>\n\
<h1>REMOTE-CONTROLLER</h1>\n\
<div>\n\
<button class=\"btn\" onclick=\"location.href='/get/btn_on'\">ON</button>\n\
<button class=\"btn\" onclick=\"location.href='/get/btn_off'\">OFF</button>\n\
</div>\n\
<div style = \"margin-top: 20px;\">\n\
<table border = \"1\">\n\
<tr><td>LED</td><td>" + (String)led + "</td></tr>\n\
<tr><td>電圧</td><td>" + (String)anv0 + "</td></tr>\n\
<tr><td>カウント数</td><td>" + (String)count + "</td></tr>\n\
</table>\n\
</div>\n\
</body></html>\n";
}
//-------------------------------------------------
// 関数
//-------------------------------------------------
/********* クライアントにWebページ(HTML)を返す *********/
void handleRoot() {
htmlData(); //htmlデータ更新
// レスポンス200を返し、htmlデータ送信
server.send(200, "text/html", html);
}
/********** クライアントにエラーメッセージを返す **********/
void handleNotFound() { //ファイルが見つかりません
server.send(404, "text/plain", "File not found!");
}
/************** ブラウザボタンON受信 **************/
// ブラウザONボタン処理
void btnOn() {
btn_sig0 = 1; //ブラウザONボタン信号を1
htmlData(); //htmlデータ更新
// レスポンス200を返し、htmlデータ送信
server.send(200, "text/html", html);
Serial.println("BTN_ON!");
}
// ブラウザOFFボタン処理
void btnOff() {
btn_sig1 = 1; //ブラウザOFFボタン信号を1
htmlData(); //htmlデータ更新
// レスポンス200を返し、htmlデータ送信
server.send(200, "text/html", html);
Serial.println("BTN_OFF!");
}
/******************* OLED表示 *******************/
// ページ0:タイトル表示
void oledPage0() {
canvas.clearDisplay(); //表示クリア
canvas.setFont(&fonts::Font4); //フォント
canvas.setCursor(0, 0); //座標を指定
canvas.printf("Starting\nAP Mode!!"); //メッセージ
canvas.pushSprite(5, 5); //描画
}
// ページ1:SSID、パスワード、IPアドレス表示
void oledPage1() {
canvas.clearDisplay(); //表示クリア
canvas.setFont(&fonts::Font2); //フォント
canvas.setCursor(0, 0); //座標を指定
canvas.print("SSID: ");
canvas.println(ssid_AP);
canvas.print("PASS: ");
canvas.println(pass_AP);
canvas.print("IP = ");
canvas.println(WiFi.softAPIP());
canvas.pushSprite(5, 5); //描画
}
/******************* wifi接続 *******************/
//アクセスポイント設定
void softAPWifiConnect() {
WiFi.softAP(ssid_AP, pass_AP); //ソフトAP設定
// WiFi.softAPConfig(ip, ip, subnet); //IPアドレス指定
oledPage0(); //タイトル表示
delay(2000); //タイトル表示時間
oledPage1(); //SSID、パスワード、IPアドレス表示
// シリアル出力
Serial.println("Starting Access Point!!");
Serial.printf("SSID:%s\n", ssid_AP);
Serial.printf("PASS:%s\n", pass_AP);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
Serial.println("WiFi connected!!");
delay(4000); //SSID、パスワード、IPアドレス表示時間
}
/********************* Webサーバー設定 ********************/
void serverSet() {
server.on("/", handleRoot); //ルートアクセス時の応答関数を設定
server.onNotFound(handleNotFound); //不正アクセス時の応答関数を設定
server.on("/get/btn_on", btnOn); //ボタンオン受信処理
server.on("/get/btn_off", btnOff); //ボタンオフ受信処理
server.begin(); //Webサーバー開始
}
//-------------------------------------------------
// 初期設定
//-------------------------------------------------
void setup() {
M5.begin(true, false, true); //Serial,POWER,LED
Serial.begin(9600); //標準のシリアル通信設定
while (!Serial) {}; //シリアル接続待ち
Serial.println("\nM5Atom Lite setup");
// 本体LED設定
M5.dis.drawpix(0, dispColor(20, 20, 20)); //LED点灯(白)
// OLED(M5GFX)設定
display.init();
display.setRotation(1); //表示方向(コネクタ位置):0下、1右、2上、3左
canvas.setColorDepth(1); //モノクロ
canvas.setTextWrap(false); //自動改行をしない
canvas.setFont(&fonts::Font2);//フォント(Font0,2,4/ 6,7,8(数字のみ))
canvas.setTextSize(1); //文字サイズ
canvas.createSprite(display.width(), display.height());
// 通信設定
softAPWifiConnect(); //アクセスポイント
serverSet(); //サーバー
// 入出力端子設定
pinMode(INPUT_PIN0, INPUT_PULLUP); //入力端子
pinMode(INPUT_PIN1, INPUT_PULLUP);
pinMode(OUTPUT_PIN0, OUTPUT); //出力端子
pinMode(OUTPUT_PIN1, OUTPUT);
digitalWrite(OUTPUT_PIN0, LOW); //出力初期化(OFF)
digitalWrite(OUTPUT_PIN1, LOW);
pinMode(AN_PIN0, ANALOG); //アナログ入力端子
}
//-------------------------------------------------
// メイン
//-------------------------------------------------
void loop() {
server.handleClient(); //クライアントからのアクセス処理
M5.update(); //ボタン状態更新
// アナログ入力処理
an_val0 = analogRead(AN_PIN0); //アナログ入力取得
anv0 = (3.3 / 4096) * an_val0; //電圧換算
// ボタン状態格納
sw_sig0 = digitalRead(INPUT_PIN0); //青(ON)ボタン状態格納
sw_sig1 = digitalRead(INPUT_PIN1); //赤(OFF)ボタン状態格納
//青ボタンまたはブラウザONボタンが押されたら
if ((sw_sig0 == 0) || (btn_sig0 == 1)) {
digitalWrite(OUTPUT_PIN0, HIGH); //出力0 ON(青色LED)
M5.dis.drawpix(0, dispColor(0, 0, 200)); //本体LED(青)
strcpy(led, "ON"); //出力0(青色LED)状態ブラウザ表示
btn_sig0 = 0; //ブラウザボタン信号初期化
}
//赤ボタンまたはブラウザOFFボタンが押されたら
if ((sw_sig1 == 0) || (btn_sig1 == 1)) {
digitalWrite(OUTPUT_PIN0, LOW); //出力0 OFF(青色LED)
M5.dis.drawpix(0, dispColor(20, 20, 20)); //本体LED(白)
strcpy(led, "OFF"); //出力0(青色LED)状態ブラウザ表示
btn_sig1 = 0; //ブラウザボタン信号初期化
}
// 本体スイッチ処理
if (M5.Btn.wasPressed()) { //本体ボタンが押されていれば
count++; //カウント+1
digitalWrite(OUTPUT_PIN1, HIGH); //出力1 ON(赤色LED)
M5.dis.drawpix(0, dispColor(200, 0, 0)); //本体LED(赤)
}
if (M5.Btn.wasReleased()) { //本体ボタンが離されていれば
digitalWrite(OUTPUT_PIN1, LOW); //出力1 OFF(赤色LED)
if ((String)led == "ON") { //本体LEDの状態で分岐
M5.dis.drawpix(0, dispColor(0, 0, 200)); //本体LED(青)
} else {
M5.dis.drawpix(0, dispColor(20, 20, 20)); //本体LED(白)
}
}
// OLED表示
canvas.clearDisplay(); //表示クリア
canvas.setFont(&fonts::Font2); //フォント
canvas.setCursor(0, 5); //座標を指定(1行目)
canvas.print("SW0: "); //SW0(青)状態表示
if (sw_sig0 == 0) {
canvas.print("ON ");
} else {
canvas.print("OFF");
}
canvas.setCursor(70, 5); //座標を指定(1行目)
canvas.print("SW1: "); //SW1(赤)状態
if (sw_sig1 == 0) {
canvas.print("ON ");
} else {
canvas.print("OFF");
}
canvas.setCursor(0, 24); //座標を指定(2行目)
canvas.printf("LED: %s", led); //LED状態
canvas.setCursor(70, 24); //座標を指定(2行目)
canvas.printf("CNT: %d", count);//カウント数
canvas.setCursor(0, 43); //座標を指定(3行目)
canvas.print("AN0: "); //アナログ値
canvas.printf("%.0f", an_val0);
canvas.setCursor(90, 43); //座標を指定(3行目)
canvas.printf("%.2fV", anv0); //アナログ値電圧換算
canvas.pushSprite(0, 0); //描画したcanvasを座標を指定して表示
delay(100);
}
長い~「コピペ」の限界を感じる・・・
他にも以下のリンクでいろいろなマイコンボードを使用したプログラムを開発環境の準備と合わせて紹介してますので確認してみましょう。
コメント