# 付録 — IoT Programming ドキュメント

# 付録

## 実験室で赤外リモコン送信テスト

内蔵の赤外LEDを用いて、ビデオカメラ操作する例を リスト 29 に示します。 ライブラリマネージャにて、IRremoteESP8266 をインストールしてください。ちなみに、テストしたバージョンは2.7.15でした。 `2.7.15` より新しいバージョンだと、失敗する場合があります。もし最新版を入れてうまくいかない場合はダウングレードしてください。

リスト 29 src/irsend02.ino

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81

    /* IRremoteESP8266: IRsendDemo - demonstrates sending IR codes with IRsend.

       Version 1.1 January, 2019
       Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009,
       Copyright 2009 Ken Shirriff, http://arcfn.com

       An IR LED circuit *MUST* be connected to the ESP8266 on a pin
       as specified by kIrLed below.

       TL;DR: The IR LED needs to be driven by a transistor for a good result.

       Suggested circuit:
           https://github.com/crankyoldgit/IRremoteESP8266/wiki#ir-sending

       Common mistakes & tips:
     *   * Don't just connect the IR LED directly to the pin, it won't
           have enough current to drive the IR LED effectively.
     *   * Make sure you have the IR LED polarity correct.
           See: https://learn.sparkfun.com/tutorials/polarity/diode-and-led-polarity
     *   * Typical digital camera/phones can be used to see if the IR LED is flashed.
           Replace the IR LED with a normal LED if you don't have a digital camera
           when debugging.
     *   * Avoid using the following pins unless you really know what you are doing:
     *     * Pin 0/D3: Can interfere with the boot/program mode & support circuits.
     *     * Pin 1/TX/TXD0: Any serial transmissions from the ESP8266 will interfere.
     *     * Pin 3/RX/RXD0: Any serial transmissions to the ESP8266 will interfere.
     *   * ESP-01 modules are tricky. We suggest you use a module with more GPIOs
           for your first time. e.g. ESP-12 etc.
    */
    #include <M5StickCPlus.h>
    #include <IRremoteESP8266.h>
    #include <IRsend.h>

    const uint16_t kIrLed = 9;  // 赤外LEDが接続されたピン番号

    IRsend irsend(kIrLed);  // Set the GPIO to be used to sending the message.

    // Example of data captured by IRrecvDumpV2.ino
    uint16_t photoshot[99] = {3488, 1740,  438, 424,  438, 1302,  440, 422,  438, 424, 440, 422,  440, 422,
                              440, 422,  438, 424,  438, 424,  438, 424,  438, 424,  438, 426,  438, 424,
                              438, 1302,  440, 422,  442, 422,  440, 424,  438, 424,  438, 424,
                              442, 420,  438, 1304,  438, 1304,  440, 1302,  438, 424,  438, 424,  438, 424,
                              438, 424,  438, 1302,  440, 424,  440, 1302,  440, 422,  438, 424,  440, 422,
                              440, 1302,  438, 1304,  438, 424,  438, 424,  438, 1304,  438, 1302,  438, 424,
                              438, 424,  462, 1278,  464, 1278,  464, 1278,  462, 1280,  460, 1280,  464, 398,
                              464, 398,  438
                             };  // PANASONIC 40040E14667C

    uint16_t recording[99] = {3490, 1738,  440, 424,  438, 1304,  438, 424,  438, 424,  438, 424,  438, 424,
                          438, 424,  438, 424,  438, 424,  438, 424,  438, 424,  438, 424,  438, 424,
                          438, 1302,  440, 424,  442, 422,  438, 424,  438, 424,  438, 424,  438, 424,
                          438, 1302,  442, 1302,  438, 1302,  440, 424,  440, 424,  438, 424,  438, 424,
                          438, 1302,  442, 420,  442, 1302,  438, 424,  438, 422,  442, 422,  438, 424,
                          440, 1302,  438, 1302,  438, 424,  438, 424,  438, 1302,  442, 1300,  440, 424,
                          440, 422,  440, 1302,  440, 424,  462, 1278,  464, 400,  464, 398,  464, 1278,  464
                         };  // PANASONIC 40040E143329

    void setup() {
      M5.begin();
      Serial.begin(115200);
      M5.Lcd.fillScreen(BLUE);
      irsend.begin();
    }

    void loop() {
      //  Serial.println("NEC");  //  irsend.sendNEC(0x00FFE01FUL);
      //  Serial.println("Sony"); //  irsend.sendSony(0xa90, 12, 2);  // 12 bits & 2 repeats
      M5.update();
      if (M5.BtnA.wasReleased()) {
        irsend.sendRaw(photoshot, 99, 38);  // Send a raw data capture at 38kHz.
        M5.Lcd.fillScreen(YELLOW);
      } else if (M5.BtnB.wasReleased()) {
        irsend.sendRaw(recording, 99, 38);  // Send a raw data capture at 38kHz.
        M5.Lcd.fillScreen(RED);
      }
      delay(150);
      M5.Lcd.fillScreen(BLUE);
      //  Serial.println("a Samsung A/C state from IRrecvDumpV2");
      //  irsend.sendSamsungAC(samsungState);
      //  delay(2000);
    }

## 気温・湿度・気圧 (ENV II Sensor)

M5Stack社ENV II Unit(U001-B) https://lang-ship.com/blog/work/m5stack-env-ii-unit-u001-b/ の、M5StickCでの使い方(GitHub) に従って、以下2つをライブラリマネージャから入れてください。（または、`arduino-cli lib install "Adafruit BMP280 Library"` などで。）

- Adafruit BMP280 Library

- Adafruit SHT31 Library

上のリンクにあったプログラムとほぼ同じですが、リスト 30 が、気温・湿度・気圧をLCDとシリアルコンソールに出力するプログラムです。（すこしだけ改変しています）

リスト 30 src/env2.ino

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44

    /*
     Please install the < Adafruit BMP280 Library > （https://github.com/adafruit/Adafruit_BMP280_Library）
                         < Adafruit SHT31 Library > （https://github.com/adafruit/Adafruit_SHT31）
       from the library manager before use.
      This code will display the temperature, humidity and air pressure information on the screen
      https://lang-ship.com/blog/work/m5stack-env-ii-unit-u001-b/
      */
    #include <M5StickCPlus.h>
    #include <Adafruit_BMP280.h>
    #include <Adafruit_SHT31.h>
    Adafruit_SHT31 sht3x = Adafruit_SHT31(&Wire);
    Adafruit_BMP280 bme = Adafruit_BMP280(&Wire);
    float tmp = 0.0;
    float hum = 0.0;
    float pressure = 0.0;
    void setup() {
      M5.begin();
      M5.Lcd.setRotation(3);
      M5.Lcd.setTextSize(3);
      Wire.begin(32, 33);
      Serial.println(F("ENV Unit(SHT30 and BMP280) test..."));
      while (!bme.begin(0x76)) {
        Serial.println("Could not find a valid BMP280 sensor, check wiring!");
        M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");
      }
      while (!sht3x.begin(0x44)) {
        Serial.println("Could not find a valid SHT3X sensor, check wiring!");
        M5.Lcd.println("Could not find a valid SHT3X sensor, check wiring!");
      }
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.println("ENV Unit test...");
    }
    void loop() {
      pressure = bme.readPressure();
      tmp = sht3x.readTemperature();
      hum = sht3x.readHumidity();
      Serial.printf("Temperature: %2.2f*C  Humidity: %0.2f%%  Pressure: %0.2fhPa\r\n", tmp, hum, pressure / 100);
      M5.Lcd.setCursor(0, 25);
      M5.Lcd.setTextColor(WHITE, BLACK);
      M5.Lcd.printf("Temp:%2.2f*C\n", tmp);
      M5.Lcd.printf("Humi:%2.2f%%\n", hum);
      M5.Lcd.printf("Prs :%2.0fhPa\n", pressure / 100);
      delay(1000);
    }

警告

ENV II HAT用のプログラムではありません。ENV II HAT用のサンプル

## Speaker Hatで音をだす

参考：https://nn-hokuson.hatenablog.com/entry/2017/09/01/092945

ボタンを押したときに、2種類の音を出す例を リスト 31 に示します。また、音データのサンプルを 16k.txt と 8k.txt におきました。 （16kも8kも、Speaker Hatで聴く分には違いはわかりませんでしたので、8kでいいとおもいます。）

リスト 31 のコメント（黄色ハイライト部分）をよく読んで、タブを追加し、16k.txt と 8k.txt の内容を貼り付けてください。

リスト 31 src/speakerhat01.ino

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    #include <M5StickCPlus.h>

    const int servo_pin = 26;
    uint8_t ledChannel = 0;
    uint8_t resolution = 8;
    uint32_t sampling_rate = 16000; //16kの場合。8kの場合は、8000

    /*
        別タブ（ファイル名はなんでもよい）に、音声データを以下の形式で貼っておく。
        【音1】
        const uint8_t coin05_8k_raw[] PROGMEM = { 0x80, ... };
        const uint32_t coin05_8k_raw_len = 7218; // ←配列のサイズ
        【音2】
        const uint8_t coin05_16k_raw[] PROGMEM = { 0x80, ... };
        const uint32_t coin05_16k_raw_len = 14437; // ←配列のサイズ
        PROGMEM と書くと、フラッシュメモリに配置する

        そのうえで、以下のextern文を、別タブの変数名と合わせて書く。
        変数名を一致させることが重要です。
    */
    //    【音1】
    extern const uint8_t coin05_8k_raw[];
    extern const uint32_t coin05_8k_raw_len;
    //    【音2】
    extern const uint8_t coin05_16k_raw[];
    extern const uint32_t coin05_16k_raw_len;

    void setup() {
      // put your setup code here, to run once:
      M5.begin();
      M5.Lcd.setRotation(3);
      M5.Lcd.setCursor(0, 30, 4);
      M5.Lcd.println(" speaker hat test");
      ledcSetup(ledChannel, sampling_rate * 32, resolution);
      ledcAttachPin(servo_pin, ledChannel);
      ledcWrite(ledChannel, 0);
    }
    void playMusic(const uint8_t* music_data, uint32_t len, uint16_t sample_rate) {
      uint32_t delay_interval = ((uint32_t)1000000 / sample_rate);
      for (int i = 0; i < len; i++) {
        ledcWrite(ledChannel, music_data[i]);
        delayMicroseconds(delay_interval);
      }
      ledcWriteTone(ledChannel, 0);
    }
    void loop() {
      M5.update();
      if (M5.BtnA.wasReleased()) {
        playMusic(coin05_16k_raw, coin05_16k_raw_len, sampling_rate + 800); //なぜか音が低いので +800した
      } else if (M5.BtnB.wasReleased()) {
        playMusic(coin05_8k_raw, coin05_8k_raw_len, sampling_rate / 2); // 8kなので、2で割った
      }
      ledcWriteTone(ledChannel, 0);
      delay(100);
    }

## LINE Notify (HTTPS POST)

https://notify-bot.line.me/ja/ で、トークンを取得しておく必要があります。

リスト 32 src/line01.ino

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52

    #include <WiFi.h>
    #include <WiFiMulti.h>
    #include <WiFiClient.h>
    #include <HTTPClient.h>

    WiFiMulti WiFiMulti;

    void setup() {
      Serial.begin(115200);
      WiFi.mode(WIFI_STA);
      WiFiMulti.addAP("miura_asp_2g", "********");

      // wait for WiFi connection
      Serial.print("Waiting for WiFi to connect...");
      while ((WiFiMulti.run() != WL_CONNECTED)) {
        Serial.print(".");
        delay(50);
      }
      Serial.println(" connected");
    }

    void loop() {
      HTTPClient http;

      if (http.begin("https://notify-api.line.me/api/notify")) {  // HTTPS
        http.addHeader("Authorization", "Bearer TOKENTOKENTOKEN"); // ここのTOKENTOKEN... の部分に、取得したTokenを指定する
        http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // format of postdata
        String postdata = "message=日本語でも大丈夫です";
        int httpCode = http.POST(postdata);

        // httpCode will be negative on error
        if (httpCode > 0) {
          // HTTP header has been send and Server response header has been handled
          Serial.printf("[HTTP] GET... code: %d\n", httpCode);

          // file found at server
          if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
            String payload = http.getString();
            Serial.println(payload);
          }
        } else {
          Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }
        http.end();
      } else {
        Serial.printf("[HTTP] Unable to connect\n");
      }

      Serial.println();
      Serial.println("Waiting 2 minutes...");
      delay(60*2*1000); // 120秒まつ
    }