Arduinoを使ってよう

小学校でもプログラミングの授業がはじまりました。プログラミングを勉強すると、考え方や物事の進め方を学ぶことができるそうです。。。でもただ、勉強するだけでは面白くないよね。そう、高専では目的を持ってプログラムを学びます。今日は熱中症対策組込システムを作製するぞ!

0.準備


袋の中身を確認しましょう。ちゃんと入っていますか?

 

@マイコンボード

AUSB通信ケーブル

B温湿度センサー

Cジャンパー線 メス−メス 3

DフルカラーLED

Eジャンパー線 オス−オス 7

F袋


 

1.使うマイコンボードはこれだ!

使うボードはこれだ! マイコンボードと呼ばれている。真ん中にあって黒い四角いところから銀色の足が3方向に出ている。合計で38本の銀色の端子が出ているのが、このマイコンボードの本体で、中にはコンピュータの計算を司るCPUCentral Processing Unitと呼ばれるコア部分と、その他LEDを点けたりスイッチの入力を読み取ったりある程度の情報を覚えることができるメモリが詰め込まれているぞ!

 


2.パソコンとマイコンボードを接続してみよう!

パソコンのUSBポートとマイコンボードをUSB通信ケーブルで接続します。

接続すると、マイコンボード上の電源ランプが青色に点灯します。電源ランプが点灯していない人はスタッフに声をかけてください・・・ケーブルの接続不良か、あるいはマイコンボードが壊れているかもしれません。


 

3.開発環境を動かしてプログラミングしてみよう!

プログラミングにはArduinoIDEという開発環境を使います。

緑色の顔のようなアイコンをダブルクリックします。

                   ※デスクトップにアイコンが無い場合は、スタートArduinoの順にクリックしてください

* 家のコンピュータでやってみたい人は、この資料の後半にある「おまけArduinoの開発環境を整えよう。」を読んで    ArduinoIDEをインストールしてみてね。10分もあればできると思います。

起動するとこんな感じ(下図)です。ウィンドウの上にファイル名が示され、メニューバーと呼ばれる場所には「ファイル」「編集」「スケッチ」「ツール」「ヘルプ」などのメニューコマンドがあります。プログラムを書いたら「ファイル」メニューから「保存」か「名前を付けて保存」をすることで、プログラムを保存することができます。なお、Arduinoではプログラムのことをスケッチといいます。

よく使うのは「」マークのボタンで示された、プログラムの検証です。これは自分で書いたプログラムがちゃんとマイコン上で動くかを検証するためのボタンです。

次によく使うのは「⇒」マークで示された、プログラムをマイコンに転送するボタンです。マイコンにプログラムを転送するとマイコンが自動的に動き始めます。

マイコンが動き始めてからよく使うのが、「虫眼鏡」のマークで示された、シリアルモニタを起動するボタンです。これを使うと、マイコンからのメッセージを表示するなど、マイコンと通信することができます。

4.はじめてのプログラム開発 「Hello World!

最初は、マイコンに「 Hello!! 」と言わせるプログラムを作成してみましょう。

といっても、今回のマイコンには音を出すスピーカなどはついていません。ですので、マイコンに「 Hello!! 」という文字を出力させます。ここで、文字を出力?と言われておかしいなと思った人もいるでしょう。そうです、マイコンにはディスプレイなど文字を表示する装置が付いていません。

そこでマイコンで出力した文字を、通信ケーブルを使ってパソコンのディスプレイに出力します。それを実現するのがシリアルモニタです。シリアルモニタとは、マイコンとパソコンとを繋いでいる通信ケーブルでやり取りされている内容を表示してくれる便利なモニターなのです。

シリアルポートを設定

メニューバーの「ツール」から「シリアルポート」を選び、マイコンがUSBケーブルで接続されているシリアルポートを選びます。下の図ではCOM5というのシリアルポートが表示されていますが、これはパソコンによって変わります。もし、他のシリアルポートも表示されていて、次に行うシリアルポートの確認で失敗するようであれば、他のシリアルポートを選択してみてください。

 

シリアルポートの確認

 


メニューバーの「ツール」から「ボード情報を取得」をクリックします。ウィンドウが現れ「ボード情報」が表示されれば、シリアルポートが正しく設定されています。

 

うまく設定できていないと、ボード情報ウィンドウは現れず、コンソールにエラーメッセージが表示されます。その場合には、シリアルポートの番号を変更するか、USBケーブルを抜き差ししてマイコンとパソコンがしっかりと接続されているかを確認しましょう。

 

プログラムを作ってみましょう

それでは下記のプログラムを打ってみましょう。マウスで枠内の文字を選択してコピー&ペーストすると楽です。

 

void setup() {

  // シリアル通信速度の設定

  Serial.begin(9600);

}

 

void loop() {

  // シリアルモニタにテキストを表示する

  Serial.println("  Hello!!  ");

 

  // 1秒間待機

  delay(1000);

}

 

プログラムを打ち終わったら「Ctrl」+「t」を同時に押してください。見やすいように自動的に成型してくれます。

動作の説明

まず、void setup()と呼ばれる関数のなかで、マイコンに必要な設定を行います。具体的にはパソコンとマイコンの通信設定を行います。通信速度を9600bpsに設定します。

次に,void loop()と呼ばれる関数の中で、パソコンのシリアルモニタに「 Hello!! 」と表示します。次に、1000ミリ秒、つまり1秒間停止します。マイコンはvoid loop()という関数を繰り返し実行し続けるようにできているので、シリアルモニタには1秒おきに「 Hello!! 」という文字が表示されることになります。

*関数ってなに? プログラム言語では処理の固まりに名前を付けます。それを関数といいます。上のプログラムでは、void setup () void loop()という2つの関数があり、各々setuploopという関数名が付いています。関数名の後の中カッコ始まり「{ 」から中カッコ終わり「 }」までの間に、マイコンに行わせたい処理を書きます。

プログラムの検証


検証が終わると、コンソールに「コンパイルが完了しました。」と表示されます。

プログラムに間違いがあると、コンソールにエラーの内容が表示されます。下記の例は、文字の打ち間違いと、日本語をプログラム中に入れてしまった場合の例です。


 



プログラムをマイコンに転送(書き込み)

「ボードへの書き込みが完了しました」と出たら成功です。すでにマイコンは皆さんが書いたプログラムの内容を実行し始めています。次にマイコンの動作を確認してみましょう。

シリアルモニタを開く & 動作確認

シリアルモニタが現れます。8行目の「 Hello!! 」を他の文字に変えたり、9行目のdelayの値を変更したりして再度マイコンボードに転送すると、表示やタイミングの変更ができます。

5.プログラム開発その1 「フルカラーLED

3色の色を表示できるLEDをマイコンに接続していろいろな色を表示させてみましょう。LEDには銀色に伸びる端子が4本ついています。短い端子はアノードと呼ばれる端子でここに電圧を加えます。いちばん長いのがカソードと呼ばれます。各色のアノードとカソードとをそれぞれプラスとマイナスにつなぐと赤、緑、青色に点灯します。

 

 

LEDとマイコンを配線 & プログラミング

#define RLED 26

#define GLED 25

#define BLED 17

 

void setup() {

  // シリアル通信速度の設定

  Serial.begin(9600);

 

  // フルカラーLEDの設定

  pinMode(RLED, OUTPUT);

  pinMode(GLED, OUTPUT);

  pinMode(BLED, OUTPUT);

}

void loop() {

  // フルカラーLEDを赤色に点灯させる

  Serial.println("赤 RED");

  digitalWrite(RLED, HIGH);

  delay(1000);

  digitalWrite(RLED, LOW);

 

  // フルカラーLEDを緑色に点灯させる

  Serial.println("緑 GREEN");

  digitalWrite(GLED, HIGH);

  delay(1000);

  digitalWrite(GLED, LOW);

 

  // フルカラーLEDを青色に点灯させる

  Serial.println("青 BLUE");

  digitalWrite(BLED, HIGH);

  delay(1000);

  digitalWrite(BLED, LOW);

}

 

setup関数内のpinModeという命令OUTPUTを用いることで、26番ピンを赤色の出力モード、25番ピンを緑色の出力モード、17番ピンを青色の出力モードとします。INPUTと打つと入力モードとなり、スイッチを接続した場合に使います。loop関数内ではdigitalWriteという命令で、光らせたい色の番号のピン(赤色は26番、緑色は25番、青色は17番)の電圧を+5Vとします。指定した番号のピンに関連する色にLEDが点灯します。次にdelay命令で1秒間待った後、再度digitalWrite命令を使い、光らせた色の番号のピンの電圧を0Vとします。そうするとLEDが消灯します。これを赤緑青の順番に行い、loop関数の最初に戻る、という動作を繰り返します。なお、「//」で始まる行はコメント行と言ってプログラムを説明するためのもので、マイコンの動作には関係しません。一般的にはここは英語で書いてあります。今回は日本語で書いてありますが

 

6.プログラム開発その2 「温度と湿度の表示」

温度と湿度を測ることができるセンサー(DHT11)をマイコンに接続し、温度と湿度を読み取りシリアルモニタを使って表示します。

上の図のように配線します。赤色の電源ラインに5Vを差しセンサーに電源を供給します。黄色は温度や湿度などの信号を送信するラインで、マイコンの23番ピンに接続します。プログラム中の「#define DHTPIN  23」が23番ピンに信号線が接続されていることを意味しています。黒色のラインはGNDラインです。マイコンのGNDと書かれたところに接続します。新規ファイルを作成し下記コードをコピー&ペーストしてマイコンボードに書き込みましょう。温度と湿度がシリアルモニタに表示されます。

#include "Adafruit_Sensor.h"

#include "DHT.h"

 

#define DHTPIN 23

#define DHTTYPE DHT11

 

DHT dht(DHTPIN, DHTTYPE);

 

void setup() {

  // シリアル通信速度の設定

  Serial.begin(9600);

  // 温湿度センサーのセットアップ

  dht.begin();

}

 

void loop() {

  delay(2000);

  // データの取得

  float temperature = dht.readTemperature();

  float humidity = dht.readHumidity();

 

  // データの表示

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

  Serial.println("温度" + (String)temperature + "");

  Serial.println("湿度" + (String)humidity + "");

}

 

 

7.プログラム開発その3 「熱中症予防マシン」

「フルカラーLED」と「温度と湿度を表示」を組み合わせて、熱中症予防マシンを作成しましょう。

熱中症危険度指数 WBGT

WBGT値とは温度と湿度から算出される熱中症予防指針です。下表で熱中症への警戒レベルがわかります。同じ温度でも湿度が高い場合は熱中症の危険度が上がります。

薄ピンク

注意

黄色

警戒

ピンク

厳重警戒

危険

 

LEDで熱中症を警告します。

WBGT値をLEDで下記の4パターンで表示し、警告を行うプログラムをマイコンに書き込みます。

注意

緑の点灯

警戒

黄色の点滅

 

 

 

 

 

 

厳重警戒

赤の点滅

 

 

 

 

 

 

危険

赤と黄色

早い点滅

 

 

 

 

 

 

 

#include "Adafruit_Sensor.h"

#include "DHT.h"

 

#define DHTPIN 23

#define DHTTYPE DHT11

#define RLED 26

#define GLED 25

#define BLED 17

 

DHT dht(DHTPIN, DHTTYPE);

// 熱中症警報用マトリクス

// 0:注意、1:警戒、2:厳重警戒、3:危険

int wbgt[20][17] = {

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2},

  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2},

  {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3},

  {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3},

  {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3},

  {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3},

  {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3},

  {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}

};

 

void setup() {

  // シリアル通信速度の設定

  Serial.begin(9600);

 

  // 温湿度センサーのセットアップ

  dht.begin();

 

  // フルカラーLEDの設定

  pinMode(RLED, OUTPUT);

  pinMode(GLED, OUTPUT);

  pinMode(BLED, OUTPUT);

 

  //フルカラーLEDの点灯確認

  LED_Initial(10);

 

  Serial.println("熱中症警告システム DHT11");

}

 

void loop() {

  // データの取得

  float tempareture = dht.readTemperature();

  float humidity = dht.readHumidity();

 

  // データの表示

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

  Serial.println("温度" + (String)tempareture + "");

  Serial.println("湿度" + (String)humidity + "");

 

  // 警報レベルの判定

  int necchu;

  if ((tempareture < 21) || (humidity < 20)) {

    necchu = 0;

    if (tempareture < 0)

      necchu = 4;

  } else {

    necchu =  wbgt[int (tempareture - 21)][int ((humidity / 5) - 4)];

  }

 

  // 警報レベルの表示

  String mess[5];

  mess[0] = "注意";

  mess[1] = "警戒";

  mess[2] = "厳重警戒";

  mess[3] = "危険";

  mess[4] = "零下警報";

  Serial.println("WBGT " + mess[necchu]);

 

  // LEDの点灯制御

  int delay_time = 2000;

  WARNNING(necchu, delay_time);

}

 

/****************************************************

  警報レベルによってLEDの色と点灯パターンを変化

  させる。

  0:注意       緑、点灯

  1:警戒      黄色、ゆっくり点滅

  2:厳重警戒   赤、はやめに点滅

  3:危険    赤と黄色が交互に素早く点滅

  4:零下警報  青、点灯

 ****************************************************/

int flag = 1;

void WARNNING(int necchu, int delay_time)

{

  // 0:注意、1:警戒、2:厳重警戒、3:危険 4:零下警報

  digitalWrite(RLED, LOW);

  digitalWrite(GLED, LOW);

  digitalWrite(BLED, LOW);

 

  // 警報レベルによるLEDの点灯制御

  switch (necchu) {

    case 0: //0:注意 緑

      digitalWrite(GLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        delay(100);

      }

      break;

 

    case 1: //1:警戒 黄色

      digitalWrite(RLED, flag);

      digitalWrite(GLED, flag);

      for (int n = 0; n < (int)(delay_time/400); n++) {

        flag = 1 - flag;

        digitalWrite(RLED, flag);

        digitalWrite(GLED, flag);

        delay(400);

      }

      break;

 

    case 2: //2:厳重警戒

      digitalWrite(RLED, flag);

      for (int n = 0; n < (int)(delay_time/250); n++) {

        flag = 1 - flag;

        digitalWrite(RLED, flag);

        delay(250);

      }

      break;

 

    case 3: //3:危険 赤黄色の点滅

      digitalWrite(RLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        flag = 1 - flag;

        digitalWrite(GLED, flag);

        delay(100);

      }

      break;

 

    case 4: //4:寒すぎる 青点灯

      digitalWrite(BLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        delay(100);

      }

      break;

 

    default:

      digitalWrite(RLED, flag);

      digitalWrite(GLED, flag);

      digitalWrite(BLED, flag);

  }

}

 

/* LED を赤、青、緑、で点灯させる 初回動作 */

void LED_Initial(int num)

{

  int n;

  for (n = 0; n < num; n++) {

 

    Serial.println(" R");

    digitalWrite(RLED, HIGH);

    delay(100);

    digitalWrite(RLED, LOW);

 

    Serial.println(" B");

    digitalWrite(BLED, HIGH);

    delay(100);

    digitalWrite(BLED, LOW);

 

    Serial.println(" G");

    digitalWrite(GLED, HIGH);

    delay(100);

    digitalWrite(GLED, LOW);

  }

}

 

 

8.プログラム開発その4 「温度と湿度をサーバに送ろう!」

最後に、マイコンで取得した温度と湿度のデータをサーバに送信してみましょう.

プログラムをマイコンに書き込む

まずは、次のコードをコピペしよう!※コピペしてもまだ実行しないでね。

#include "Adafruit_Sensor.h"

#include "DHT.h"

#include "PubSubClient.h"

#include <time.h>

#include <WiFiClientSecure.h>

#include <WiFi.h>

 

#define DHTPIN 23

#define DHTTYPE DHT11

#define RLED 26

#define GLED 25

#define BLED 17

// タイムゾーンを日本時刻にするための定数を定義

#define JST     3600* 9

 

// MQTT サーバにアップロードするデータベースの名前(※2回目以降は変更することはできません!!)

//const char* username = "好きな言葉を入れてね";

 

DHT dht(DHTPIN, DHTTYPE);

char macAddr_str[18];

char clientid[18];

const char* server = "iot.st.nagaoka-ct.ac.jp";

const uint16_t port = 8883;

boolean wifi_connected = true;

WiFiClientSecure espClient;

PubSubClient mqttClient(espClient);

// 熱中症警報用マトリクス

// 0:注意、1:警戒、2:厳重警戒、3:危険

int wbgt[20][17] = {

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2},

  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2},

  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2},

  {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3},

  {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3},

  {0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3},

  {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3},

  {0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3},

  {0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},

  {2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}

};

 

 

void setup() {

  const char* ssid     = "denden-Lab1";      // WiFiSSIDを入力

  const char* password = "S364!Denk!";  // WiFiPasswordを入力

 

  // シリアル通信速度の設定

  Serial.begin(9600);

 

  // 温湿度センサーのセットアップ

  dht.begin();

 

  // フルカラーLEDの設定

  pinMode(RLED, OUTPUT);

  pinMode(GLED, OUTPUT);

  pinMode(BLED, OUTPUT);

 

  //フルカラーLEDの点灯確認

  LED_Initial(10);

 

  // WiFi へ接続

  uint8_t wifi_counter = 0;

  Serial.println();

  WiFi.begin(ssid, password);

  Serial.print("Connecting");

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(1000);

    Serial.print(".");

    wifi_counter = wifi_counter + 1;

    if (wifi_counter > 15)

    {

      Serial.print("Wifiの取得を中断します.");

      wifi_connected = false;

      break;

    }

  }

 

  // Wi-Fi に与えられた IP アドレスの表示

  if (wifi_connected)

  {

    Serial.print("\nConnected, IP address: ");

    Serial.println(WiFi.localIP());

  }

 

  // MAC Address の取得

  uint8_t macAddr[6];

  if (wifi_connected)

  {

    WiFi.softAPmacAddress(macAddr);

    sprintf(macAddr_str, "%02X-%02X-%02X-%02X-%02X-%02X", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);

    Serial.printf("MACAddress = %s\n", macAddr_str);

  }

 

  // MQTT Publisher のクライアントIDの決定

  if (wifi_connected)

  {

    sprintf(clientid, "%02X%02X%02X%02X%02X%02X.Pub", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);

    Serial.printf("clientid = %s\n", clientid);

  }

 

  // SSL/TSL 通信のためのcertファイルの設定

  if (wifi_connected)

  {

    const char* rootCACertificate = \

                                    "-----BEGIN CERTIFICATE-----\n" \

                                    "MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl\n" \

                                    "MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe\n" \

                                    "U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX\n" \

                                    "DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy\n" \

                                    "dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj\n" \

                                    "YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV\n" \

                                    "OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr\n" \

                                    "zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM\n" \

                                    "VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ\n" \

                                    "hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO\n" \

                                    "ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw\n" \

                                    "awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs\n" \

                                    "OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\n" \

                                    "DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF\n" \

                                    "coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc\n" \

                                    "okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8\n" \

                                    "t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy\n" \

                                    "1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/\n" \

                                    "SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03\n" \

                                    "-----END CERTIFICATE-----\n";

    espClient.setCACert(rootCACertificate);

  }

 

  // MQTTサーバのアドレスとポートをセットする.

  if (wifi_connected)

  {

    mqttClient.setServer(server, port);

    Serial.print("connecting to ");

    Serial.println(server);

  }

 

  // 乱数を使用するためのセットアップをする.

  if (wifi_connected)

  {

    randomSeed(analogRead(0));

  }

 

  // タイムゾーンを日本に設定する.

  configTime( JST, 0, "ntp.nict.jp", "ntp.jst.mfeed.ad.jp");

 

  Serial.println("熱中症警告システム DHT11");

  delay(1000);

}

 

void loop() {

  int delay_time=2000;   // 2秒ごとにセンサの値を更新するように設定

  int mqtt_interval=5;  // ココの数値は変えないこと!!

  static int counter=3;

  float temperature, humidity;

 

  // 気温と湿度を取得してシリアルモニタに表示

  Get_TempHumi(&temperature, &humidity);

  Serial.printf("temperature: %.2f,   humidity: %.2f\n", temperature, humidity);

 

  if (counter >= mqtt_interval)

  {

    counter = 0;

    if (wifi_connected)

    {

      if (mqttClient.connect(clientid)) {

        char mqttdata[256];

        char now[15];

 

        // 現在時刻の取得

        Get_Time(now);

        Serial.printf("現在の日時 : %s\n", now);

 

        // MQTT サーバに送信するデータを作成

        Set_MqttData(mqttdata, now, temperature, humidity);

        Serial.printf("mqttdata :%s\n", mqttdata);

 

        char topic[7];

        sprintf(topic, "topic%d", random(mqtt_interval-2));

        mqttClient.publish(topic, mqttdata);

      } else {

        // MQTT サーバに接続できなかった場合はシリアルモニタにエラーを表示

        Serial.print("failed, rc=");

        Serial.print(mqttClient.state());

        Serial.print("MQTTサーバに接続できなかったよ...");

      }

      // MQTTサーバから切断する.

      mqttClient.disconnect();

    }

  }

 

  // 警報レベルの判定

  int necchu;

  if ((temperature < 21) || (humidity < 20)) {

    necchu = 0;

    if (temperature < 0)

      necchu = 4;

  } else {

    necchu =  wbgt[int (temperature - 21)][int ((humidity / 5) - 4)];

  }

 

  // 警報レベルの表示

  String mess[5];

  mess[0] = "注意";

  mess[1] = "警戒";

  mess[2] = "厳重警戒";

  mess[3] = "危険";

  mess[4] = "零下警報";

  Serial.println("WBGT " + mess[necchu]);

 

  // LEDの点灯制御

  WARNNING(necchu, delay_time);

 

  counter += 1;

}

 

/****************************************************

  警報レベルによってLEDの色と点灯パターンを変化

  させる。

  0:注意       緑、点灯

  1:警戒      黄色、ゆっくり点滅

  2:厳重警戒   赤、はやめに点滅

  3:危険    赤と黄色が交互に素早く点滅

  4:零下警報  青、点灯

 ****************************************************/

int flag = 1;

void WARNNING(int necchu, int delay_time)

{

  // 0:注意、1:警戒、2:厳重警戒、3:危険 4:零下警報

  digitalWrite(RLED, LOW);

  digitalWrite(GLED, LOW);

  digitalWrite(BLED, LOW);

 

  // 警報レベルによるLEDの点灯制御

  switch (necchu) {

    case 0: //0:注意 緑

      digitalWrite(GLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        delay(100);

      }

      break;

 

    case 1: //1:警戒 黄色

      digitalWrite(RLED, flag);

      digitalWrite(GLED, flag);

      for (int n = 0; n < (int)(delay_time/400); n++) {

        flag = 1 - flag;

        digitalWrite(RLED, flag);

        digitalWrite(GLED, flag);

        delay(400);

      }

      break;

 

    case 2: //2:厳重警戒

      digitalWrite(RLED, flag);

      for (int n = 0; n < (int)(delay_time/250); n++) {

        flag = 1 - flag;

        digitalWrite(RLED, flag);

        delay(250);

      }

      break;

 

    case 3: //3:危険 赤黄色の点滅

      digitalWrite(RLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        flag = 1 - flag;

        digitalWrite(GLED, flag);

        delay(100);

      }

      break;

 

    case 4: //4:寒すぎる 青点灯

      digitalWrite(BLED, HIGH);

      for (int n = 0; n < (int)(delay_time/100); n++) {

        delay(100);

      }

      break;

 

    default:

      digitalWrite(RLED, flag);

      digitalWrite(GLED, flag);

      digitalWrite(BLED, flag);

  }

}

 

/* LED を赤、青、緑、で点灯させる 初回動作 */

void LED_Initial(int num)

{

  int n;

  for (n = 0; n < num; n++) {

 

    Serial.println(" R");

    digitalWrite(RLED, HIGH);

    delay(100);

    digitalWrite(RLED, LOW);

 

    Serial.println(" B");

    digitalWrite(BLED, HIGH);

    delay(100);

    digitalWrite(BLED, LOW);

 

    Serial.println(" G");

    digitalWrite(GLED, HIGH);

    delay(100);

    digitalWrite(GLED, LOW);

  }

}

 

// 気温と湿度を取得する関数

void Get_TempHumi(float * temperature, float * humidity)

{

  // データの取得

  *temperature = dht.readTemperature(); // 温度

  *humidity = dht.readHumidity(); // 湿度

 

  // 湿度・温度の表示

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

  //Serial.println("温度" + (String)*temperature + "");

  //Serial.println("湿度" + (String)*humidity + "");

}

 

// 現在時刻(JST)を取得する関数

void Get_Time(char now[15]) {

  /*

   * 202072019365秒の時、変数nowは以下の値となる.

   * now = 20200720193605

   */

 

  time_t t;

  struct tm *tm;

 

  t = time(NULL);

  tm = localtime(&t);

 

  sprintf(now, "%04d%02d%02d%02d%02d%02d",

          tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,

          tm->tm_hour, tm->tm_min, tm->tm_sec);

}

 

// MQTT サーバに送信するためのデータを生成するための関数

void Set_MqttData(char mqttdata[256], char now[15], float temperature, float humidity) {

  /*

   * mqttdata = {device:MacAddress,

   *             name:username,

   *             object1:{id:1, title:温度, unit:°C, result:tempreture, date:now},

   *             object2:{id:2, title:湿度, unit:, result:humidity, date:now}

   *             }

   */

  sprintf(mqttdata, "{\"device\":\"%s\",\"name\":\"%s\",\"object1\":{\"id\":\"1\",\"title\":\"温度\",\"unit\":\"°C\",\"result\":\"%.3f\",\"date\":\"%s\"},\"object2\":{\"id\":\"2\",\"title\":\"湿度\",\"unit\":\"\",\"result\":\"%.3f\",\"date\":\"%s\"}}",

          macAddr_str, username, temperature, now, humidity, now);

}

 

 

コピーが終わったら、17行目のコードを修正してください。修正する内容は次の図を参考にしてね。


修正が終わったらマイコンに書き込んでみよう。書き込むまでに時間がかかるかも。。。気長に待ってね。

 

wEBブラウザで動作確認

ココをクリックして、Webブラウザが起動するまで待ってください。起動出来たら先ほど入力した名前をクリックして温度や湿度のグラフを表示してみよう!このグラフは10秒間に1回ずつしか更新されないように設定されているよ。より短い時間間隔での温度と湿度を確認したい場合はシリアルモニタから見てみてね。