饂飩コーディング

iOSアプリやら、Unityやら、Cocos2dやらごにょごにょ書いております

アレクサ!扇風機をつけてをトリガー! ネット非対応家電でもOK

appdeappuappu.hateblo.jp
↑で作ったPHP使います。


IFTTTでCreateします。
スマホ画面からの操作とデスクトップPCブラウザでの操作が若干違うのでご注意を。

スマホではGet moreからCreate!

ThisのボタンからAmazonAlexaを選択
Say a specific phraseを選択
「扇風機をつけて」と入力

ThatのボタンからWebHooksを選択
Make a web requestを選択
URLに前回使ったhttp://hogehoge.com/testPHP/phpRemoconStatusUpdate.phpを入力
Method はPOSTを選択
Content Typeはapplication/x-www-form-urlencodedを選択
BodyにはsoushinID=1を入力

はいこれでAmazon Alexa
「アレクサ!扇風機をつけてをトリガー!」
と言えば前回作成したリモコンが扇風機をつけてくれます。
うん!便利便利。扇風機のリモコンって小さくてどっかいっちゃうからw

設定はこんな感じ↓

f:id:appdeappuappu:20200626133409j:plain
IFTTT扇風機



とは言えですよとは言え・・・
「トリガー!」ってつけるのすら面倒ですよね?

こう言いたい!
自分:「アレクサ!扇風機!!!!」
Alexa「はい!わかりました。」
って感じが理想です。

ということで、以下の手順で設定します。

f:id:appdeappuappu:20200626140754j:plain

f:id:appdeappuappu:20200626140807j:plain

f:id:appdeappuappu:20200626140822j:plain

f:id:appdeappuappu:20200626140837j:plain

f:id:appdeappuappu:20200626140904j:plain

f:id:appdeappuappu:20200626140915j:plain


ネット家電じゃなくてもリモコン使える家電なら
この方法でなんとか声で操作できますな。うんちょっと近未来な感じでいい!

ESP8266でネット経由で家電を操作する

f:id:appdeappuappu:20200607220016j:plain
家電リモコンの概要

f:id:appdeappuappu:20200607220157p:plain
ESP8266ブレッドボードでの回路


f:id:appdeappuappu:20200607220549j:plain
スマホから指示する画面

f:id:appdeappuappu:20200607220707j:plain
テレビはレグザ

f:id:appdeappuappu:20200607220648j:plain
エアコンは霧ヶ峰

f:id:appdeappuappu:20200607220638j:plain
扇風機はバルミューダ



私は猫を飼っています。夏は設定温度28度で付けっ放しで外出していますが、
エアコンつけ忘れたら猫が熱中症で危ないですよね??

というわけで、概要の絵のような感じで外出先からエアコンやら扇風機やらのオンオフが
できるようにESP8266を使って組み立てて見ました。


パートを分けるとしたら以下の通り
1、ESP8266で赤外線でリモコン情報をピピっつ!と飛ばす部分
2、スマホのブラウザで電源オンオフを行うボタンを表示する部分
3、ブラウザやESP8266からPHPで情報の受け渡しをする部分
4、mySQLでリモコン管理ようのテーブルを設計する部分

だいたいこの4つですが1の部分が楽しくてしょうがないですw(電子工作初心者だとリモコン楽しい〜)

本当は、赤外線LEDから送信されるデータはすべて管理ようのデータベーステーブルに登録しておいて
毎回そのデータをネットから受信して発光させようと思ってたんですが、なんだか無駄な気がして
とりあえずは赤外線LEDを発光させるデータはスケッチにオンコーディングしています。


それでは早速!
1、ESP8266で赤外線でリモコン情報をピピっつ!と飛ばす部分
電源を5V→3.3Vにレギュレータを使って降圧します。
秋月電子で購入した以下のパーツを使っています。
akizukidenshi.com

ちょっと前までは5vでESP8266をそのまま動かしていたのですが
金属のカバー部分がめっちゃくちゃ熱くなってたのでヤバイと感じて3.3Vにして見たら
発熱も気にならなくなりました。

赤外線LEDは二つ使います。テレビと扇風機に向ける赤外線LED1個とエアコンに向ける赤外線LED1個
計2つです。秋月電子で購入した以下の赤外線LEDを使いました。
akizukidenshi.com
Vf=1.35Vで最大電力が100mA
これを70mAで使っていきます。

70mA流したいのでトランジスタを使っています。有名なトランジスタのセカンドソース品ですw
akizukidenshi.com


IrSendDemoESP8266.ino
スケッチはサンプルスケッチIRsendDemoを改変して使いましょうw
不必要なコードが入っているので近日中に削除しておきます。

/* 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 <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Mitsubishi.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <ir_Mitsubishi.h>

const uint16_t kIrLed = 4;  // ESP8266 GPIO pin to use. Recommended: 4 (D2).

const char *ssid = "xxxxxxxxxxxxxxxxxx";  //ENTER YOUR WIFI SETTINGS
const char *password = "xxxxxxxxxxxxxx";

IRMitsubishiAC ac(kIrLed);  // Set the GPIO used for sending messages.

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


// Example of data captured by IRrecvDumpV2.ino
uint16_t rawData[67] = {9000, 4500, 650, 550, 650, 1650, 600, 550, 650, 550,
                        600, 1650, 650, 550, 600, 1650, 650, 1650, 650, 1650,
                        600, 550, 650, 1650, 650, 1650, 650, 550, 600, 1650,
                        650, 1650, 650, 550, 650, 550, 650, 1650, 650, 550,
                        650, 550, 650, 550, 600, 550, 650, 550, 650, 550,
                        650, 1650, 600, 550, 650, 1650, 650, 1650, 650, 1650,
                        650, 1650, 650, 1650, 650, 1650, 600};

// Example Samsung A/C state captured from IRrecvDumpV2.ino
uint8_t samsungState[kSamsungAcStateLength] = {
    0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0,
    0x01, 0xE2, 0xFE, 0x71, 0x40, 0x11, 0xF0};



void setup() {
  irsend.begin();
  pinMode(PIN_PUSHBUTTON, INPUT);
  delay(200);
  
  
#if ESP8266
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
#else  // ESP8266
  Serial.begin(115200, SERIAL_8N1);
#endif  // ESP8266

WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
  delay(1000);
  WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot
  
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");

  Serial.print("Connecting");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP

}

void loop() {

  // Send request
    HTTPClient http;    //Declare object of class HTTPClient
    http.useHTTP10(true);
    //http.begin("http://arduinojson.org/example.json");
    http.begin("http://xxxxxxxxxxxxx.com/testPHP/phpRemocon1.php");
    http.GET();

    // Parse response
    DynamicJsonDocument doc(500);
    deserializeJson(doc, http.getStream());

    // Read values
    int iidnumber_recieve = doc["iidnumber"];
    Serial.println(iidnumber_recieve);
    int istats_recieve = doc["istats"];
    Serial.println(istats_recieve);
    const char* iptyp_recieve = doc["iptyp"];
    Serial.println(iptyp_recieve);
    const char* itext_recieve = doc["itext"];
    Serial.println(itext_recieve);
    http.end(); 

    //扇風機ON
    if(strcmp(iptyp_recieve,"FNON")==0){
      senpuukiOn();
      motodatakoushin(iidnumber_recieve);
    }
    //扇風機OFF
    if(strcmp(iptyp_recieve,"FNOF")==0){
      senpuukiOn();
      motodatakoushin(iidnumber_recieve);
    }
    //TV ON
    if(strcmp(iptyp_recieve,"TVON")==0){
      terebiOn();
      motodatakoushin(iidnumber_recieve);
    }
    //TV OFF
    if(strcmp(iptyp_recieve,"TVOF")==0){
      terebiOn();
      motodatakoushin(iidnumber_recieve);
    }
    //MitsubishiAC ON
    if(strcmp(iptyp_recieve,"ACON")==0){
      airconOn();
      motodatakoushin(iidnumber_recieve);
    }
    //MitsubishiAC OFF
    if(strcmp(iptyp_recieve,"ACOF")==0){
      airconOFF();
      motodatakoushin(iidnumber_recieve);
    }
 
    delay(10000);
  
}

void senpuukiOn (){
  irsend.sendPanasonic(0x3242, 0x32427078807F);
  Serial.println("senpuuki ON");
   delay(1000);   
}
void terebiOn (){
  //NEC 
    Serial.println("NEC");
    irsend.sendNEC(0x2FD48B7);//TV ON
    delay(1000);
}
void airconOn(){
  //mitsubishiAC
    ac.begin();
    delay(200);
    ac.on();
    ac.setFan(1);
    ac.setMode(kMitsubishiAcCool);
    ac.setTemp(26);
    ac.setVane(kMitsubishiAcVaneAuto);
  //Serial.println("Sending IR command to A/C ...");
    ac.send(); 
}
void airconOFF(){
  //mitsubishiAC
    ac.begin();
    delay(200);
    ac.off();
  //Serial.println("Sending IR command to A/C ...");
    ac.send(); 
}

void motodatakoushin(int x){
  // Send request
    String postData,watasuData;
    watasuData = String(x);
    postData = "soushinData=" + watasuData ;

    Serial.println(watasuData);
    Serial.println(postData);
    Serial.println(x);
    
    HTTPClient http;    //Declare object of class HTTPClient
    http.begin("http://xxxxxxxxxxxxx.com/testPHP/phpRemocon2.php");
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    int httpCode = http.POST(postData);
    http.end();
}

phpRemocon1.php
(ESP8266のループから10秒間隔で呼び出されます。)
管理テーブルIrcontrolTableをチェックして赤外線LEDを光らせて
家電を操作してし終わったら管理テーブルを更新させるように動きます。

<?php

    $dbh= null;
    $user = null;
    $password = null;

    // データベースに接続するために必要なデータソースを変数に格納
    // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
    $dsn = 'mysql:host=hogehoge.com;dbname=hogehogeDatabeseName;charset=utf8'; 
    // データベースのユーザー名
    $user = 'hogehoge';
    // データベースのパスワード
    $password = 'hogehoge';

    $userData = array(); 

    // tryにPDOの処理を記述
    try {
        // PDOインスタンスを生成
        $dbh = new PDO($dsn, $user, $password);
        $sth = $dbh->prepare("SELECT * FROM IrcontrolTable WHERE irstatus = 0"); //SQLを準備
        $sth->execute();
        //SQLを実行
        
        $rowcount = 0; // カウンターセット                               
        while($row = $sth->fetch(PDO::FETCH_ASSOC)){        //SQLで取得したデータ($sth)から連想配列でフェッチして$rowに一行づつ入れる
        $userData[]=array(
        'iidnumber'=>$row['iridnumber'],
        'istats'=>$row['irstatus'],
        'iptyp'=>$row['irprocesstype'],
        'itext'=>$row['irtext'],
        );
        $rowcount++;
        }

            if($rowcount == 0){
                $userData[]=array(
                    'iidnumber'=>0,
                    'istats'=>9,
                    'iptyp'=>'NONR',
                    'itext'=>'No record',
                );
            }

        // エラー(例外)が発生した時の処理を記述
    }catch (PDOException $e) {
        // エラーメッセージを表示させる
            echo 'データベースにアクセスできません!' . $e->getMessage();
            
            // 強制終了
            exit;
    }



    //jsonとして出力
    //header('Content-type: application/json');           //ヘッダの作成(JSON出力の明確化)
    echo json_encode($userData[0]);                        //ユーザーデータ配列をJSON化!!!
   
?>

phpRemocon2.php
ESP8266で家電の電源入れたり消したりしたら管理テーブルIrcontrolTableの更新を行って
「終わったよ」と書き込んでおきます。

<?php

$uketoriiridnumber = $_POST['soushinData'];

// データベースに接続するために必要なデータソースを変数に格納
  // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
$dsn = 'mysql:host=hogehoge.com;dbname=hogehogeDatabeseName;charset=utf8'; 
    // データベースのユーザー名
    $user = 'hogehoge';
    // データベースのパスワード
    $password = 'hogehoge';
 
// tryにPDOの処理を記述
try {
  // PDOインスタンスを生成
  $dbh = new PDO($dsn, $user, $password);
// エラー(例外)が発生した時の処理を記述
} catch (PDOException $e) {
  // エラーメッセージを表示させる
  echo 'データベースにアクセスできません!' . $e->getMessage();
  // 強制終了
  exit;
}


// SELECT文を変数に格納
$sql = "UPDATE IrcontrolTable SET irstatus = 1, irupdatedate = NOW() WHERE iridnumber = $uketoriiridnumber";
// SQLステートメントを実行し、結果を変数に格納
$stmt = $dbh->query($sql);
 
?>

リモコン操作を指示するIrcontrolTableのDDS
ESP8266はPHPを介してこのテーブルをチェックしてます。

CREATE TABLE `IrcontrolTable` (
  `iridnumber` int(5) NOT NULL COMMENT '登録IDナンバー',
  `irstatus` int(5) NOT NULL DEFAULT '0' COMMENT '0:未処理 1:処理済',
  `irprocesstype` char(4) NOT NULL COMMENT '処理対象タイプ',
  `irtext` text NOT NULL COMMENT '備考',
  `ircreatedate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '登録タイムスタンプ',
  `irupdatedate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新タイムスタンプ'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


remoconGamen2.php
スマホ等で表示する指示画面(外出時のリモコン画面といったとこですね)
適当なサーバにアップロードしてブラウザから開いてください。

<html>
  <head>
    <link rel="stylesheet" href="rest.css" />
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
  <p class="textColor"> リモートリモコン</p>

<form action="../phpRemoconStatusUpdate.php" method="post">
    <button id="submit_button" type="submit" name="soushinId" value = 1> 扇風機オン </button>
    <button id="submit_buttonOFF" type="submit" name="soushinId" value = 4> 扇風機オフ </button>
    </br>
    </br>
    <button id="submit_button" type="submit" name="soushinId" value = 2> テレビオン </button>
    <button id="submit_buttonOFF" type="submit" name="soushinId" value = 5> テレビオフ </button>
    </br>
    </br>
    <button id="submit_button" type="submit" name="soushinId" value = 3> エアコンオン </button>
    <button id="submit_buttonOFF" type="submit" name="soushinId" value = 6> エアコンオフ </button>
    </br>
    </br>
    <button id="submit_button" type="submit" name="soushinId" value = 7> マルチチャンネル </button>
    </br>
    </br>

</form>

//同一画面に部屋の温度情報を表示させたい時はこんな感じで
<iframe id="inlineFrameExample"
    title="Inline Frame Example"
    width="600"
    height="2000"
    src="https://ambidata.io/ch/channel.html?id=hoehogehogehoge">
</iframe>

  </body>
</html>


phpRemoconStatusUpdate.php
ブラウザで開いたリモコン画面から呼ばれるPHPです
管理テーブルIrcontrolTableを更新してるだけの簡単なお仕事してます。
このPHPを利用してアレクサから利用できます

<?php

$uketoriiridnumber = $_POST['soushinId'];

// データベースに接続するために必要なデータソースを変数に格納
  // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
$dsn = 'mysql:host=hogehoge.com;dbname=hogehogeDatabeseName;charset=utf8'; 
    // データベースのユーザー名
    $user = 'hogehoge';
    // データベースのパスワード
    $password = 'hogehoge';
 
// tryにPDOの処理を記述
try {
  // PDOインスタンスを生成
  $dbh = new PDO($dsn, $user, $password);
// エラー(例外)が発生した時の処理を記述
} catch (PDOException $e) {
  // エラーメッセージを表示させる
  echo 'データベースにアクセスできません!' . $e->getMessage();
  // 強制終了
  exit;
}


// SELECT文を変数に格納
$sql = "UPDATE IrcontrolTable SET irstatus = 0, irupdatedate = NOW() WHERE iridnumber = $uketoriiridnumber";
// SQLステートメントを実行し、結果を変数に格納
$stmt = $dbh->query($sql);

header("refresh:2;url=testPHPGamen/remoconGamen2.php");
//print ("該当のリモコンが約10秒後に送信されます。<br>");
?>

<html>
  <head>
    <meta http-equiv=”refresh” content=”0;URL='testPHPGamen/remoconGamen2.php' />
    <link rel="stylesheet" href="rest.css" />
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
  <p class="textColor"> 10秒後にリモコンが起動します。</p>
  <p class="textColor"> このページは自動で戻ります。</p>

  </body>
</html>


style.css

@media screen and (min-width:0px){
    body{
      color: #5bc0de;
    }
  }
  
  @media screen and (min-width:300px){
    body{
      color: #d9534f;
    }
    
    p{
        font-size : 1.0rem ; /* これでフォントサイズは16pxになる*/
    }

    form{
        font-size : 1.0rem ; /* これでフォントサイズは16pxになる*/ 
    }

  }
  
  @media screen and (min-width:600px){
    body{
      color: #115a71;
    }
    p{
        font-size : 2.0rem ; /* これでフォントサイズは16pxになる*/
    }
    form{
      font-size : 1.6rem ; /* これでフォントサイズは16pxになる*/ 
    }
        button#submit_button {
        font-size: 1.0rem;
        font-weight: bold;
        background-color: #ff0000;
        width: 200px;
        height: 50px;
      }

        button#submit_buttonOFF {
        font-size: 1.0rem;
        font-weight: bold;
        background-color: #a8a7b3;
        width: 200px;
        height: 50px;
      }
  }


rest.css

/* 
html5doctor.com Reset Stylesheet
v1.6.1
Last Updated: 2010-09-17
Author: Richard Clark - http://richclarkdesign.com 
Twitter: @rich_clark
*/

html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
    margin:0;
    padding:0;
    border:0;
    outline:0;
    font-size:100%;
    vertical-align:baseline;
    background:transparent;
}

body {
    line-height:1;
}

article,aside,details,figcaption,figure,
footer,header,hgroup,menu,nav,section { 
    display:block;
}

nav ul {
    list-style:none;
}

blockquote, q {
    quotes:none;
}

blockquote:before, blockquote:after,
q:before, q:after {
    content:'';
    content:none;
}

a {
    margin:0;
    padding:0;
    font-size:100%;
    vertical-align:baseline;
    background:transparent;
}

/* change colours to suit your needs */
ins {
    background-color:#ff9;
    color:#000;
    text-decoration:none;
}

/* change colours to suit your needs */
mark {
    background-color:#ff9;
    color:#000; 
    font-style:italic;
    font-weight:bold;
}

del {
    text-decoration: line-through;
}

abbr[title], dfn[title] {
    border-bottom:1px dotted;
    cursor:help;
}

table {
    border-collapse:collapse;
    border-spacing:0;
}

/* change border colour to suit your needs */
hr {
    display:block;
    height:1px;
    border:0;   
    border-top:1px solid #cccccc;
    margin:1em 0;
    padding:0;
}

input, select {
    vertical-align:middle;
}


だらだらと一気に作ったので、効率的では無い構造になってたり
冗長的だったり雑ですが楽しかったのでよしとしますw。

次回はAmazon Alexaを使って声でリモコン操作します。

Arduino Unoとトランジスタと白色LED*2と私

f:id:appdeappuappu:20200604103329j:plain
トランジスタの文字小さい

白色LEDって必要な電圧も電流も他のいろのLEDよりも大きい。
二つ直列につないで光らせたくてもArduinoでは電圧が足りないし電流も心もとない。
そこで外部電源(エネループ直列5つ)で光らせます!!!

今回はUNOにトランジスタをつないでスイッチの役目をしてもらいます。


使ったトランジスタはこちら!↓
トランジスタ 2SC1815L−BL−T92−K 60V150mA (20個入): 半導体 秋月電子通商-電子部品・ネット通販


回路図と抵抗設計

f:id:appdeappuappu:20200604103716j:plain
抵抗値計算と実測値


回路と抵抗値はネットを漁れば簡単なものから複雑なものまでたくさん載ってますが
自分初心者なので簡単なやつで設計計算実測して見ました。

まずは、上の図で黒色で回路設計して見ました。
目的はUNOをスイッチとして使い、コレクタ部分で外部電源を引き込むことです。
わかっている情報は
コレクタ側:Vin 6.4v
白LED Vf 3V If 20mA
ベース側:5V
トランジスタ:hFE 350〜700

緑色では必要な抵抗値の計算をしています。
① Rc=(6.4-3-3)/0.02 = 20Ω
② IB=0.02/350 = 0.0000625A
③ RB=(5-0.7)/0.0000625 = 69kΩ

赤色はテスターで測定した結果です。
「何mA流れてるののかなぁ?」という素朴な疑問を実際に測定しただけです。
計算で算出するのが一般できなのかなぁ?自分としてはデバッグ的なノリでやってます。


結論
VBEはだいたいのトランジスタで一定で0.7Vこの電圧よりも大きな電圧をかければスイッチが入る!
おそらくトランジスタの付属資料記載のhFE最低値350を考えるとコレクタ系に0.062mA*350=217mAとなるが、データシートからコレクター電流の最大値は150mAとなりそうだ。
コレクタ系は上で計算した21.7Aまで流す事ができるが、オームの法則にしたがった電流量が流れるので、
抵抗RCの部分で見てみると実測値計算0.37V 実測値での計算=20Ω*0.0182A=0.362Vでほぼ一致した。


うん、簡単な回路ならトランジスタの働きわかった気がする。
中身の半導体での自由電子の挙動とかドーピングとかは学校で習ったきがするけど
その時はなんかの宗教みたいでピンとこなかったけど、こうやって実際に回路組むと
なんの役に立つのかよくわかりました。

アレクサお願い!!IFTTTでメールして!!!

IFTTTをいじって、アレクサに「アレクサ!テスト送信をトリガー!!!」
で自分宛にメールを送ってみよう。
amazonへの接続等は初めての場合はパスワード要求されるかな)

f:id:appdeappuappu:20200526094903j:plain
f:id:appdeappuappu:20200526094925j:plain
f:id:appdeappuappu:20200526094953j:plain
f:id:appdeappuappu:20200526095056j:plain
f:id:appdeappuappu:20200526095111j:plain
f:id:appdeappuappu:20200526095125j:plain
f:id:appdeappuappu:20200526095141j:plain
f:id:appdeappuappu:20200526095157j:plain
f:id:appdeappuappu:20200526095212j:plain
f:id:appdeappuappu:20200526095227j:plain

ここまでできたら
「アレクサ!テスト送信をトリガー!!!」
f:id:appdeappuappu:20200526100855j:plain


自分宛にしかメールできないのと
パラメータを渡せないのでこれだけでは
活用しにくいけど、それはそれでなんとかしましょう。


「〜をトリガー!」ってのがうざい場合は
Alexaアプリで定型アクションを作ってそこでこのIFTTTの
設定を起動するようにすればOK!

ESP8266からPHPにGETしてmySQLからのJSONデータをParseする

件名が長ったらしいですが、一連の流れが表れています。w
概要
1、PHPでデータベーステーブルに接続してSelect文を投げてからfetchしたデータを
  連想配列に突っ込んでJSONエンコードする。
2、ArduinoIDEでArduinoJsonをインクルードして1のphpにアクセスしてJSON
  受け取りParseする
3、Arduinoで分割した受け取りデータを分岐させて活用する。
  リモコンでもいいし、リモコンの送信データでも如何様にでも〜

注意
 Arduino公式が出してるJSONライブラリもある
 ArduinoJson5、ArduinoJson6があって古いネット情報では5の情報が多い
 この記事は6でやってるよ。


参考サイト
arduinojson.org
arduinojson.org
http://arduinojson.org/example.json
↑上記二つのリンクで使うJSONデータ



それでは実装してみましょう

順番は概要とは違いますが、ArduinoIDEでのコーディングから
RecieveJsonFromPhp.ino

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
/* Set these to your desired credentials. */
const char *ssid = "使えるSSID";  //ENTER YOUR WIFI SETTINGS
const char *password = "WIFIのパスワード";

void setup() {
  // put your setup code here, to run once:
  delay(1000);
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
  delay(1000);
  WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot
  
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");

  Serial.print("Connecting");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
}

void loop() {
  // Send request
    HTTPClient http;    //Declare object of class HTTPClient
    http.useHTTP10(true);
    //http.begin("http://arduinojson.org/example.json");//←これは参考にするJSONを返すURLです
    http.begin("ここにあなたが作ったJSONを返すPHPのURLを記述します");
    http.GET();

    // Parse response
    DynamicJsonDocument doc(2048);
    deserializeJson(doc, http.getStream());

    // Read values
    const char* id_recieve = doc["id"];
    Serial.println(id_recieve);
    int ondo_recieve = doc["ondo"];
    Serial.println(ondo_recieve);
    const char* time_recieve = doc["zikan"];
    Serial.println(time_recieve);

    http.end(); 
    delay(10000);
}

JSONを返すPHP

<?php
// データベースに接続するために必要なデータソースを変数に格納
  // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
$dsn = 'mysql:host=サーバドメイン;dbname=データベース名;charset=utf8'; 
  // データベースのユーザー名
$user = 'データベースユーザー名';
  // データベースのパスワード
$password = 'データベースへのアクセスパスワード';
// tryにPDOの処理を記述
try {
  // PDOインスタンスを生成
  $dbh = new PDO($dsn, $user, $password);
// エラー(例外)が発生した時の処理を記述
} catch (PDOException $e) {
  // エラーメッセージを表示させる
  echo 'データベースにアクセスできません!' . $e->getMessage();
  // 強制終了
  exit;
}

$sth = $dbh->prepare("SELECT文をここに入力!"); //SQLを準備
$sth->execute();                                   //SQLを実行

//$stest = $dbh->query($sql);

$userData = array();                               
while($row = $sth->fetch(PDO::FETCH_ASSOC)){        //SQLで取得したデータ($sth)から連想配列でフェッチして$rowに一行づつ入れる
    $userData[]=array(
    'id'=>$row['id_number'],
    'ondo'=>$row['temperatureField'],
    'zikan'=>$row['hizuke'],
    );
}

//print_r ($userData);                                //print_rで配列の中身を表示する(確認用後に削除する)

//echo "<br>";

//jsonとして出力
//header('Content-type: application/json');           //ヘッダの作成(JSON出力の明確化)
echo json_encode($userData[0]);                        //ユーザーデータ配列をJSON化!!!
//echo addslashes(json_encode($userData[0])); //配列0にしているのはselectデータの最初だけをJSONするため
//echo addslashes(json_encode($userData));     //addslashesはダブルコーテーションをバックスラッシュでエスケープする場合
//echo json_encode($sth); 
//var_dump(json_encode($userData));
?>
作成されるJSONデータ
{"id":"55","ondo":"54","zikan":"2020-05-22 14:53:06"}

id=連番
ondo=センサーからの温度
zikan=レコード作成時間
お好みでPHPやらデータベスのテーブルを作ってJSON作成してください。

スケッチを実行するとWifiにつながってURL投げてJSONゲットしてParseしてSerialPrintしてこうなります。

f:id:appdeappuappu:20200523101230p:plain
シリアルモニター

ESP8266からPHPにPOSTしてmySQLを更新する

概要
1、PHPでPOSTデータを受け取れるようにコーディングする。例えば温度データを受け取るとか
  その中で該当テーブルにSQLを投げてレコードを追加する。
2、ESP8266から上記phpにポストする。
その他 データベースのテーブルカラムは以下の感じでIDをオートインクリメント、時間はレコード作成時間
    にしておくと楽。(何も考えてない・・・w)
テーブルはこんな感じで!↓

f:id:appdeappuappu:20200523104037p:plain
テーブル例

/*
#include <ESP8266WiFi.h> 
#include <ESP8266HTTPClient.h>

/* Set these to your desired credentials. */
const char *ssid = "SSID";  //ENTER YOUR WIFI SETTINGS
const char *password = "パスワード";

//Web/Server address to read/write from 
//const char *host = "xxxxxxxx.さくら.net";   //https://circuits4you.com website or IP address of server

//=======================================================================
//                    Power on setup
//=======================================================================

void setup() {
  delay(1000);
  Serial.begin(115200);
  WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
  delay(1000);
  WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot
  
  WiFi.begin(ssid, password);     //Connect to your WiFi router
  Serial.println("");

  Serial.print("Connecting");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  //If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP
}

//=======================================================================
//                    Main Program Loop
//=======================================================================
void loop() {
  HTTPClient http;    //Declare object of class HTTPClient

  String postData,watasuData;
  //int adcvalue=analogRead(A0);  //Read Analog value of LDR
  //ADCData = String(adcvalue);   //String to interger conversion
  //station = "A";

  //Post Data
  int watasuValue = 54;
  watasuData = String(watasuValue);
  //postData = "status=" + ADCData + "&station=" + station ;
  postData = "ondoDataPara=" + watasuData ;
  
  http.begin("http://xxxxxx.さくら.ne.jp/ほにゃらら.php?");              //Specify request destination
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");    //Specify content-type header

  int httpCode = http.POST(postData);   //Send the request
  String payload = http.getString();    //Get the response payload

  Serial.println("*****");
  Serial.println(httpCode);   //Print HTTP return code
  Serial.println("*****");
  Serial.println(payload);    //Print request response payload
  Serial.println("*****");

  http.end();  //Close connection
  
  delay(10000);  //Post Data at every 5 seconds


  
}
//=======================================================================
<?php

$uketoriOndo = $_POST['ondoDataPara'];

// データベースに接続するために必要なデータソースを変数に格納
  // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード
$dsn = 'mysql:host=mysqlxxxx.db.xxxxx.ne.jp;dbname=データベース名;charset=utf8';
  // データベースのユーザー名
$user = 'データベースアクセスユーザー名';
  // データベースのパスワード
$password = 'アクセスパスワード';
 
// tryにPDOの処理を記述
try {
  // PDOインスタンスを生成
  $dbh = new PDO($dsn, $user, $password);
// エラー(例外)が発生した時の処理を記述
} catch (PDOException $e) {
  // エラーメッセージを表示させる
  echo 'データベースにアクセスできません!' . $e->getMessage();
  // 強制終了
  exit;
}


// SELECT文を変数に格納
$sql = "INSERT INTO テーブル名 (temperatureField) VALUES ($uketoriOndo)";
// SQLステートメントを実行し、結果を変数に格納
$stmt = $dbh->query($sql);
 
?>

esp8266(ESP wroom-02) を秋月電商の通販で買ってみた ハンダつけたりIDE設定してみたり Lチカしたり

f:id:appdeappuappu:20200521150842j:plain
wroom02
akizukidenshi.com

f:id:appdeappuappu:20200521150921j:plain
ピッチ変換基板
akizukidenshi.com

f:id:appdeappuappu:20200521151255j:plain
USBシリアル変換モジュール
akizukidenshi.com


購入したのは上記三点!
注文から中3日で手元に届きました。AmazonPrimeに慣れていると遅く感じますがコロナの影響もあるし
そのくらいが普通ですよね。

でお値段!
Wroom-02(ESP8266) ¥250
ピッチ変換基板        ¥120
USBシリアル変換モジュール  ¥850

USBシリアル変換モジュールを別にすると¥370円!!これでWifiにつながってArduinoっぽく使いまわせる。
ならお得かもですね。
秋月で大量買いするほど電子工作に慣れていないので送料¥400円を電車賃と考えるとそれはそれでOKですかね。

早速ハンダ付け!ハンダ盛りすぎましたもっと少なくていいみたいですね。

f:id:appdeappuappu:20200521153627p:plain
ハンダ下手すぎ

とりあえず、ATコマンドで通電確認しました!
シリアルモニタからAT+GMRでモジュールのバージョンが表示されていたのでOKでしょう。
(マルチテスター持ってないのでそもそも通電確認したことがないw)


回路の繋げ方等々はこちらの記事を参考にさせていただきました。
めちゃ整理されてて色々検索してたんですが、一発目でこちらの記事にぶち当たりたかったw

sucher.net


ここで少し疑問が・・・
今回購入したUSBシリアル変換モジュールはEsp8266が3.3V入力だったので
ディプスイッチで3.3Vと5Vを切り替えできると思って購入したのですが、なんと!

f:id:appdeappuappu:20200521160306j:plain
気になることが・・・

信号電圧が切り替えられるってだけでした・・・電源が3.3Vで出力できてるわけではなかった・・・
そのうちEsp8266が壊れるかもですね。まぁ安いしその時はその時で


それでは
Arduino IDE側の設定を!
環境設定で↓を
http://arduino.esp8266.com/stable/package_esp8266com_index.json
追加して→ボードマネージャからESP8266を追加インストールする。

ツール設定は以下のように!!

f:id:appdeappuappu:20200521161047p:plain
ツール設定

さてLチカのスケッチを以下の感じで書いてみましょう。

void setup() {
  // put your setup code here, to run once:
  //test
  pinMode(16, OUTPUT);
  Serial.begin(9200);
  Serial.println("Lチカ開始します");

}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(16, HIGH);   // LED ON
  Serial.println("On!");
  delay(1000);              
  digitalWrite(16, LOW);    // LED OFF
  Serial.println("Off!");
  delay(1000);              
}

コンパイルしてみると!!!!
コンパイルエラー!発生!!????
Python3で鍵使って署名してるみたいなんだけどその時のリンクが見つからないとか
ウンタラカンタラ・・・

解決方法は
github.com
小一時間ネットをさまよって、サラーっと読んでたら!あ!!!これじゃん!って
本当Github最高!


さてESP8266の書き込みモードは
www.switch-science.com
↑ここにあるように、
「モード切替ボタンはIO0番ピンにつながっています。ボタンを押すとIO0がLOW、放すとIO0がHIGHになります。IO0がHIGHの状態でリセットされるとファームウェアの実行モードで起動しますが、IO0がLOWの状態でリセットされるとファームウェアの書き込みモードで起動します。」

ということなので、
1、リセットボタンを押したままにする
2、IO0ボタンを押したままにする
3、リセットボタンを放す
4、IO0ボタンを放す
で書き込みモード突入!
5、IDEから実行バイナリを書き込み
6、リセットボタンを押して放してプロブラム実行モードにする


無事にコンパイルできたんで、ESP8266に書き込んでLチカできました!

あとでこのブレッドぼーどをユニバーサル基板作り直しておこうか
考え中。