|
|
View previous topic :: View next topic |
Author |
Message |
Markdem
Joined: 24 Jun 2005 Posts: 206
|
Universal remote control |
Posted: Sun Jul 09, 2006 2:19 am |
|
|
Hello all, sorry if this is a bit off topic. I am tiring to make an IR to RS232 converter. Basically I want to send commands from a universal remote control (Logitech harmony 880) and then send commands to a light controller (Clipsal C-BUS). My devise will not send IR commands. The universal remote is a learning type, but what do I need to do to teach it? Do I need to first make a device that can first program the remote, and then make the receiver, or is there another way, programming the remote from my PC�s IRDA port maybe? Also, what IR decoders should I use? I have found that a TSOP1738 is common, is it going to do what I need??
Thanks, Mark |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Jul 09, 2006 3:45 am |
|
|
I just read my question back to myself, and it made no sence . i guess the question i should be asking is how can i program my universal remote without making somthing that can send it the commands in the first place? can somthing like this be done, or am i dreaming??
Thanks, Mark |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Sun Jul 09, 2006 4:57 am |
|
|
A universal remote attempts to repeat the infrared pattern it has detected. There are different encoding frequencies but if you make one with a 38KHz encoding frequency then most remotes should be able to learn the sequence. You could make it easier on yourself by basing you device on a common protocol. Even better when you emulate a specific remote.
Take an exisiting remote (Sony are common) and have your device emulate it. This has the advantage that you can preprogram the auto learning remote to replicate a Sony (for example) in this case it does not really need to learn plus it gives you a wide range of options in terms of what remote to use.
There are standard IR receivers that provide an output pulse stream corresponding to the encoded signal. You need to get one of these that matches the encoding frequency you are using. For example a 36KHz IR receiver works poorly with a 38KHz encoded signal. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
deltatech
Joined: 22 Apr 2006 Posts: 87
|
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sun Jul 09, 2006 10:49 am |
|
|
To avoid re inventing the wheel use as was recommened an existing protocol and frequency. IR is very noisy mostly it's flourescent lights that make the mischief. The protocols that have been perfected by Sony and other TV manufacturers will reject this noise by either pulse width ( o and 1 are identified by the length of the pulse) encoding or space width encoding ( same as pulse only using space)or shift encoding ( 1 is long pulse short space 0 is short pulse long space) and further protect with redundancy ... sending the signal twice sending the signal followed by its inverse etc.
Here is some code that is the inverse of what you want...You wanted your PIC to train your universal remote but you are dead at the outset since you have no Tx capability. The code below is the PIC learning or at least identifying the signal from various remotes. It will not work on any remote only the ones I had laying around the house but the code might be of use to you.
Code: |
//// v1 modified for time period T
//// AGC pulse is identified as 16T
//// AGC pause is identified as 8T
//// Pulse is T and space is minimum of 2T for space encoded
//// working with toshiba and magnavox and leadtek 6/19/04
/// format is byte0 is address and byte1 its complement
// byte 2 is the key scan code byte3 its complement
#include <18F452>
#fuses HS,noWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP
#device *=16 CCSICD=TRUE
#use delay(clock=20000000)
#use rs232 (debugger)
#define IR input(PIN_A0)
#define LED PIN_D0 //// flash led on valid code received
/////////////////////////////////////////////////////////////////////////////
//// notes ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//// a long 9ms pulse is sent for AGC followed by a 4 ms space
/// the bits are code as follows
//// space coded .... zero and one is encoded by the length of the space
/// pulse=600us and fixed space varies 0= 600us 1=1500us
//// pulse coded .... zero and one is encoded by the length of the pulse
/// shift coded .... zero =short pulse long space one =long pulse short space
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///// constants to filter glitches as from flourescent lights
//////////////////////////////////////////////////////////////////////////////
///// toshiba agc_time 30000 bit_time 1000 space coded
///// leadtek agc_time 30000 bit_time 1000 space coded
//#define AGC_time 1000 /// 30k*.2=6 ms AGC is typically 9ms
#define MAX_DURATION 5 //// 10ms
#define TOSHIBA 1
#define MAGNAVOX 1
#define LEADTEK 1
#define ECHSTAR 2
///// globals //////////////////////
int16 AGC_pulse ; /// 30k*.2=6 ms AGC is typically 9ms
int16 AGC_space ;
int16 BIT_time ;
int16 T;
int8 timed_out,duration,index,str_index,space_terminated,maker;
int16 pulse_width,space_width,pulse_adj;
struct {
int8 byte0;
int8 byte1;
int8 byte2;
int8 byte3;
int8 byte4;
int8 byte5;
} code;
char binstr[50];
/////////////////////////////////////////
///////// isr /////////////////////////
/////////////////////////////////////////
#int_RTCC
isr_timer0()
{
/// the timer overflows every 256 counts
/// a count occurs every 4 * 4 =16 cycles at 20MHZ or 8us
/// so we get here every 256*8 =2048 us approx
/// longest pulse or space is approx 10ms ...max duration of 5
duration++;
if (duration>=MAX_DURATION)
{
duration=0;
timed_out=true;
}
}
///////////////////////////////////////
int16 pulse()
{
int16 time;
/// measure time the carrier is high
/// carrier high means the demodulator is low
/// a glitch can not interrupt a carrier
/// set up the interrupt timeout clock timer0
/// if timeout is exceeded interrupt sets timed_out to true
timed_out=false;
duration=0;
set_timer0(0);
loop:
time=0;
while((IR==1)&& (timed_out==false)); //wait for low
if (timed_out==true) return(0xFFFF); /// timed out
set_timer1(0); /// start timing
while(IR==0); /// hold till low ends ...low will always end since the carrier pulse is always a burst
time=get_timer1();
//// ignore a short carrier pulse as a glitch
if (time<BIT_time) goto loop; //// 200 us = .2ms or shorter are ignored
return (time);
}
////////////////////////////////////////////////
int16 space()
{
int16 time;
/// measure time the carrier is absent
/// carrier absent means the demodulator is high
/// the space is vunerable to a noise glitch
while(IR==0); //wait for high it will always go high since carrier is aburst
/// set up the interrupt timeout clock timer0
/// if timeout is exceeded interrupt sets timed_out to true
timed_out=false;
duration=0;
set_timer0(0);
time=0;
set_timer1(0); /// start timing
loop:
while((IR==1) && (timed_out==false)); /// hold till high ends
if(timed_out==true) return(0xFFFF);
time+=get_timer1();
/// there could be a short duration noise glitch or a truly valid pulse beginning
/// so we encroach a short time on a valid pulse when testing to see if it was a glitch
set_timer1(0); /// start timing possible glitch .. a very short duration low ( carrier burst)
while((IR==0) && (get_timer1()<BIT_time>2*pulse) {
shift_right(&code,6,1); /// goes in lsb first
binstr[str_index]='1';
}
else {
shift_right(&code,6,0);
binstr[str_index]='0';
}
str_index--;
}
if(mode==3)
{
// pulse encoded
if (pulse>2*space) {
shift_right(&code,6,1); /// goes in lsb first
binstr[str_index]='1';
}
else {
shift_right(&code,6,0);
binstr[str_index]='0';
}
str_index--;
}
}
////////////////////////////////////////////////////////////
int8 validate(int8 mode)
{
if ((mode==1) || (mode==2))
{
// toshiba or magnavox byte3 is complement of byte 2 and byte 1 complement of byte 0
if (code.byte3 != (~code.byte2)) return false;
if (code.byte1 != (~code.byte0)) return false;
}
return(true);
}
///////////////////////////////////////////////////
init_IR_control( int8 mode)
{
if ( mode==1) {
//// typical 9ms agc pulse 4ms AGC space
/// 600us pulse eithet 600us space or 1500 us space
AGC_pulse=30000 ; /// 30k*.2=6 ms AGC is typically 9ms
AGC_space=12000 ;
BIT_time=100;
space_terminated=true;
return;
}
if (mode==2)
{
/// leadtek
AGC_PULSE=3000;
AGC_space=30000;
BIT_time=100;
space_terminated=true;
return;
}
return;
}
main() {
int8 j,success;
int16 pulse_table[49],space_table[49];
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); /// start timer over flows 4*4*256 cycles =800us
setup_timer_1(T1_INTERNAL|T1_div_by_1); // Start timer 1 tick every 4 cycles or .2us at 20mhz
/// all tv remotes send out pulses of the carrier 38kz of various durations
/// pulses are separated by spaces (no carrier) of varying duration
/// the code will measure the pulse and space intervals in a train of pulses
/// the ir is demodulated so as to have a logic high when no carrier is detected
/// a timeout is used to end a pulse train
/// a timing constant T is assigned to each make of remote
maker=TOSHIBA;
T=2500;
printf("\n\r start maker=%d",maker);
enable_interrupts(INT_timer0);
enable_interrupts(global);
///// initialize AGC pulse and space
//init_IR_control(TOSHIBA);
init_IR_control(maker);
start:
for(j=0;j<50;j++){ pulse_table[j]=0;space_table[j]=0;}
code.byte0=0;
code.byte1=0;
code.byte2=0;
code.byte3=0;
code.byte4=0;
code.byte5=0;
for(j=0;j<48;j++)binstr[j]='X';
binstr[49]=0;
////////////// transmission is assumed to be lsb first
///////////// the structure code is written and the string binstr as bits are translated
str_index=48; /// string is filled lsb first so lasb goes to pos 48
///////// a change to pulse from the idle (space) state starts the analysis
pulse_width=pulse(); /// get the beginning agc pulse if any
if ((pulse_width==0xFFFF) || (pulse_width<T)) goto start; /// we timed out instead of starting
/// it's not that the pulse was this long
/// just that we timed_out waiting for a pulse
/// or pulse is to short to be valid
/// we have either an AGC pulse or a bit
re_start:
str_index=48; /// string is filled lsb first so lsb goes to pos 48
/// str is msb.................lsb when printed
/// lsb was received first and msb last
/// code.byte0 is 7..lsb
/// code.byte1 is 15..8 etc until transmission ends
/// transmission is assumed to end after 48 bits or earlier
pulse_table[0]=pulse_width; /// slot 0 is for the agc
space_width=space();
if ((space_width==0xFFFF) || (space_width<T)) goto start; /// to long AGC space
/// it's not that the space was this long
/// its just that we are detecting an idle condition
/// or space is too short
space_table[0]=space_width; /// slot 0 is for the AGC
/// we we get here we have either an AGC pulse space pair
/// or a bit pulse space pair
index=1;
next_bit:
/// pick up the data payload usually 48 bits
pulse_width=pulse_adj+pulse(); /// in testing for glitches we can encroach on a little into a valid pulse
//// payload can be pulse terminated
if (pulse_width<T>4*T)) goto exit;
pulse_table[index]=pulse_width; // time of high part of bit
space_width=space();
if(space_width<T>4*T)) goto exit;
space_table[index]=space_width;
translate(maker,pulse_width,space_width); //// space or pulse encoded translation
if (index<49) {index++; goto next_bit ;}
exit:
if(index<16 ) goto start;
for (j=index;j<49;j++) shift_right(&code,6,0);//// need to fill in the remaining bits
success=validate(maker);
if (success==true) {
/// flash led
output_high(LED);
delay_ms(100);
output_low(LED);
delay_ms(100);
}
binstr[49]=0;
for(j=index+1;j<49;j++){ pulse_table[j]=0xFFFF;space_table[j]=0xFFFF;}
// for (j=0;j<index;j++) printf("\n\r %02u %05lu %05lu ",j,pulse_table[j]/5,space_table[j]/5);
printf("\n\r %2x:%2x:%2x:%2x:%2x:%2x \n\r",
code.byte5,code.byte4,code.byte3,code.byte2,code.byte1,code.byte0);
if (success==true ) printf("\n\r %s OK bits %d",binstr,index-1);
else printf("\n\r %s ERR bits %d",binstr,index-1);
goto start;
while(1);
}
|
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
Posted: Sun Jul 09, 2006 12:00 pm |
|
|
As was suggested, take existing code (there are at least two examples in the Code Library that I know of), and use that to create an IR receiver. Short of having a decent digital oscilloscope, there is no way to determine what code, or the code format, a remote control is sending. Once you know the code and format, then you can write a program to send these codes to the learning remote.
Some notes:
- There something like 6 major code formats, and almost all A/V equipment use one of these formats. Then there are a LOT of lesser-used codes, usually employed by such well known brands as Loewe Opta, Cmwell, and Alba.
- The major codes usually follow a signaling scheme like this:
1. Lead in sequence - a long burst of IR at the carrier frequency (usually 38 - 40 kHz), followed by a shorter period of silence. May or may not be present (most Sony codes do not have a lead in sequence).
2. First data payload. Can be 8 - 32 bits long.
3. Lead out/pause. All formats employ a short pause (short IR burst followed by a relatively long pause - not as long as the lead-in, if present).
4. Repeat of data OR transmission of new data.
5. Pause. --> Usually the end of the transmission for most formats.
6. Repeat of data OR new data. Sony typically at a minimum will transmit 15 bits three times. In all cases I've examined, it's the same data.
As someone has already said, the actual 1 & 0 format varies as well. Here are the common ones:
- Short burst (constant), short pause = one state, short burst (constant), long pause = other state. I'm not actually going to say one is a 0 and the other is a 1 because I don't remember which is which (and this prevents someone from correcting me )
- Short burst, short pause (constant), and long burst, short pause (constant).
There are many variations on this theme.
I developed a product that features an IR passthru feature - the operator points an ordinary IR remote at a touch screen, and is able to control the A/V equipment which is locked away in a vault. The commands are received, decoded, compressed and sent (via CAN bus) to the remote receiving unit where they are reconstructed and retransmitted. It took a couple of weeks for me to perfect the code, but it works perfectly now with a barely perceptable pause between the press of the button and the reaction of the equipment. The most difficult part was decoding all the different signaling formats (actually sorting through the received code to determine if a lead in sequence is present, what is the 0 & 1 format, actually decoding the data that was sent, etc). I managed to come up with an algorithm that recognizes almost all the codes in a universal remote - save for the famous brand names I mentioned earlier.
Before you ask, no I can't share it. But a tip when it comes to transmitting the sequence (actually flashing the IR LED): use the PWM module to create a (approx) 40 kHz 50% duty cycle waveform - this drives the LED (or a transistor, which in turn drives the LED). Then write your code to switch the TRIS so that the PWM module gets connected to the LED to create the bursts, and disconnected to create the silences. Much better than using delays and output_high() and output_low() commands. |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Sun Jul 09, 2006 3:55 pm |
|
|
Thank you for all your help guys.
I did not think of using a remote from another device that i dont have. The universal remote can be programed with predefinded sets of codes from the internet. So, what i am thinking i will do is take a device that i dont own eg. sony tv, and send the commands to my reciver that i will make. Then iwill make my reciver change the command from the remote, eg channel up, into a command i need, eg lights on.
Will this work??
Thanks again, Mark |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Sun Jul 09, 2006 7:05 pm |
|
|
Yes it will work, I used this approach myself. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|