www.audiodesignguide.com

Remote volume control

by Andrea Ciuffoli - starting in the May 2007
contact me for any problem or question: webmaster @ audiodesignguide.com

INTRODUCTION

In all my projects I am using a DACT stepper attenuator instead of the normal ALPS or NOBLE solution, but in same case, like AV systems, could be usefull use a remote command.

 

 

COMPONENTS

There are many chips with the function of digital potentiometer but only few of these are true Audio Volume Control with Hi-End characteristics.

The first chip is the Crystal CS3310 used by many companies on the market like the Jeff Rowland (see article about - mirror).

To use these chips it is necessary a microcontroller to interface all the necessary parts (IR received, push buttons, rotary encoder, display).

These are the main chips:

Company Part Number   Gain (dB)    Attenuation (dB)   Interchannel Crosstalk @ 1 kHz (dBFS)   THD + N @ 1 kHz (%)   Analog Supply (V)   Digital Supply  (V)   Control Interface   Pin/Package  
Crystal CS3310 31.5 -95.5     +/-5 5 SPI SOIC-16
Burr-Brown PGA2310 31.5 -95.5 -126 0.0004 +/-15 5 SPI DIP-16 / SOL-16
Burr-Brown PGA2311 31.5 -95.5 -126 0.0002 +/-5 5 SPI DIP-16 / SOL-16
Wolfson WF8816 15.5 -111.5 -110 0.00001 +/-5 5 SPI SOIC-16

 

 

 

 

 

About the remote command now I am using an old Philips hifi remote control RC07104/01 still available on some Ebay stores but I am still searching a final product for this purpuse.

I have develop also a simple remote command with a very litle PIC the 12F629 by Microchip.

The RC5 protocol of Philips remote command is available in many documents like these one:

and the receiver used is the Vishay TSOP1836

I have used a normal and cheap 16 x 2 LCD HD-44780 compatible like this one:

To test the Wolfson chip I have got the evaluation board WM8816-EV1M available on Wolfson webite at about 100$.

I have used an old CS3310 with DIP package but it is no more available.

To program the microcontroller I have used the PICKIT 2 USB Development Programmer/Debugger (cod. PG164120 or DV164121) with a cost about 40-50$

I love the C language because it is very simple if compared to assembler.

The my C source has been compiled with HI-TECH PICC-Lite Compiler.

HI-TECH Software has provided a  freeware HI-TECH PICC-Lite compiler as a tool for hobbyists and students, but the licence allows its use for commercial purposes as well. It is ideal as a teaching tool for an introduction into the 'C' language and embedded programing on a Microchip device.

 

Here you can download the last version 10 July 2007 

SCHEMATIC

 

REMOTE COMMAND

In the photo is show the 2 version of the custom RC5 remote command create to complete the project.

One version have the ICSP connector to program the microchip with the PICKIT 2.

The second one have a simple 78L05 regulator on power supply to reduce the voltage of the 12V micro battery.

The schematic is quite a copy of the project seen on:

http://www.sixca.com/eng/articles/remote/

(for the mirror click here)

but the software has been written in C language instead of assembler to be simpler and to use a carrier frequency 36KHz instead of 38KHz to be compatible with the receiver.

To get better performances the 4MHz quartz has been changed with one at  20MHz.

#include <pic.h>
#include <stdio.h>


#define sleep() asm("sleep")

#define PIC_CLK 20000000
#include "delay_alternative_enhanced_precision.h"


//=============================================================
__CONFIG(WDTDIS & HS & UNPROTECT & MCLRDIS & BORDIS & PWRTEN);
//=============================================================
// WDTDIS: watch dog disable
// HS: freq. clock 20MHz
// UNPROTECT: data protection off
// MCLRDIS: master clear reset function disabled
// BORDIS: brown out reset disabled
// PWRTEN: power up timer enabled
//=============================================================


#define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit))

static bit GP0 @ PORTBIT(GPIO, 0);
static bit GP1 @ PORTBIT(GPIO, 1);
static bit GP2 @ PORTBIT(GPIO, 2);


void DelayMs(unsigned char cnt);
void Sendlogic1(void);
void Sendlogic0(void);
void VolumeUp(void);
void VolumeDown(void);
void SendRC5(int toggle, int addr, int data);

void main()
{
    int i;

    CMCON  = 0b00000111; // All comparator disabled
    GPPU   = 0;          // enable pull-up
    WPU2   = 0;          // disable pull-up for GP2
    TRISIO = 0b00001011; // GP2 is output
    IOCB0  = 1;          // enable interrupt on change for GP0
    IOCB1  = 1;          // enable interrupt on change for GP1
    IOCB3  = 1;          // enable interrupt on change for GP3
    GPIE   = 1;          // enable the GPIO port change
    GIE    = 0;          // disable all interrupts


    while (1)
    {
        sleep();

        if (GP0 == 0)
        {
            VolumeUp();
        }
        else if (GP1 == 0)
        {
            VolumeDown();
        }
        else
        {
            DelayMs(50);
        }
    }
}

void VolumeUp(void)
{
    Sendlogic1();
    Sendlogic1();

    Sendlogic0();

    Sendlogic1();
    Sendlogic0();
    Sendlogic1();
    Sendlogic0();
    Sendlogic0();

    Sendlogic0();
    Sendlogic1();
    Sendlogic0();
    Sendlogic0();
    Sendlogic0();
    Sendlogic0();

    DelayMs(90);
}

void VolumeDown(void)
{
    Sendlogic1();
    Sendlogic1();

    Sendlogic0();

    Sendlogic1();
    Sendlogic0();
    Sendlogic1();
    Sendlogic0();
    Sendlogic0();

    Sendlogic0();
    Sendlogic1();
    Sendlogic0();
    Sendlogic0();
    Sendlogic0();
    Sendlogic1();

    DelayMs(90);
}

void Sendlogic1(void)
{
    int i;

    DelayUs(255);
    DelayUs(255);
    DelayUs(255);
    DelayUs(139);

    for (i = 0; i < 32; i++)
    {
        GP2 = 1;
        NDelayUs(5);
        GP2 = 0;
        NDelayUs(19);
    }
}

void Sendlogic0(void)
{
    int i;

    for (i = 0; i < 32; i++)
    {
        GP2 = 1;
        NDelayUs(5);
        GP2 = 0;
        NDelayUs(19);
    }

    DelayUs(255);
    DelayUs(255);
    DelayUs(255);
    DelayUs(139);
}

void DelayMs(unsigned char cnt)
{
    unsigned char i;

    do {
        i = 4;

        do {
            DelayUs(250);
        } while(--i);
    } while(--cnt);
}