• 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教育​ 応用編:イーサネットシールドでIoTウェブサーバーを作る 

ArduinoでSTEM教育​ 応用編:イーサネットシールドでIoTウェブサーバーを作る 

2020年9月5日 by STEMSHIP コメントを書く

Arduinoに接続したセンサーの値をパソコンに表示したり、パソコンからLEDのON/OFFをコントロールします。どのようにするかというと、Arduinoをwebサーバーとして動かし、パソコンからアクセスできる簡単なHTMLページを作ります。LAN用のルーターとイーサネットシールドをイーサネットケーブルで接続して使用します。イーサネットシールドは、WIZnet社のTCP/IP処理専用モジュールのW5500を搭載したシールドがよく用いられます。扱い易いおすすめのシールドは、Arduino イーサネットシールド2で、Micro SDカードリーダとしても使用できます。

図1. Arduino イーサネットシールド2

LEDと可変抵抗の配線図

LEDと可変抵抗を接続します。図2はArduino Unoから直接配線している図になっていますが、実際にはArduino UNOの上にイーサネットシールドを載せてあるので、ジャンパー線はイーサネットシールドのソケットにさすことになります。

図2. 接続図(イーサネットシールドの下にはArduino UNOがあります)

イーサネットシールドのRJ45(LAN)コネクタとルーターをLANケーブルで接続します。ルーターを使わずに直接パソコンに接続することもできますが、PCは通常DHCPサーバー機能を持っていません。DHCPサーバ機能とは、LANに接続した機器にIPアドレスなどのネットワーク設定を自動で割り振る機能のことです。この場合は手動でIPアドレスを割り当てることになります。

IoTサーバーの動作説明

図3のようなHTML(web)ページに可変抵抗の読み取り値を表示し、リンクをクリックすることでLEDの点灯・消灯を切り替えられるようにします。これはwebサイトのアドレスに続くリンクでサーバーにリクエストします。「?on」を続ければLEDが点灯、「?off」を続ければLEDが消灯します。アドレス・サーバー名・ファイル名に続けて命令などの追加のデータを送信する場合、ウェブリクエストでは一般的に「?」(疑問符)をつけて表記します。

この例ではサーバーアドレスが「192.168.1.18」とすると、webページ上のリンク「LEDをONにする」は「192.168.1.18/?on」を、「LEDをOFFにする」は「192.168.1.18/?off」をそれぞれリクエストします。Arduinoウェブサーバーがこのリクエストを受け取り、内容に応じて動作します。

図3. Webブラウザでの表示結果

対応するHTMLソースは以下の通りです。簡略化のため、本来あるべき<head>、<body>の部分を省略していますが、ウェブブラウザでは正しく表示することができます。本来のHTMLやウェブデザインに関心があれば、HTMLについてのウェブページや書籍を参考にしてください。

<!DOCTYPE HTML>
<html>
アナログ値:240
<br><br>
<a href='?on'>LEDをONにする</a>
<br><br>
<a href='?off'>LEDをOFFにする</a>
</html>

HTMLはタグという呼ばれるコマンドを使ってwebページを組み立てていきます。タグは<>で囲まれています。<br>は改行を行うタグ、<a>はクリック可能なリンクを作成するタグです。本来はリンクしたいアドレスをすべて記載しますが、リンク先が同じサーバー上の場合にはアドレス部分を省略することができます。

このHTMLソースを生成し、LEDのON/OFFの切り替えリクエストに対応するスケッチが必要になります。Arduinoには「Ethernet.h」というライブラリが最初からインストールされています。

IoTサーバーのプログラム

次のスケッチをアップロードします。

#define LEDPIN 3
#define ANALOGPIN A0

#include "SPI.h"          //(1)
#include "Ethernet.h"
 
byte MAC[] = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56};  //(2)
 
EthernetServer Server(80);  //(3)
EthernetClient Client;
String Request;
 
void setup()
{
  pinMode(LEDPIN, OUTPUT);
  Serial.begin(115200);  //(4)
  delay(100);
  Serial.println("My IP-Adresse: ");  
  Ethernet.begin(MAC);   //(5)
  delay(3000);   
  Serial.println(Ethernet.localIP());   //(6)

  Server.begin();  //(7)
}
 
void loop() 
{
  Client = Server.available();  //(8)

  if (Client)
  {
    Serial.println("New Client");
    boolean blankLine = true;
 
    while (Client.connected())  //(9)
    {
      if (Client.available())  //(10)
      {
        char c = Client.read();
        if (Request.length() < 100)  //(11)
          Request += c;

        if (c == '\n' && blankLine)  //(12)(13)
        {
          Serial.print("Request from Client: ");
          Serial.println(Request);
          if(Request.indexOf("on")>0)  //(14)
            digitalWrite(LEDPIN,HIGH);  //(15)

          if(Request.indexOf("off")>0)  //(16)
            digitalWrite(LEDPIN,LOW);
                           
           // HTTP Header 200 an den Browser schicken
          Client.println("HTTP/1.1 200 OK");  //(17)
          Client.println("Content-Type: text/html");
          Client.println("Connection: close"); //(18)
          Client.println("Refresh: 2"); //(19)
          Client.println();  //(20)
          Client.println("<!DOCTYPE HTML>");  //(21)
          Client.println("<html>");
          Client.print("アナログ値:");        
          Client.print(analogRead(ANALOGPIN));
          Client.println("<br><br>"); 
          Client.println("<a href='?on'>LEDをONにする</a>");
          Client.println("<br><br>");
          Client.println("<a href='?off'>LEDをOFFにする</a>");
          Client.println("</html>");
  
          Request = "";  //(22)
          break;         //(23)
        }
        
        if (c == '\n')  //(24)
            blankLine = true;
        else if (c != '\r')
            blankLine = false;
      }
    }

    delay(1);  //(25)
    Client.stop();
    Serial.println("client disconnected.");
    Serial.println("");
  }

  Ethernet.maintain();  //(26)
}

スケッチの解説

(1) イーサネットシールドとの通信はSPIで行うので、SPIライブラリを読み込みます。

(2) 通常、ネットワークに接続して使うデバイスはMACアドレスという識別用のアドレスが割り振られていますが、安価な互換シールドにはMACアドレスがありません(Arduinoイーサネットシールド2はMACアドレスが書かれたシールがシールドに貼られています)。MACアドレスはLAN接続する上で必ず必要な物なので手動で設定します。MACアドレスの最初の3バイトはデバイスの製造元を識別するもので、適当な値を入れてしまうと「どのメーカーにも割り当てられていないアドレス」になってしまう可能性があります。接続するルーターやハブの中には、「どのメーカーにも割り当てられていないアドレス」からの接続を拒否するものもあります。割り当てのあるアドレスはwebページ(https://uic.jp/mac/)で調べられます。後半3バイトは任意のアドレスを使用します。

(3) サーバー用・クライアント用のオブジェクトを、ライブラリのクラスから作成します。サーバーとして作成する場合は、リクエストを受け取るポートの番号を引数として渡します。暗号化のされていないwebサイト(httpサイト)では、常に「80」番を使用します。

(4) 今回の例ではシリアルモニタでやり取りするデータ量が多くなっているので、シリアル通信の速度を高速にしています。シリアルモニタの設定も変える必要があります。今回の例ではシリアル通信は動作確認のために取り入れているだけなので、省略することもできます。

(5) 「Ethernet.begin()」関数にMACアドレスを渡すネットワーク接続を開始します。オプションで、2つ目の引数に静的IPアドレスを渡すこともでき、パソコンと直接接続して使用する場合に必要になります。2つ目の引数がない場合には、DHCP経由で自動的にIPアドレスを取得します。

(6) DHCPで取得したIPアドレスを表示します。

(7) 「Server.begin()」関数を実行することでウェブサーバーとして動作し始めます。

(8) リクエストが届いた場合、「Server.available()」関数はそのリクエストを発したクライアントを返します。リクエストがなければfalseを返します。クライアントに応答を返すときに、クライアントのIPアドレスとポートを割り当てることができるようになります。

(9) クライアントとの接続が続いている限り、while文の中を繰り返します。

(10) クライアントからリクエストが届いているか確認します。この段階ではクエリ(リクエスト)の内容は読み込んでいません。

(11) クエリを「Client.read()」関数で1バイトずつ読み取り、文字列オブジェクトRequestに追加していきます。メモリを節約するため、クエリは100バイトまでに制限しています。

(12) クライアントはリクエストの終わりを「空行」を送ることで表現します。「\n」は改行するという意味のヌル文字(実際には表示されない文字)を表し、変数「blankLine」は前回受け取ったリクエストが実際には空行だった場合にtrueになります。この後、リクエストを1バイト(≒1文字)ずつ受け取りながら、リクエストを組み立てていきます。改行コードがその終わりを意味するということです。

(13) リクエストが終了した場合は処理を開始します。

(14) 「indexOF()」関数は文字列オブジェクトの中に引数で渡した文字列があるかどうかを検索する関数です。戻り値は引数の文字列が見つかればその文字列、見つからなければ-1となります。ここではリクエストの文字列に「on」という文字が含まれているかどうかを確認しています。

(15) リクエストに文字列「on」が含まれていればLEDを点灯させます。

(16) 同様に、リクエストに「off」という文字列が含まれていればLEDを消灯します。

(17) リクエストが成功したことをクライアントに返信します。HTTP 200というのが、リクエスト成功という意味です。

(18) 返信後、接続を終了します。

(19) アナログ値を更新するため、2秒ごとに自動でページを再読み込みするよう指示します。

(20) 空行は、ヘッダーデータの終わりとHTTPソースの始まりを示しています。

(21) 先に示したHTMLタグを順番に送信していきます。

(22) 送信終了後、次のリクエストを受け付けられるように、文字列Requestを空にしておきます。

(23) 「break()」関数は条件分岐から条件に関わらず抜け出す命令です。ここではwhileループから抜けて、(25)の行にジャンプします。

(24) 受け取ったリクエストのデータcが改行コード「\n」だった場合に、変数blankLineをtrueに設定します。改行コードではない場合にはfalseに設定します。

(25) 「Client.print()」や「Client.println()」といったコマンドを送った後に、イーサネットモジュールの反応が遅れる場合があるため、1ミリ秒動作を停止した後で接続を終了します。

(26) DHCP経由でIPアドレスを取得した場合、定期的に「Ethernet.mentain()」関数を呼び出す必要があります。DHCPによって割り振られたIPアドレスには有効期限(通常は数時間)があり、期限切れ後にDHCPサーバーが別の機器に同じIPアドレスを割り振ってしまう可能性があります。「Ethernet.mentain()」関数は、DHCPサーバーに取得したIPアドレスの有効期限を延長する連絡をさせる命令です。今回の例ではloop()文を実行するたびに「Ethernet.mentain()」を呼び出していますが、実際に連絡をするのはIPアドレスの有効期限が迫っているときのみです。

スケッチのアップロード後、シリアルモニタを開くとDHCPで割り当てられたIPアドレスを確認できます。このIPアドレスをwebブラウザのアドレスバーに入力するだけで接続でき、webサイトが開きます。同時に、シリアルモニタでリクエストの内容を確認することもできます。

Filed Under: Arduino応用編 関連タグ:LED, イーサネット

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

2023年3月
月 火 水 木 金 土 日
 12345
6789101112
13141516171819
20212223242526
2728293031  
« 10月    

Copyright © 2023 · STEMSHIP.COM