Control de volumen remoto del decodificador de TV IP usando Attiny13A

Una vez recibí una llamada de Rostelecom y me ofrecí a conectar IP TV. Bueno, decidí dejar que la esposa y el hijo vieran dibujos animados en el dormitorio y acepté. Y luego me trajeron la codiciada caja. Porque No tengo un televisor separado, así que decidí conectarlo a un monitor antiguo a través de un adaptador HDMI-VGA. Para el sonido, tenía altavoces de computadora viejos. Decidido - hecho. Todo comenzó bien con una cosa: desde el control remoto que viene con el decodificador, es imposible ajustar el volumen del sonido. ¿Como es eso? Honestamente, nunca me he encontrado con algo así. Realmente no entendí las razones, pero parece que el control remoto de Rostelecom está registrado en el televisor, por lo que el volumen del televisor cambia desde el control remoto y no en la salida del decodificador. Convenientemente? Por supuesto, si conecta el decodificador a un televisor moderno.Pero levantarse de la cama y girar el tocadiscos en los altavoces cada vez que necesite cambiar el volumen es un inconveniente. Nos ocuparemos de este problema. Montaremos un dispositivo independiente que ajustará el volumen de nuestros altavoces según la señal del mando a distancia.



Primero, veamos qué tipo de señales genera el control remoto al presionar los botones "subir volumen", "bajar volumen" y "silenciar". Usé VS1838B como receptor de señales del control remoto.



Este es un receptor útil porque ya demodula la señal infrarroja de 38 kHz del control remoto.



Resultó que los botones anteriores generan dos tipos de señales alternativamente. Primero una opción, la próxima vez que presione otra opción. La figura muestra una de las opciones de señal al presionar el botón "mute". Las señales se leyeron utilizando un analizador lógico.



Gráfico de señal del analizador lógico



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 , - . .



( ), .



Placa de circuito impreso



9 , , 78L05.



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



Tablero de columna



:



Vista desde arriba



Vista inferior



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



, .



:






All Articles