Arduinoライブラリでテレビジョンを制御 家庭でできるIoT! 5パルス目 [ESP32]
前回( https://hamayan.blog.ss-blog.jp/2019-12-09-1 )作成したリモコンのコードを受信するプログラムを使って、テレビジョン(AQUOS)の幾つかのリモコンコードをサンプリングしました。その内容を使ってBlynkでリモコンを実現します。
もうお判りでしょうが、AQUOSライブラリを作成するにあたってHeatpumpIR Classを使って赤外線ドライバー部分はお手軽に実現しています。
テレビはNHKとテレ東くらいしか観ないので、Blynkのパネルの一番下に一発選局ボタンを付けておきました(笑)。
もうちょい機能を追加すれば、テレビのリモコン無くしても安心ですね!
aquos.h
aquos.cpp
スケッチの追加部分のみ
もうお判りでしょうが、AQUOSライブラリを作成するにあたってHeatpumpIR Classを使って赤外線ドライバー部分はお手軽に実現しています。
テレビはNHKとテレ東くらいしか観ないので、Blynkのパネルの一番下に一発選局ボタンを付けておきました(笑)。
もうちょい機能を追加すれば、テレビのリモコン無くしても安心ですね!
aquos.h
/****************************************************************************/ /* お家のAQUOSをなんとかするヘッダー */ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/ #ifndef aquos_h #define aquos_h #include <Arduino.h> #include <HeatpumpIR.h> extern "C" { // #include <mul_tsk.h> } /****************************************************************************/ /* なにかの定義 */ /****************************************************************************/ #define AEHA_T_PERIOD 425UL // #define AEHA_REPEAT_PERIOD 100UL // typedef struct /*AQUOSのフォーマットはAEHAタイプ*/ { uint8_t customerCode[2]; uint8_t data[4]; } AQUOS_CODE; class aquos : public HeatpumpIR { private: int antenaSelect; int channelSelect; uint32_t startTim; void send( IRSender& IR, const uint8_t *code, size_t size ); public: aquos(); void onOff( IRSender& IR ); void ch( IRSender& IR, int value ); void chUpDown( IRSender& IR, int value ); void volume( IRSender& IR, int value ); void antena( IRSender& IR ); void decide( IRSender& IR ); void back( IRSender& IR ); void program( IRSender& IR ); void recorderList( IRSender& IR ); void selectorSwitch( IRSender& IR, int upDown, int rightLeft ); void favorite( IRSender& IR, int sel ); char type( void ); }; #endif /*aquos_h*/ /****************************************************************************/ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/
aquos.cpp
/*********************************************************************************/ /* お家のAQUOSをなんとかするソース */ /* designed by hamayan since 2015/05/28 */ /*********************************************************************************/ #include "aquos.h" #if !defined( _MULTITASK_H_ ) #define dly_tsk(tim) delay(tim) #define rot_rdq() #define loc_cpu() interrupts() #define unl_cpu() noInterrupts() #endif /*_MULTITASK_H_ */ /*************************************************************************/ /* 大域変数宣言 */ /*************************************************************************/ /*************************************************************************/ /* プロトタイプ宣言 */ /*************************************************************************/ /*************************************************************************/ /* インスタンス */ /*************************************************************************/ aquos::aquos() { antenaSelect = 0; channelSelect = 1; } /*************************************************************************/ /* send */ /*************************************************************************/ void aquos::send( IRSender& IR, const uint8_t *code, size_t size ) { uint8_t tempUC[ size ]; memcpy( tempUC, code, size ); // 40 kHz PWM frequency IR.setFrequency( 38 ); //リピートでメソッドが呼ばれた時、強制的に間隔を開ける while( (millis() - startTim) < AEHA_REPEAT_PERIOD ) delay( 10 ); // start time startTim = millis(); // Header IR.mark( 8 * AEHA_T_PERIOD ); //frame ppm on IR.space( 4 * AEHA_T_PERIOD ); //frame ppm off // Data for( unsigned int i = 0; i < size; i++ ) { IR.sendIRbyte( tempUC[i], AEHA_T_PERIOD, AEHA_T_PERIOD, 3 * AEHA_T_PERIOD ); // data,426us,425us,1275us // pulse on period, pulse off period at ZERO, pulse off period at 1 } // End mark IR.mark( AEHA_T_PERIOD ); IR.space( 0 ); } /*************************************************************************/ /* 番組表 */ /*************************************************************************/ static const uint8_t TVPROGRAMLIST[] = {0xaa,0x5a,0x8f,0x12,0x60,0xf2}; void aquos::program( IRSender& IR ) { send( IR, TVPROGRAMLIST, sizeof( TVPROGRAMLIST ) ); } /*************************************************************************/ /* 電源の入り切。だが実際にはテレビがそれに追従してはいない。 */ /*************************************************************************/ static const uint8_t TVOnOff[] = {0xaa,0x5a,0x8f,0x12,0x16,0xd1}; void aquos::onOff( IRSender& IR ) { send( IR, TVOnOff, sizeof( TVOnOff ) ); } /*************************************************************************/ /* 決定ボタン */ /*************************************************************************/ static const uint8_t DECIDE[] = {0xaa,0x5a,0x8f,0x12,0x52,0xd1}; void aquos::decide( IRSender& IR ) { send( IR, DECIDE, sizeof( DECIDE ) ); } /*************************************************************************/ /* 戻るボタン */ /*************************************************************************/ static const uint8_t BACK[] = {0xaa,0x5a,0x8f,0x12,0xe4,0x01}; void aquos::back( IRSender& IR ) { send( IR, BACK, sizeof( BACK ) ); } /*************************************************************************/ /* 録画リスト */ /*************************************************************************/ static const uint8_t RECORDERLIST[] = {0xaa,0x5a,0x8f,0x12,0xad,0x3f}; void aquos::recorderList( IRSender& IR ) { send( IR, RECORDERLIST, sizeof( RECORDERLIST ) ); } /*************************************************************************/ /* 選択用スイッチ */ /*************************************************************************/ static const uint8_t SELECTORSWITCH[][6] = { {0xaa,0x5a,0x8f,0x12,0x57,0x81}, /*up*/ {0xaa,0x5a,0x8f,0x12,0x20,0x81}, /*down*/ {0xaa,0x5a,0x8f,0x12,0xd8,0xf1}, /*right*/ {0xaa,0x5a,0x8f,0x12,0xd7,0x01}, /*left*/ }; void aquos::selectorSwitch( IRSender& IR, int upDown, int rightLeft ) { if( upDown >= 1 ) send( IR, SELECTORSWITCH[0], sizeof( SELECTORSWITCH[0] ) ); else if( upDown <= -1 ) send( IR, SELECTORSWITCH[1], sizeof( SELECTORSWITCH[1] ) ); dly_tsk( 100UL ); if( rightLeft >= 1 ) send( IR, SELECTORSWITCH[2], sizeof( SELECTORSWITCH[2] ) ); else if( rightLeft <= -1 ) send( IR, SELECTORSWITCH[3], sizeof( SELECTORSWITCH[3] ) ); } /*************************************************************************/ /* チャネルの切り替え */ /*************************************************************************/ static const uint8_t TVCH[][6] = { {0xaa,0x5a,0x8f,0x12,0x4e,0x32}, /*ch1*/ {0xaa,0x5a,0x8f,0x12,0x4f,0x22}, /*ch2*/ {0xaa,0x5a,0x8f,0x12,0x50,0xc2}, /*ch3*/ {0xaa,0x5a,0x8f,0x12,0x51,0xd2}, /*ch4*/ {0xaa,0x5a,0x8f,0x12,0x52,0xe2}, /*ch5*/ {0xaa,0x5a,0x8f,0x12,0x53,0xf2}, /*ch6*/ {0xaa,0x5a,0x8f,0x12,0x54,0x82}, /*ch7*/ {0xaa,0x5a,0x8f,0x12,0x55,0x92}, /*ch8*/ {0xaa,0x5a,0x8f,0x12,0x56,0xa2}, /*ch9*/ {0xaa,0x5a,0x8f,0x12,0x57,0xb2}, /*ch10*/ {0xaa,0x5a,0x8f,0x12,0x58,0x42}, /*ch11*/ {0xaa,0x5a,0x8f,0x12,0x59,0x52}, /*ch12*/ }; void aquos::ch( IRSender& IR, int value ) { if( value >= 1 && value <= 12 ) { send( IR, TVCH[value - 1], sizeof( TVCH[0] ) ); channelSelect = value; } } /*************************************************************************/ /* チャネルの上下 */ /*************************************************************************/ static const uint8_t TVSEL[][6] = { {0xaa,0x5a,0x8f,0x12,0x11,0xa1}, /*decide up*/ {0xaa,0x5a,0x8f,0x12,0x12,0x91}, /*decide down*/ }; void aquos::chUpDown( IRSender& IR, int value ) { if( value > 0 ) //up { send( IR, TVSEL[0], sizeof( TVSEL[0] ) ); channelSelect++; } else if( value < 0 ) //down { send( IR, TVSEL[1], sizeof( TVSEL[1] ) ); channelSelect--; } } /*************************************************************************/ /* チューナー(アンテナ)の切り替え */ /*************************************************************************/ static const uint8_t TVANTENA[][6] = { {0xaa,0x5a,0x8f,0x12,0x89,0x82}, /*地デジ*/ {0xaa,0x5a,0x8f,0x12,0x8a,0xb2}, /*BS*/ {0xaa,0x5a,0x8f,0x12,0x8b,0xa2}, /*CS*/ }; void aquos::antena( IRSender& IR ) { if( ++antenaSelect > 1 ) antenaSelect = 0; send( IR, TVANTENA[antenaSelect], sizeof( TVANTENA[0] ) ); } /*************************************************************************/ /* ボリュームの上下 */ /*************************************************************************/ static const uint8_t TVVOLUME[][6] = { {0xaa,0x5a,0x8f,0x12,0x14,0xf1}, /*volume up*/ {0xaa,0x5a,0x8f,0x12,0x15,0xe1}, /*volume down*/ }; void aquos::volume( IRSender& IR, int value ) { if( value < 0 ) { send( IR, TVVOLUME[1], sizeof( TVVOLUME[1] ) ); } else if( value > 0 ) { send( IR, TVVOLUME[0], sizeof( TVVOLUME[0] ) ); } } /*************************************************************************/ /* お気に入り番組登録 */ /*************************************************************************/ void aquos::favorite( IRSender& IR, int value ) { if( value == 0 ) /* nhk sougou. */ { antenaSelect = 0; channelSelect = 1; } else if( value == 1 ) /* nhk bs premium. */ { antenaSelect = 1; channelSelect = 3; } else if( value == 2 ) /* tokyo televison. */ { antenaSelect = 0; channelSelect = 7; } else if( value == 3 ) /* bs tokyo televison. */ { antenaSelect = 1; channelSelect = 7; } else return; send( IR, TVANTENA[antenaSelect], sizeof( TVANTENA[0] ) ); send( IR, TVCH[channelSelect - 1], sizeof( TVCH[0] ) ); } /*************************************************************************/ /* リモコンフォーマットを答える */ /*************************************************************************/ char aquos::type( void ) { return 'A'; /*AEHAのA!*/ } /*********************************************************************************/ /* end of file */ /* designed by hamayan since 2015/05/28 */ /*********************************************************************************/
スケッチの追加部分のみ
aquos *tv = new aquos(); /*************************************************************************/ /* blynk virtual pin 6 function as TV power on or off. */ /*************************************************************************/ BLYNK_WRITE( V6 ) { tv->onOff( irSender ); } /*************************************************************************/ /* blynk virtual pin 7 function as TV program list on or off. */ /*************************************************************************/ BLYNK_WRITE( V7 ) { tv->program( irSender ); } /*************************************************************************/ /* blynk virtual pin 8 function as TV record list on or off. */ /*************************************************************************/ BLYNK_WRITE( V8 ) { tv->recorderList( irSender ); } /*************************************************************************/ /* blynk virtual pin 9 function as TV antena(tuner) change. */ /*************************************************************************/ BLYNK_WRITE( V9 ) { tv->antena( irSender ); } /*************************************************************************/ /* blynk virtual pin 10 function as channel NHK SOUGOU. */ /*************************************************************************/ BLYNK_WRITE( V10 ) { tv->favorite( irSender, 0 ); } /*************************************************************************/ /* blynk virtual pin 11 function as channel NHK BS PREMIUM. */ /*************************************************************************/ BLYNK_WRITE( V11 ) { tv->favorite( irSender, 1 ); } /*************************************************************************/ /* blynk virtual pin 12 function as channel TOKYO TELEVISION. */ /*************************************************************************/ BLYNK_WRITE( V12 ) { tv->favorite( irSender, 2 ); } /*************************************************************************/ /* blynk virtual pin 13 function as channel BS TOKYO TELEVISION. */ /*************************************************************************/ BLYNK_WRITE( V13 ) { tv->favorite( irSender, 3 ); } /*************************************************************************/ /* blynk virtual pin 14 function as cursor move. */ /*************************************************************************/ BLYNK_WRITE( V14 ) { int rightLeft = param[0].asInt(); int upDown = param[1].asInt(); tv->selectorSwitch( irSender, upDown, rightLeft ); } /*************************************************************************/ /* blynk virtual pin 15 function as channel up. */ /*************************************************************************/ BLYNK_WRITE( V15 ) { int channel = param.asInt(); tv->chUpDown( irSender, channel ); } /*************************************************************************/ /* blynk virtual pin 16 function as channel down. */ /*************************************************************************/ BLYNK_WRITE( V16 ) { int channel = param.asInt(); tv->chUpDown( irSender, channel ); } /*************************************************************************/ /* blynk virtual pin 17 function as volume up. */ /*************************************************************************/ BLYNK_WRITE( V17 ) { int volume = param.asInt(); tv->volume( irSender, volume ); } /*************************************************************************/ /* blynk virtual pin 18 function as volume down. */ /*************************************************************************/ BLYNK_WRITE( V18 ) { int volume = param.asInt(); tv->volume( irSender, volume ); } /*************************************************************************/ /* blynk virtual pin 19 function as decide button. */ /*************************************************************************/ BLYNK_WRITE( V19 ) { tv->decide( irSender ); } /*************************************************************************/ /* blynk virtual pin 20 function as back button. */ /*************************************************************************/ BLYNK_WRITE( V20 ) { tv->back( irSender ); }
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~12畳 SH8237LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン
オーデリック LEDシーリングライト リモコン付き LED一体型 電球色~昼光色 調光・調色タイプ ~14畳 SH8234LDR
- 出版社/メーカー: オーデリック
- メディア: ホーム&キッチン