使用Attiny13A远程控制IP电视机顶盒的音量

一旦我接到Rostelecom的电话,并提出要连接IP TV。好吧,我决定让妻子和儿子在卧室里看动画片,并表示同意。然后他们给我带来了令人垂涎的盒子。因为我没有单独的电视,所以我决定通过HDMI-VGA适配器将其连接到旧显示器。对于声音,我有旧的电脑扬声器。决定-完成。一切都可以通过一件事开始:从机顶盒随附的遥控器开始,无法调节音量。那个怎么样?老实说,我从未遇到过这样的事情。我并不清楚原因,但似乎Rostelecom的遥控器已在电视上注册,因此电视本身的音量是通过遥控器更改的,而不是机顶盒的输出。方便吗当然,如果您将机顶盒连接到现代电视。但是,每次需要更改音量时,起床并打开扬声器就很不方便。我们将处理此问题的解决方案。我们将组装一个单独的设备,该设备将根据遥控器的信号调节扬声器的音量。



首先,让我们看看遥控器在按下“提高音量”,“降低音量”和“静音”按钮时会产生什么样的信号。我使用VS1838B作为遥控器的信号接收器。



这是一个方便的接收器,因为 它已经解调了来自遥控器的38kHz红外信号。



事实证明,以上按钮交替生成两种类型的信号。第一个选项,然后按另一个选项。该图显示了按下“静音”按钮时的信号选项之一。使用逻辑分析仪读取信号。



逻辑分析仪信号图



100 . 24- . ( ) 900 , ( , ) 1800 . , , :



1. .



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0
2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0
Mute 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0
Mute 2 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0


. , 50. .. , , — . "" . X9C103P. 10 . , , , 10 . .



VS1838B. . , , , . , , , . Attiny13A. : , . : 1 64 SRAM. (Atmega 328) 32 2 SRAM.



, , - . , :



const unsigned long UP1_DATA[] =   {860, 900, 1750, 900, 860, 900, 860, 900, 860, 900, 860, 900, 860, 900, 860, 1750, 1750, 900, 860, 900, 860, 900, 860};


, attiny . . — , .. . : , 6- 15-, 19- 20- — . . — . . 8 ( 2).



2 — 1



1 2 3 4 5 6 7 8
1 1 0 0 1 1 0 0 0
2 0 0 1 1 1 0 0 0
1 0 0 1 1 1 0 0 1
2 1 0 0 1 1 0 0 1
Mute 1 0 0 1 0 0 1 1 1
Mute 2 1 0 0 0 0 1 1 1


:



#define UP1_DATA      0b00011001
#define UP2_DATA      0b00011100
#define DOWN1_DATA    0b10011100
#define DOWN2_DATA    0b10011001
#define MUTE_ON_DATA   0b11100100
#define MUTE_OFF_DATA   0b11100001


. , ( ) . . , .



. _timer:



volatile unsigned long _timer = 0;

ISR(TIM0_OVF_vect)
{
    _timer++;
}


Attiny13A 9,6 . 256 , 37500 . 900 33 , 1800 67 . , 9,6 , .



getExpectedTime, ,
#define SHORT_TIME 33UL
#define LONG_TIME 67UL

uint8_t _counter = 0;

unsigned long getExpectedTime(uint8_t data)
{
    uint8_t index;
    if (_counter >= 2 && _counter <= 4)
    {
        index = _counter - 2;
    }
    else if (_counter >= 15 && _counter <= 17)
    {
        index = _counter - 12;
    }
    else if (_counter >= 20 && _counter <= 21)
    {
        index = _counter - 14;
    }
    else
    {
        return SHORT_TIME;
    }
    if (data & (1 << index)) return LONG_TIME;
    return SHORT_TIME;
}




_counter — . data — 6 : UP1_DATA, UP2_DATA, DOWN1_DATA, DOWN2_DATA, MUTE_1_DATA, MUTE_2_DATA.


.. , , ( ) getExpectedTime . — .





volatile bool _hasPulse = false;
volatile unsigned long _RXPreviousTime = 0;
volatile unsigned long _pulseDuration = 0;

ISR(INT0_vect)
{
    _pulseDuration = _timer - _RXPreviousTime;
    _RXPreviousTime = _timer;
    _hasPulse = true;
    _rxPinStatus = !!(PINB & (1 << RX_PIN)); // digitalRead  .
}


,



incrementCounter,
#define SIZE_OF_PATTERNS 6
#define PAUSE_TIME 375UL //10000 
#define HAS_PATTERN_START 0b00111111
#define ERROR_VALUE 19UL
#define SIZE_OF_DATA 23

#define UP1_BT 0
#define UP2_BT 1
#define DOWN1_BT 2
#define DOWN2_BT 3
#define MUTE_ON_BT 4
#define MUTE_OFF_BT 5

//         : UP1_BT, UP2_BT, DOWN1_DATA, DOWN2_DATA, MUTE_ON_BT, MUTE_OFF_BT
const uint8_t PATTERNS[] = {UP1_DATA, UP2_DATA, DOWN1_DATA, DOWN2_DATA, MUTE_ON_DATA, MUTE_OFF_DATA};
uint8_t _hasPattern = HAS_PATTERN_START;

//   ,       PATTERNS.
uint8_t incrementCounter() //   ,       PATTERNS.
{
    if (_pulseDuration > PAUSE_TIME)
    {
        _counter = 0;
        _hasPattern = HAS_PATTERN_START;
        return 255;
    }
    if (_hasPattern)
    {
        unsigned long eTime;
        for (uint8_t i = 0; i < SIZE_OF_PATTERNS; i++)
        {
            if (_hasPattern & (1 << i)) //   .
            {
                eTime = getExpectedTime(PATTERNS[i]);
                if (!((_rxPinStatus ^ !!(_counter % 2)) && _pulseDuration >= eTime - ERROR_VALUE && _pulseDuration <= eTime + ERROR_VALUE)) //  .
                {
                    _hasPattern &= ~(1 << i);
                }
            }
        }
        _counter++;
        if (_counter == SIZE_OF_DATA)
        {
            if (_hasPattern) //-  
            {

                switch (_hasPattern)
                {
                    case 1: return UP1_BT;
                    case 2: return UP2_BT;
                    case 4: return DOWN1_BT;
                    case 8: return DOWN2_BT;
                    case 16: return MUTE_ON_BT;
                    case 32: return MUTE_OFF_BT;
                    default: return 255;
                }
            }
            else
            {
                return 255;
            }
        }
        else
        {
            return 255; //    
        }
    }
    else
    {
        return 255; //   
    }
}


_hasPattern — , . 1. -, , 0. , - . PATTERNS.



, X9C103P.



1020 1024 , , (-Os). GitHub. UNO, .. , Attiny13A. UNO , - . .



( ), .



印刷电路板



9 , , 78L05.



8 : 3 , 3 . UTP , 8 . , .



立柱板



:



从上方查看



底视图



, , , -. , GND , . . , smd 100 , .



, .



:






All Articles