• Skip to main content
  • Skip to primary sidebar
  • Skip to footer
  • HOME
  • Arduino
    • Arduino初心者編
    • Arduino基礎編
    • Arduino応用編
    • Arduino実践編
  • Raspberry Pi
  • microbit
  • XBee
  • Scratch
  • Contact Us
  • Privacy Policy

STEMSHIP

ものづくりを通して、科学を学ぼう!

現在の場所:ホーム / Arduino / Arduino応用編 / ArduinoでSTEM教育​ 応用編:MQTTとNode-REDを用いたLED制御 その1

ArduinoでSTEM教育​ 応用編:MQTTとNode-REDを用いたLED制御 その1

2020年9月29日 by STEMSHIP 1 コメント

Node-REDを使用して、Arduinoの入出力をコンピュータからGUI操作する方法を紹介します。例として、今回はLED制御(ON/OFF、明るさ調整、アナログ値の時系列グラフ表示)をブラウザ上のユーザーインターフェースで行います。Node-REDは、やってみるとそれほど難しくなく、IoT機器/アプリを作ってみたいという方にはおすすめです。

MQTTブローカーソフトウェア

図1. ネットワーク接続図

この実験ではコンピュータがブローカーとクライアントの両方の役割を持ちます。
クライアントの1つ「MQTT.fx」は通信プロセスを理解できるよう、MQTTの通信トラフィックを表示するために使用します。
もう1つのクライアント「Node-RED」はArduino/ESPで読み取ったアナログ値の表示やLEDの制御を行うブラウザ上のユーザーインターフェースを提供するために使用します。

最初に、3つのプログラムをインストールします。

1つ目はMQTTブローカーとなるMosquittoです。ダウンロードページからインストーラファイルをダウンロードしてください。

https://mosquitto.org/download/

Windowsの場合は、インストーラの実行ファイル(.exe)を実行します。設定はデフォルトのまま、変更は必要ありません。

図2. Mosquittoのインストール

続いて、MQTT通信のトラフィックを表示する、MQTT.fxをインストールします。
同様にダウンロードページからインストーラファイルをダウンロード・インストールしてください。

https://mqttfx.jensd.de/index.php/download

最後に、MQTTクライアントとしてNode-REDをインストールします。
Node-REDを実行するために、Node-jsというプラットフォームが必要なので、こちらを先にインストールします。
ダウンロードページからインストーラファイルをダウンロードしてください。

https://mosquitto.org/download/

Windowsの場合は、インストーラの実行ファイル(.msi)を実行します。設定はデフォルトのまま、変更は必要ありません。

https://nodejs.org/ja/download/

図3. Node-jsのインストール

Node-jsプラットフォームのインストールが完了したら、Node-REDアプリケーションをインストールします。
コマンドプロンプトを開きます。Windowsではスタートメニューを開き、「cmd」と入力します。

図4. スタートメニューで「cmd」で検索してコマンドプロンプトを起動

コマンドプロンプトで次のように入力します。

node –version && npm -version

Enterキーを押して、バージョンが表示されればNode-jsが正しくインストールできています。
エラーメッセージが出た場合は、再度インストールを試してください。

図5. バージョン情報が表示された

次のコマンドで、Node-REDのインストールを開始します。

npm install -g –unsafe-perm node-red

Enterキーを押すと、Node Package ManagerがNode-REDをダウンロード・インストールしてくれます。

図6. インストール中はメッセージが次々に表示されます。

これで、MQTTの実験の準備が整いました。ここからはArduino/ESPをプログラミングしていきます。

プログラミングの準備

まず、Arduino IDEのライブラリマネージャから必要なライブラリ「PubSubCluent.h」をダウンロード・インストールします。
作者名は「by Nick O’Leary」となっているはずです。

図7. 「PubSubClient」ライブラリを使用します

スケッチを作成する前に、MQTTブローカー(ここではパソコン)のIPアドレスを調べておきます。
コマンドプロンプトでコマンド「ipconfig」を入力し、Enterキーを押します。
ネットワーク接続が一覧で表示されます。

図8. ipconfigを実行したところ

このうち、「IPv4アドレス」を今回は使用します。図8では「192.168.1.137」です。これで、MQTTプラットフォームを利用した実験を進められます。
前回までの実験と同様、ArduinoやESPで可変抵抗から読み取ったアナログ値を表示し、ArduinoやESPに接続したLEDのON/OFF制御、ここでは加えてPWMによる明るさの調整を行います。

イーサネットシールド用のプログラム

まずはArduinoとEthernet Shieldを使用する場合のスケッチを見てみましょう。
後にESP8266とESP32のスケッチも示します。これらは少しだけプログラムが異なっています。

#define LEDPIN 3
#define ANALOGPIN 0
#define MQTT_BROKER "192.168.1.137"

#include "SPI.h"
#include "Ethernet.h"
#include "PubSubClient.h"  //(1)
 
byte MAC[] = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56};
 
EthernetClient ethClient;
PubSubClient mqttClient(ethClient);  //(2)

long Timer = 0;
char Buffer[50];

void setup()
{
  pinMode(LEDPIN, OUTPUT);
  Serial.begin(115200);
  delay(100);
  Serial.println("My IP-Adresse: ");  
  Ethernet.begin(MAC); 
  delay(3000);   
  Serial.println(Ethernet.localIP());             
                       
  mqttClient.setServer(MQTT_BROKER, 1883);  //(3)
}

void loop()
{ 
  if (!mqttClient.connected())  //(4)
    reconnect();

  mqttClient.loop();  //(5)

  if(millis() > Timer)  //(6)
  {
    String AnalogValue = String(analogRead(ANALOGPIN));
    AnalogValue.toCharArray(Buffer, 20);  //(7)
    mqttClient.publish("Arduino/AnalogValue", Buffer);  //(8)

    Serial.println("Published Value: " + AnalogValue);
    Timer = millis() + 5000;
  }
  Ethernet.maintain();
}

void subscribeReceive(char* Topic, byte* UserData, unsigned int Length)  //(9)
{
  Serial.println("### Receive ###");
  Serial.print("Topic: ");
  Serial.println(Topic);  //(10)

  Serial.print("User Data: ");
  for(int i = 0; i < Length; i ++)
    Serial.print(char(UserData[i]));
  Serial.println("");
  
  byte Brightness = atoi(UserData);  //(11)
  Serial.print("Brightness: "); Serial.println(Brightness);
  analogWrite(LEDPIN, Brightness);

  Serial.println("-----------------");
}

void reconnect()  //(12)
{
  while(!mqttClient.connected())  //(13)
  {
    Serial.print("Connect with MQTT.");
    
    if(!mqttClient.connect("EthernetClient"))  //(14)
    {
      Serial.print("Error: ");
      Serial.print(mqttClient.state());
      Serial.println("Try again in 5 seconds.");
      delay(5000);
    }
      
    mqttClient.setCallback(subscribeReceive);  //(15)
    mqttClient.subscribe("Arduino/LED");  //(16)
  }
}

(1) MQTTライブラリを読み込みます。

(2) オブジェクトmqttClientがクライアントを表します。

(3) 「setServer()」関数でクライアントに接続するブローカーを決定します。
パソコンにインストールしたMosquittoを利用するので、パソコンのIPアドレスを指定します。Mosquittoはデフォルトでポート1883を使用します。

(4) メインの処理を行う前に、ブローカーに接続できているかチェックします。接続されていなければ「reconnect()」関数を呼び出し、ブローカーへの接続を試みます。電源を入れたり、リセットしたりした直後にも一度実行します。

(5) PubSubCliantライブラリではメインループの任意の場所でクライアントオブジェクトの「loop()」関数を呼び出して、ブローカーが新しいメッセージを送信したかどうかをチェックします。

(6) このif条件は5秒ごとにtrueとなって内部の処理を実行し、可変抵抗のアナログ読み取り値をブローカーに送信します。

(7) このライブラリでは送信する値をchar配列で送る必要があるので、オブジェクト関数「toCharArray()」で文字列オブジェクトのアナログ値をchar配列にコピーします。

(8) 「publish()」関数でトピックとメッセージをMQTTネットワークに送信します。引数の1つ目にトピック、2つ目にメッセージを指定します。ここでは省略していますが、3つ目にtrueを指定するとリテイナーが有効になります。

(9) 「subscribeReceive」関数はブローカーからメッセージを受信したときにライブラリから呼び出されます。

(10) この例ではトピックによって動作を変えることは行っておらず、ただシリアルモニタに表示しているだけです。

(11) メッセージの内容は文字列として受け取ります。「atoi()」関数(ACSII to Integer)で整数に変換することで、LEDのPWM制御に利用できるようになります。

(12) 「reconnect」関数はMQTTブローカーに最初に接続するときや、接続しなおすときに呼び出されます。

(13) MQTT接続ができるまで、接続動作を繰り返します。

(14) 「connect()」関数を使用して接続を行います。引数にはネットワーク接続を表すオブジェクトの名前を指定します。

(15) 接続が確立されると、(9)の「subscribeReceive」関数が呼び出されます。

(16) トピック「Arduino/LED」を受け取ります。

ESP8266用のプログラム

続いて、ESP8266のプログラムです。

#define LEDPIN D3
#define ANALOGPIN A0

#define NETWORKNAME "MyWLAN"
#define PASSWORD "Password"
#define MQTT_BROKER "192.168.1.137"

#include "ESP8266WiFi.h"
#include "PubSubClient.h"
 
WiFiClient espClient;
PubSubClient mqttClient(espClient);

long Timer = 0;
char Buffer[50];
 
void setup()
{
  pinMode(LEDPIN, OUTPUT);
  Serial.begin(115200);
  delay(100);
  Serial.println();
  Serial.print("Connect with WLAN: ");
  Serial.println("My WLAN");//Serial.println(NETWORKNAME);

  WiFi.begin(NETWORKNAME, PASSWORD);

  while (WiFi.status() != WL_CONNECTED)  //(1)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Successfully. My IPaddress: ");
  Serial.println(WiFi.localIP());
  
  mqttClient.setServer(MQTT_BROKER, 1883);
}

void loop()
{ 
  if (!mqttClient.connected())
    reconnect();

  mqttClient.loop();

  if(millis() > Timer)
  {
    String AnalogValue = String(analogRead(A0));
    AnalogValue.toCharArray(Buffer, 20);
    mqttClient.publish("Arduino/AnalogValue", Buffer);

    Serial.println("Published Value:  " + AnalogValue);
    Timer = millis() + 5000;
  }
}

void subscribeReceive(char* Topic, byte* UserData, unsigned int Length)
{
  Serial.println("### Receive ###");
  Serial.print("Topic: ");
  Serial.println(Topic);
  
  Serial.print("UserData: ");
  for(int i = 0; i < Length; i ++)
    Serial.print(char(UserData[i]));

  Serial.println("");
  byte Brightness = (UserData[0]-'0')*100 + (UserData[1]-'0')*10 + (UserData[2]-'0');  //(2)
  Serial.print("Brightness: "); Serial.println(Brightness);
  analogWrite(LEDPIN, Brightness);

  Serial.println("-----------------");
}

void reconnect()
{
  while (!mqttClient.connected())
  {
    Serial.print("Connect with MQTT.");
    
    if (!mqttClient.connect("ESP8266Client"))
    {
      Serial.print("Error: ");
      Serial.print(mqttClient.state());
      Serial.println("Try again in 5 seconds.");
      delay(5000);
    }
  }
  mqttClient.setCallback(subscribeReceive);
  mqttClient.subscribe("Arduino/LED");
}

(1) webサーバーの例の時と同様、WiFi接続が確立するまでそれ以降の処理の実行を待ちます。

(2) ESP8266のコンパイラではatoi()関数が使用できません。ここでは、手動で文字列を数値に変換しています。

ESP32用のプログラム

ESP32では、analogRead()関数やanalogWrite()関数が使えないため、さらに変更を行います。

#define LEDPIN 4
#define PWM_CHANNEL 0  
#define ANALOGPIN ADC1_CHANNEL_4 

#define NETWORKNAME "MyWLAN"
#define PASSWORD "Password"
#define MQTT_BROKER "192.168.1.137"

#include "WiFi.h"
#include "driver/adc.h"  //(1)
#include "PubSubClient.h"
 
WiFiClient espClient;
PubSubClient mqttClient(espClient);

long Timer = 0;
char Buffer[50];
 
void setup()
{
  pinMode(LEDPIN, OUTPUT);
  Serial.begin(115200);
  delay(100);
  Serial.println();
  Serial.print("Connect with WLAN: ");
  Serial.println("My WLAN");//Serial.println(NETWORKNAME);

  WiFi.begin(NETWORKNAME, PASSWORD);

  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Successfully. My IPaddress: ");
  Serial.println(WiFi.localIP());
  
  mqttClient.setServer(MQTT_BROKER, 1883);

  adc1_config_width(ADC_WIDTH_BIT_10);  //(2)
  adc1_config_channel_atten(ANALOGPIN,ADC_ATTEN_DB_11); 
  ledcSetup(PWM_CHANNEL, 5000, 8);   //(3)
  ledcAttachPin(LEDPIN, PWM_CHANNEL);  //(4)
}
 
void loop()
{
  if (!mqttClient.connected())
    reconnect();

  mqttClient.loop();

  if(millis() > Timer)
  {
    String AnalogValue = String(adc1_get_raw(ANALOGPIN));
    AnalogValue.toCharArray(Buffer, 20);
    mqttClient.publish("Arduino/AnalogValue", Buffer);

    Serial.println("Published Value:  " + AnalogValue);
    Timer = millis() + 5000;
  }
}

void subscribeReceive(char* Topic, byte* UserData, unsigned int Length)
{
  Serial.println("### Receive ###");
  Serial.print("Topic: ");
  Serial.println(Topic);
  
  Serial.print("UserData: ");
  for(int i = 0; i < Length; i ++)
    Serial.print(char(UserData[i]));
  Serial.println("");

  byte Brightness = (UserData[0]-'0')*100 + (UserData[1]-'0')*10 + (UserData[2]-'0');
  Serial.print("Brightness: "); Serial.println(Brightness);
  ledcWrite(PWM_CHANNEL, Brightness);  //(5)
 
  Serial.println("-----------------");
}

void reconnect()
{
  while (!mqttClient.connected())
  {
    Serial.print("Connect with MQTT.");
    
    if (!mqttClient.connect("ESP8266Client"))
    {
      Serial.print("Error: ");
      Serial.print(mqttClient.state());
      Serial.println("Try again in 5 seconds.");
      delay(5000);
    }
  }
  mqttClient.setCallback(subscribeReceive);
  mqttClient.subscribe("Arduino/LED");
}

(1) アナログ入力の追加ライブラリについてはwebサーバーの例で使用したのと同じものを使用します。

(2) webサーバーの例と同様に、アナログ入力に関する設定を行います。

(3) ESP32では16チャンネルのPWMが用意されています。(LEDコントローラと呼ばれています)
LEDコントローラを使用するには3つの引数を用意して「ledcSetup()」関数を呼び出します。
1つ目の引数でチャンネル、2つ目でPWMの周波数、3つ目で分解能をそれぞれ指定します。

(4) LEDコントローラを出力端子に割り当てます。

(5) 「ledcWrite()」関数がArduinoでいうところのanalogWrite()関数に対応します。

スケッチのアップロード後、パソコン上でクライアントMQTT.fxを使用して、クライアントが動作するかテストを行います。
Arduino+Ethernet Shieldを使用する場合も、ESP8266/ESP32を使用する場合も、この先の手順は同じになります。

この続きは次回にしたいと思います。

Filed Under: Arduino応用編 関連タグ:IoT, LED, MQTT, Node-RED

Reader Interactions

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。

最初のサイドバー

CONTACT US

  • Facebook
  • Twitter
  • Youtube

More to See

Arduinoベースのセンサノード:XBeeデータ収集ノードの製作

2021年9月27日 By STEMSHIP

Arduinoベースのセンサノード:Arduinoを使った温度センサの作製

2021年9月21日 By STEMSHIP

XBeeモジュールとBMP280センサを使用してデータ収集する

2021年5月31日 By STEMSHIP

XBeeモジュールでMicroPythonを使ってセンサを読み取る

2021年5月24日 By STEMSHIP

XBeeモジュールでセンサを読み取る:センサノードの設定と測定

2021年5月17日 By STEMSHIP

カテゴリー

  • Arduino (44)
    • Arduino初心者編 (15)
    • Arduino基礎編 (11)
    • Arduino実践編 (4)
    • Arduino応用編 (11)
    • Arduino番外編 (3)
  • MakeyMakey (1)
  • microbit (11)
  • Raspberry Pi (13)
  • Scratch (6)
  • STEM教育 (5)
  • XBee (15)
  • ものづくり教育 (2)
  • 子供の教育 (2)
  • 科学 (6)
  • 算数 (5)

Tags

BLE DCモータ EEPROM ELEGOO ESP32 ESP8266 IoT LCD LED makeymakey MQTT Node-RED scratch STEM教育 WiFi XBee アニメーション オンラインゲーム カメラ クローン ゲーム コスチュームの変更 サーボモータ ステッピングモータ ステートマシン スピーカ タイマー ピンポン ブロック定義 ペン ライントレース ラジコン リスト 分数 割り込み 実験 工作 幼児 当たり判定 温度センサ 無線通信 物理 角度制御 重力 音楽

Footer

最近の投稿

  • Arduinoベースのセンサノード:スケッチ(プログラム)の作製
  • Arduinoベースのセンサノード:XBeeデータ収集ノードの製作
  • Arduinoベースのセンサノード:Arduinoを使った温度センサの作製
  • XBeeモジュールとBMP280センサを使用してデータ収集する
  • XBeeモジュールでMicroPythonを使ってセンサを読み取る

タグ

BLE DCモータ EEPROM ELEGOO ESP32 ESP8266 IoT LCD LED makeymakey MQTT Node-RED scratch STEM教育 WiFi XBee アニメーション オンラインゲーム カメラ クローン ゲーム コスチュームの変更 サーボモータ ステッピングモータ ステートマシン スピーカ タイマー ピンポン ブロック定義 ペン ライントレース ラジコン リスト 分数 割り込み 実験 工作 幼児 当たり判定 温度センサ 無線通信 物理 角度制御 重力 音楽

Search

2025年5月
月 火 水 木 金 土 日
 1234
567891011
12131415161718
19202122232425
262728293031  
« 10月    

Copyright © 2025 · STEMSHIP.COM