SSブログ

Arduinoライブラリでテレビジョンを制御 家庭でできるIoT! 5パルス目 [ESP32]

2019-12-13 09.13.34.png2019-12-13 09.13.27.png前回( https://hamayan.blog.ss-blog.jp/2019-12-09-1 )作成したリモコンのコードを受信するプログラムを使って、テレビジョン(AQUOS)の幾つかのリモコンコードをサンプリングしました。その内容を使ってBlynkでリモコンを実現します。
もうお判りでしょうが、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 );
}



ESP-WROOM-02開発ボード

ESP-WROOM-02開発ボード

  • 出版社/メーカー: スイッチサイエンス(Switch Science)
  • メディア: おもちゃ&ホビー









nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。