While watching TV I feel warm, i need to turn on fan but
“I am lazy”, then I think why couldn’t use the same Sony TV remote controller
to control fan and bulb
There are two problems I need to decode the Sony remote
controller and adjust the fan input. I had learned about firing angle control
of TRIAC so that part is not a difficult.
Basically, the zero crossing detector circuit interrupt the
microcontroller after every 10ms,this interrupt command microcontroller to
generate firing pulses, firing pulses are delayed with respect to this
interrupt in the range of 1ms to 9ms, figure(2) below showsout puts for different firing angles. In
order to control both positive and negative cycles the frequency of firing
pulses should be 100 Hz(means should produce two pulses per 50Hz ,one for
positive cycle and another for negative cycle).
Circuit description
The complete circuit can be divided into
SIRC-remote decoding
Zero crossing detection
TRIAC controller
SIRC-remote decoding
I goggled about “remote
controller”I got many types, each
manufacture use different set of protocols for example RC80 is used by
Panasonic RC5 is used by Philips and SIRC is used by Sony fortunately which is
the simplest to decode
In order to eliminate ambient light sources from interfering
with the data stream transmitted modulated light is used, this modulation is
centred around different frequencies depending on manufacture and varies from 32khz
to 56khz in the case of Sony the modulation centre is 40khz which means we need
a IR receiver that can receive the modulation infra red light and convert it to
TTL signal for a PIC. There are a number of IR receiver available, each having
a specific centre frequencies, here i use TSOP 1738 which has a centre
frequency of 38 kHz. The figure below shows the internal block diagram of TSOP
1738
Output-Routis
normally high as you can see from block diagram it has a pull-up resister that
keep logic high when no signal present when infra-red signal is detected output
is low(active low output).
SONY protocol, SIRC (serial infra red control) is an infra
red light remote control communication that uses a form of pulse width
modulation (PWM) to build serial interface. The most common protocol is 12-bit
interface. Figure below shows a series of pulses build up 12-bit packet
The header bit is 2.4ms in length, logic 1 is 1.8ms (1.2ms
high+0.6ms low), logic 0 is 1.2ms (0.6ms high +0.6ms low). The packet consist
of start bit command code(7 bit) which present the actual button pressed on the
remote control, and device code (5 bit) which presenta TV,VCR,CD player and etc. That signal is
inverted to Rout of TSOP 1738 when the data is sent 45ms delay timed before the
next packet is sent and it is repeated for as long as the key is pressed. Table
shown below is some list of key command code for TV (device code=1)
Zero crossing detector
Figure below shows the circuit diagram of the zero crossing detector,
the LED side of opto- coupler is connected to the phase through 200k(.25w),a
10k is connected in between ground and emitter.
The working
of the circuit is simple, whenever a positive cycle comes, the LED emits and
transistor turn on, hence a 5V appears in between emitter and ground, there is
no role for a negative voltage (means diode is in reverse bias) , so the output
will be a 50Hz square wave of approximate turn on 10ms, since I use an opto-
coupler for high volt zero crossing the chance of high volt risk is eliminated.
TRIAC controller
Moc3021 is an opto- coupler TRIAC driver
Since the load is an inductive load (single phase induction
motor) a snubber should be added in order to avoid the risk of dv/dt rise here
i use .1uf and 2k4.
char Current_state = Idle; char got_data = 0; char Command_code, Device_code; void pulse(void){ RC4=1; __delay_us(100); RC4=0; } void interrupt ISR(){ if(INTF){ switch (Current_state){ case Idle: INTEDG = 1; //interrupt on rising edge. counter = 0; Current_state = Start_bit; break; //found the rising edge, check lenght for 2.4ms case Start_bit: //correct signal, move on to next state if(counter == 4) { counter = 0; bit_count = 0; input_data = 0; Current_state = Capture_bit; } else { //fault signal, reset to Idle Current_state = Idle; } break; case Capture_bit: //check plus length for 0 or 1 if(counter == 2){ input_data >>= 1; // add 0 to received data bit_count++; }else { if(counter == 3){ input_data >>= 1; input_data |= 0x8000; //add 1 to received data bit_count++; } else { //error occurs, reset to Idle state INTEDG = 0; //interrupt on falling edge. Current_state = Idle; } } //compleat 12 bit if(bit_count >= 12){ got_data = 1; input_data >>= 4; INTEDG = 0; //interrupt on falling edge. Current_state = Idle; } counter = 0; break; default: Current_state = Idle; } INTF = 0; //clear interrupt flag. }
}
}
//****************************************************************************** // MAIN MAIN MAIN MAIN //****************************************************************************** void main() {
INTE = 1; //enable RB0 interrupt. INTEDG = 0; //interrupt on falling edge.
ADCON1 = 0x0F; //all digital I/O //****************************************************************************** // Timer2 interrupt set up, interrupt every 600us //****************************************************************************** PR2 = 149; //preload timer2 comparator value. T2CON = 1; //timer off, prescaler 1:16 TMR2 = 0; //reset value timer2 TMR2IF = 0; //clear interrupt flag. TMR2IE = 1; //enable timer2 interrupt. TMR2ON = 1; //timer2 is on TMR0IE=1; //enable timer0 interrupt. TMR0IF=0; //clear interrupt flag. T0CS=1; //Transition on RA4/T0CKI pin PSA=0; // Prescaler is assigned to the Timer0 module
T1CKPS1=0; //timer1- 1:2 prescale value T1CKPS0=1;
CCP1IE=1;//ccp1 interrupt is enabled CCP1IF=0;//clear interrupt flag TRISC2=1;//RC2 input TRISC4=0;//RC4 output
CCP1M3=0;//ccp1 interrupt on every rising edge CCP1M2=1; CCP1M1=0; CCP1M0=1; //****************************************************************************** // Global interrupt enable //****************************************************************************** PEIE=1; //peripheral interrupt enable bit GIE = 1; //enable global interrupt