見出し画像

Amazon Echo Dot(第3世代)とESPr Developerでシャープのアクオスをあやつる。

【はじめのはじめ】
はんだごて持って、みんなで作りましょうよ!
もし分からないところがあれば、コメント欄にご記入ください。出来る限り、対応します。。。


【はじめに】
 Amazon Echo Dot単体では、赤外線送信の機能がありません。よって、テレビのリモコンみたいに使いたければ別途、赤外線が送信できるスマートリモコンを導入しなければなりません。このスマートリモコンは5,000円ぐらいからあります。Echo dotも約6,000円しますので、ここでの11,000円ぐらいの出費は痛いものがあります。(たまにEcho自体のセールをやるときがありますが)もっと、機能限定されてもいいから、安価にできないかな?と思いついたのが、マイコンをであるこのESPr Developperを使った自作リモコンです。このボードは1つ約2,000円ですが、プログラム次第では何とでもコントロールできてしまいます。ちょっと本当にできるか実験したいと思います。もちろん、色々なサイトでこのような事をされている方がおられます。真似をしてみましたが、ことごとく失敗に終わってます。2世代目のEcho dotだったら上手く出来たかもしれませんが。。。

もちろん、このnote無料ですが。。。サポート頂けると幸いです。

【主に準備したモノ】
➀Amazon Echo Dot
②ESPr Developper
③赤外線LEDと抵抗
その他、電線、ハンダ、ブレッドボードなどが必要です。

【ハードウエア】
一応、下図のような感じの回路でOKです。

写真でいうとデジタルIOの4番にLEDの+を、その右にLEDのーを。LEDによって違いますが、このLEDの場合、33Ωの抵抗をかませてあります。この抵抗がないとLEDは死んでしまいます。ハードウエアはこれで完成です。簡単なんです。ここまでは。パソコンとUSBでつないじゃいます。

ハードウエアは、最終的にはこのような形になりました。

【ソフトウエア】
◎少なくとも、ここまではわかっています。

 まず、このAmazon Echo Dotと、ESPr Developperで、Belkin WeMo 家庭用電源リモートスイッチをマイコンの中に作って、自由にON/OFF制御をする。→これリモコンに活用できるじゃん。ていうことになります。
 ちなみに、Amazon Echo Dot(第3世代)とesp8266-alexa-wemo-emulatorとは相性が悪いみたいで、サーバーが応答しないとかエラーとかで使えません。そこで、fauxmoesp を使う事にしました。ソースもここhttps://bitbucket.org/xoseperez/fauxmoesp)から引用してモデファイしております。これも、一癖あって、赤外線LEDをコントロールするためのライブラリであるIRremoteが使えません。別途、IRremoteに代わるものを作らないといけません。(ヒントあれば教えてください)
 あと、うちのテレビ、シャープの古いアクオスですが、リモコンが発信するデータを事前に取っておきました。(公表しちゃっていいのかどうか..)このデータを吸い出す方法は、ググれば出てきます。検索ワードは「echo esp8266 スマートホーム リモコン テレビ」です。

ちなみに、吸いだしたデータとしては、下記になります。

btn_電源	            0x555AF148688B
btn_消音    	    0x555AF148E883
btn_1	            0x555AF148724C
btn_2	            0x555AF148F244
btn_3	            0x555AF1480A43
btn_4	            0x555AF1488A4B
btn_5               0x555AF1484A47
btn_6	            0x555AF148CA4F
btn_7	            0x555AF1482A41
btn_8	            0x555AF148AA49
btn_9	            0x555AF1486A45
btn_10	            0x555AF148EA4D
btn_11	            0x555AF1481A42
btn_12	            0x555AF1489A4A
btn_地デジ       0x555AF1489141
btn_BS	            0x555AF148514D
btn_CS	            0x555AF148D145
btn_d	            0x555AF1487A44
btn_Vol_up	    0x555AF148288F
btn_Vol_down	    0x555AF148A887
btn_チャンネル_up     0x555AF1488885
btn_チャンネル_down   0x555AF1484889
btn_入力切替      0x555AF148C881
btn_番組表	    0x555AF148064F
btn_裏番組	    0x555AF148AE4D
btn_番組情報	    0x555AF148FA4C
btn_↑	            0x555AF148EA81
btn_↓    	    0x555AF1480481
btn_←	            0x555AF148EB80
btn_→	            0x555AF1481B8F
btn_終了    	    0x555AF148AF80
btn_戻る    	    0x555AF1482780
btn_青	            0x555AF1480148
btn_赤	            0x555AF1488140
btn_緑	            0x555AF148414C
btn_黄        	    0x555AF148C144

マイコンをプログラミングし、このデータを送信することによって、リモコンとして動作させます。

 このマイコンにやらせたい事を大まかにプログラミングしました。さて、次に赤外線送出の所のプログラミングを始めます。「赤外線リモコンの通信フォーマット」を参考させていただきます。果たしてプログラミングできるかがキモになります。ちなみに、シャープは家製協(AEHA)フォーマットです。
そのソースは、こちら。一応、色々盛り込みました。。キタナイソースですが。下記ソース中のFire_tv()、Blu_ray()の中身は、空白にしてあります。これは、どの機器が、どのHDMI端子に刺さってるかによりかわるので。
静岡県に合わせてますので、地デジチャンネルのところの関数名も、その地域に合わせて変えて使ってください。CSは家では観てないので、そこらへんもカットしてあります。プログラム中のスイッチを増設して、割り当ててみてください。


/// リビングのテレビリモコン for SHARP LC-37GX2W(古っ)
/// Amaon Dot Echo でコントロールしてみよう。
/// AEHAフォーマットです。


#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "fauxmoESP.h"
#define SERIAL_BAUDRATE 115200
#define IR_LED 4
#define LED 3
#define delay_time 250
const unsigned long T = 425;
fauxmoESP fauxmo;
char ssid[] = "xxxxx";      //WIFIのSSIDを入力してください
char password[] = "xxxxxx";  //そのSSIDに対するパスワードを入力してください。
char btn_sw[]             = "555AF148688B";
char btn_mute[]           = "555AF148E883";
char btn_1[]              = "555AF148724C";
char btn_2[]              = "555AF148F244";
char btn_3[]              = "555AF1480A43";
char btn_4[]              = "555AF1488A4B";
char btn_5[]              = "555AF1484A47";
char btn_6[]              = "555AF148CA4F";
char btn_7[]              = "555AF1482A41";
char btn_8[]              = "555AF148AA49";
char btn_9[]              = "555AF1486A45";
char btn_10[]             = "555AF148EA4D";
char btn_11[]             = "555AF1481A42";
char btn_12[]             = "555AF1489A4A";
char btn_Digital[]        = "555AF1489141";
char btn_BS[]             = "555AF148514D";
char btn_CS[]             = "555AF148D145";
char btn_d[]              = "555AF1487A44";
char btn_Vol_up[]         = "555AF148288F";
char btn_Vol_down[]       = "555AF148A887";
char btn_ch_select_up[]   = "555AF1488885";
char btn_select_down[]    = "555AF1484889";
char btn_input_selector[] = "555AF148C881";
char btn_timetable[]      = "555AF148064F";
char btn_urabangumi[]     = "555AF148AE4D";
char btn_information[]    = "555AF148FA4C";
char btn_up[]             = "555AF148EA81";
char btn_down[]           = "555AF1480481";
char btn_left[]           = "555AF148EB80";
char btn_right[]          = "555AF1481B8F";
char btn_exit[]           = "555AF148AF80";
char btn_return[]         = "555AF1482780";
char btn_blue[]           = "555AF1480148";
char btn_red[]            = "555AF1488140";
char btn_green[]          = "555AF148414C";
char btn_yellow[]         = "555AF148C144";
char bin[16][5] = {
  "0000",  "0001",  "0010",  "0011",
  "0100",  "0101",  "0110",  "0111",
  "1000",  "1001",  "1010",  "1011",
  "1100",  "1101",  "1110",  "1111"
};
void power_sw();
void mute();
void vol_up();
void vol_down();
void vol_up_more();
void vol_down_more();
void Fire_tv();
void Blu_ray();
void blue();
void red();
void green();
void yellow();
void d_sw();
void NHK();
void NHK_E();
void daiichi();
void asahi();
void SBS();
void tereshizu();
void BS1();
void BS_Premium();
void BS_nittere();
void BS_asahi();
void BS_TBS();
void BS_teretou();
void BS_FUJI();
void BS_11();
void BS_12();
void timetable();
void ir_send();
void sub_carrier();
void wait();
void leader();
void trailer();
void transmit_IR();

// -----------------------------------------------------------------------------
// Wifi
// -----------------------------------------------------------------------------

void wifiSetup() {
  // Set WIFI module to STA mode
  WiFi.mode(WIFI_STA);
  // Connect
  Serial.printf("[WIFI] Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  // Wait
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  // Connected!
  Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
}
void setup() {
  // Init serial port and clean garbage
  Serial.begin(SERIAL_BAUDRATE);
  Serial.println();
  Serial.println();
  // Wifi
  wifiSetup();
  // status
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
  pinMode(IR_LED, OUTPUT);
  digitalWrite(IR_LED, LOW);
  // You have to call enable(true) once you have a WiFi connection
  // You can enable or disable the library at any moment
  // Disabling it will prevent the devices from being discovered and switched
  fauxmo.enable(true);
  // Add virtual devices
  fauxmo.addDevice("LVTV00"); // 0
  fauxmo.addDevice("LVTV01"); // 1
  fauxmo.addDevice("LVTV02"); // 2
  fauxmo.addDevice("LVTV03"); // 3
  fauxmo.addDevice("LVTV04"); // 4
  fauxmo.addDevice("LVTV05"); // 5
  fauxmo.addDevice("LVTV06"); // 6
  fauxmo.addDevice("LVTV07"); // 7
  fauxmo.addDevice("LVTV08"); // 8
  fauxmo.addDevice("LVTV09"); // 9
  fauxmo.addDevice("LVTV10"); // 10
  fauxmo.addDevice("LVTV11"); // 11
  fauxmo.addDevice("LVTV12"); // 12
  fauxmo.addDevice("LVTV13"); // 13
  fauxmo.addDevice("LVTV14"); // 14
  fauxmo.addDevice("LVTV15"); // 15
  //
  // fauxmoESP 2.0.0 has changed the callback signature to add the device_id,
  // this way it's easier to match devices to action without having to compare strings.
   fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state) {
    int id;
    Serial.printf("[MAIN] Device #%d (%s) state: %s\n", device_id, device_name, state ? "ON" : "OFF");
    Serial.printf("id:%s\n", device_name);
    if (device_id == 0)
    {
      state ?  power_sw() : mute();
    }
    else if (device_id ==1)
    {
      state ? vol_up() : vol_down();
    }
    else if (device_id == 2) {
      state ? vol_up_more() : vol_down_more();
    }
    else if (device_id == 3) {
      state ? Fire_tv() : Blu_ray();
    }
    else if (device_id == 4) {
      state ? blue() : red();
    }
    else if (device_id == 5) {
      state ? green() : yellow();
    }
    else if (device_id == 6) {
      state ? d_sw() : timetable();
    }
    else if (device_id == 7) {
      state ? NHK() : NHK_E();
    }
    else if (device_id == 8) {
      state ? daiichi() : asahi();
    }
    else if (device_id == 9) {
      state ? SBS() : tereshizu();
    }
    else if (device_id == 10) {
      state ? BS1() : BS_Premium();
    }
    else if (device_id == 11) {
      state ? BS_nittere() : BS_asahi();
    }
    else if (device_id == 12) {
      state ? BS_TBS() : BS_teretou();
    }
    else if (device_id ==13) {
      state ? BS_FUJI() : BS_11();
    }
    else if (device_id ==14) {
      BS_12();
    }
   
    else {
    }
    digitalWrite(LED, state);
  });
  // Callback to retrieve current state (for GetBinaryState queries)
  fauxmo.onGetState([](unsigned char device_id, const char * device_name) {
    return digitalRead(LED);
  });

}
 
}
void loop() {

  // Since fauxmoESP 2.0 the library uses the "compatibility" mode by
  // default, this means that it uses WiFiUdp class instead of AsyncUDP.
  // The later requires the Arduino Core for ESP8266 staging version
  // whilst the former works fine with current stable 2.3.0 version.
  // But, since it's not "async" anymore we have to manually poll for UDP
  // packets
  fauxmo.handle();

  //static unsigned long last = millis();
  //if (millis() - last > 5000) {
  //  last = millis();
  //  Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
  //}
}

void power_sw() {
  wait(1000000);
  ir_send(btn_sw);
}
void mute() {
  ir_send(btn_mute);
}
void vol_up() {
  ir_send(btn_Vol_up);
}
void vol_down() {
  ir_send(btn_Vol_down);
}
void vol_up_more() {
  ir_send(btn_Vol_up);
  wait(250000);
  ir_send(btn_Vol_up);
  wait(250000);
  ir_send(btn_Vol_up);
  wait(250000);
  ir_send(btn_Vol_up);
  wait(250000);
  ir_send(btn_Vol_up);
}
void vol_down_more() {
  ir_send(btn_Vol_down);
  wait(250000);
  ir_send(btn_Vol_down);
  wait(250000);
  ir_send(btn_Vol_down);
  wait(250000);
  ir_send(btn_Vol_down);
  wait(250000);
  ir_send(btn_Vol_down);
}
void Fire_tv() {
  
}
void Blu_ray() {
  
}
void blue() {
  ir_send(btn_blue);
}
void red() {
  ir_send(btn_red);
}
void green() {
  ir_send(btn_green);
}
void yellow() {
  ir_send(btn_yellow);
}
void d_sw() {
  ir_send(btn_d);
}
void timetable() {
  ir_send(btn_timetable);
}
//地デジチャンネル
void NHK() {
  ir_send(btn_Digital);
  wait(250000);
  ir_send(btn_1);
}
void NHK_E() {
  ir_send(btn_Digital);
  wait(250000);
  ir_send(btn_2);
}
void daiichi() {
  ir_send(btn_Digital);
  wait(250000);
  ir_send(btn_4);
}
void asahi() {
  ir_send(btn_Digital);
  ir_send(btn_5);
}
void SBS() {
  ir_send(btn_Digital);
  wait(250000);
  ir_send(btn_6);
}
void tereshizu() {
  ir_send(btn_Digital);
  wait(250000);
  ir_send(btn_8);
}
//BSチャンネル
void BS1() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_1);
}
void BS_Premium() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_3);
}
void BS_nittere() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_4);
}
void BS_asahi() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_5);
}
void BS_TBS() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_6);
}
void BS_teretou() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_7);
}
void BS_FUJI() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_8);
}
void BS_11() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_11);
}
void BS_12() {
  ir_send(btn_BS);
  wait(250000);
  ir_send(btn_12);
}
void ir_send(char *raw_data) {
  unsigned int i;
  unsigned int rawdata_length;
  char ir_send_data[rawdata_length];
  rawdata_length = strlen(raw_data);
  char s[2];
  leader();
  for (i = 0; i < rawdata_length; i++) {
    sprintf(s, "%c", raw_data[i]);
    sub_carrier(bin[strtol(s, NULL, 16)]);
  }
  trailer();
}
void sub_carrier(char *data) {
  int i, j, d;
  unsigned long now;
  for (i = 0; i < 4; i++)
  {
    d = data[i] - 48;
    for (j = 0; j < 15; j++) {
      transmit_IR();
    }
    d ? wait(3 * T) : wait(T);
  }
}
void leader()
{
  unsigned long now;
  now = micros();
  while (micros() - now < 8 * T + 200)
  {
    transmit_IR();
  }
  wait(4 * T);
}
void trailer()
{
  int j;
  for (j = 0; j < 15; j++) {
    transmit_IR();
  }
}
void wait(unsigned long wait_time)
{
  unsigned long start_time = micros();
  while ((4294967295 - start_time) <= (unsigned long)(wait_time * 1.01))
  {
    delay(1);
  }
  while (micros() - start_time < wait_time) {
    delay(1);
  }
}
void transmit_IR() {
  digitalWrite(IR_LED, HIGH);
  wait(8);
  digitalWrite(IR_LED, LOW);
  wait(17);
}



ちなみに、下のスクショは、コンパイル条件です。

今度は、NECフォーマットを仕込みにかかります。

とりあえず、以上です。

この記事が気に入ったらサポートをしてみませんか?