Results 1 to 6 of 6

Thread: Homemade Infra-red remote control

  1. #1

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Homemade Infra-red remote control

    Homemade Infra-red remote control [VB 2005]

    If you are building a Home-Theater-PC (HTPC) one of the things you need to install is a remote control and its driver. Even without Media Center this is a simple thing to do.

    A hardware circuit that plugs into an RS232 port is actually pretty simple and easy to build. Here is a circuit that works just fine.

    I don't think that the Vishay TSOP1738 is available any longer, but any of Vishay's 38kHz IR Sensor Modules for remote Control Systems will work. I have used the TSOP31238 with no problem. You can get a few of these for free by requesting a sample from Vishay. http://www.vishay.com/product?docid=...uery=tsop31238 . LCD TVs output a lot of IR when they warm up, so you might want to instead use one of their modules designed for noisy environments. (i.e. TSOP31438)

    RS232 ports have become less common on modern computers being replace with USB ports. If you don't have a serial port available and don't want to add one, you can add a RS232 to USB converter to your system.

    There is a fantastic open source project for Linux called LIRC that handles the software interface to the device (http://lirc.org). Version 0.6.5 was ported to windows in 2003 (http://winlirc.sourceforge.net) but there is a serious flaw with this software. WinLIRC relies on the serial port interrupt for timing the pulses to decode the signal. The problem with this is that the serial port interrupt is a lower priority interrupt than the video interrupt so that when your system is performing some serious video task, such as video playback, the serial port interrupt will be delayed to an extent that makes the IR remote unusable. The solution to this problem is to perform the IR pulse detection and decoding via a polling technique instead. WinLIRC can still be used to generate the remote configuration file (obviously not while viewing motion video).

    Below is a replacement IR Remote daemon that works reliably even when video playback is going on.

    Most remote control units modulate the IR signal at 38kHz and follow the same basic protocol. When a key is pressed on the remote control, the unit produces a train of pulses who's widths identify what key was pressed. After demodulation, the signal consists of several square pulses of different widths separated by spaces of about 500 microseconds (us). The pulse train starts with a wide header pulse of about 5 milliseconds (ms). Next comes a series of 32 pulses. Each pulse represent a one or zero depending on its width. A one is represented by a pulse width of about 1600us and a zero is about 500us wide. These 32 digits can be combined to for a unique 32-bit unsigned integer that identifies the key pressed. Actually the high word identifies the remote control used and the low word identifies the key pressed. Finally a very wide tail pulse; about 40ms; is sent.

    Here is an overview of the software does:
    • We can use the serial port interrupt to detect the first pulse edge since an inaccuracy in the width of the first pulse (header) does not affect the results. The com-port PinChanged event signals us that an IR signal has been detected. This could be the beginning of a valid pulse train.
    • When the first pulse edge has been detected, start polling the com-port in a background thread with higher than normal priority to watch for future edges.
    • When a pulse comes in, measure its width with the high performance counter.
    • Start a one shot pulse-train timer to signal us when the pulsetrain should be finished.
    • When the one-shot timer expires, we should have collected 32 pulses. Convert the 32 valid pulses to ones and zeros (depending on the pulse width) and convert that into a 32-bit integer which tells us which key on the remote controller has been pressed.
    • Start a repeat timer to prevent repeat keys from being reported for the next 500ms.
    • Look up the name of the key and remote that correspond to the 32-bit integer above.
    • Send this data over TCP/IP to the clients.
    Attached Files Attached Files
    Last edited by moeur; Jun 13th, 2009 at 05:28 PM. Reason: The attached file now is complete and will run

  2. #2

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Homemade Infra-red remote control

    To detect the first pulse edge, monitor the com port's Pin Changed event.
    Code:
        Private Sub CommPort_PinChanged(ByVal sender As Object, ByVal e As SerialPinChangedEventArgs) Handles ComPort.PinChanged
            'we only use the com port interrupt to detect the first pulse edge.  
            'This is allowed because the accuracy of the width of the first (header) 
            'pulse is not important.
            If ThreadData.isBusy Then Return 'ignore interrupts while we are in the process of measuring a pulse train
            If e.EventType = SerialPinChange.CDChanged Then 'only interested in the DCD line
                If ComPort.CDHolding = False Then ThreadData.AR.Set() 'begin polling
            End If
        End Sub
    The detection of the first pulse then signals us to start the polling process. We use the High performance Timer to measure pulse widths and start a one-shot timer to signal us to stop polling.
    Code:
        Private Sub doPolling(ByVal oData As Object)
            'we cannot rely on interrupts to detect pulse edges since the com port interrupt
            'has too low a priority and will give inaccurate results if many interrupts of higher
            'priorities are occuring.  This situation arrises during video playback.
            Static LastState As Boolean
            'data is sent along the DCD line (pin 1); this line remains high while idle
            Dim ThreadData As clsThreadData = DirectCast(oData, clsThreadData)
            With ThreadData
                Do
                    'wait here for next pulse train
                    .AR.WaitOne()
                    .isBusy = True
                    .isFirstPulse = True
                    Do
                        LastState = .cPort.CDHolding
                        ThreadData.TimerValue = PerformanceTimer.CurrentCounts()
                        getData(ThreadData)
                        Do
                            'wait here until next change on DCD line
                            'or until pulse train is finished
                            If Not .isBusy Then Exit Do
                        Loop While (.cPort.CDHolding = LastState)
    
                    Loop While .isBusy
                Loop
            End With
        End Sub
    Here is the ThreadData class
    Code:
        Private Class clsThreadData
            Public Sub New(ByVal Port As SerialPort)
                HiData.Initialize()
                LoData.Initialize()
                cPort = Port
            End Sub
            Public cPort As SerialPort
            Public isBusy As Boolean = False
            Public AR As New Threading.AutoResetEvent(False)
            Public isFirstPulse As Boolean = True
            Public HiData As PerformanceTimer.Data
            Public LoData As PerformanceTimer.Data
            Public TimerValue As Long
        End Class
    When the one-shot timer expires, we should have collected 32 pulse widths.
    Code:
        Private Sub OneshotTimer_Tick(ByVal stateinfo As Object)
            'this is the end of a pulse train
            'no more data should be coming in now
            Dim ThreadData As clsThreadData = DirectCast(stateinfo, clsThreadData)
            ThreadData.isBusy = False
            mDataCount = Index 'number of pulses found, should be 32 + header + tail = 34
            'unless it is a repeat key then count should be 2
            Index = 0
            If (mDataCount = 34) Or (mDataCount = 2) Then
                For i As Integer = 0 To mDataCount - 1
                    getDigit(Pulses(i))
                Next
            Else
                isValid = False
            End If
            'here is the data we just gathered, convert pulses to an integer value
            Dim data As DWORD = getKeyCode(Pulses, mDataCount)
            'now that we have a value, see if it corresponds to a key in our list
            If isValid Then
                If Codes.ContainsKey(data.Value) Then
                    RepeatFlag = False
                    'start the repeat timer to ignore repet keypresses for the next 500ms (delay1)
                    'subsequent repeats can happen again within 100ms (delay2)
                    RepeatTimer.Change(delay1, delay2)
                    RaiseEventNewKey(Remotes(data.HiWord), Codes(data.Value), data.ToString)
                    LastKeyCode = data
                Else 'unknown key code
                    LastKeyCode.clear()
                    RepeatFlag = False
                    RaiseEventUnknownKey(data.ToString())
                End If
                isValid = False
            ElseIf (data.Repeats > 0) And (mDataCount = 2) Then
                If LastKeyCode.Value = 0 Then Return
                If data.Repeats > 1 Then
                    LastKeyCode.clear()
                    Return
                End If
                RepeatCount += data.Repeats
                If RepeatFlag Then
                    RepeatFlag = False
                    RaiseEventRepeatKey(Remotes(LastKeyCode.HiWord), Codes(LastKeyCode.Value), RepeatCount, data.ToString)
                End If
            Else
                'reject noise
                RepeatCount = 0
                LastKeyCode.clear()
            End If
    
        End Sub
    As with LIRC, the daemon or server program transmits decoded IR remote data on a TCP/IP port to any number of client programs that need the data. Attached is a demo program that shows how to develop server and client programs. I've put together some classes that make the process of development easier. Here is a list of these classes.

    clsLIRCserver - this handles all the com port polling and signal decoding
    clsTCPserver - this class handles the server side of the TCP details
    clsIniFile - A class to simplify the reading of Windows ini files. The server uses this class to read te key code mapping information.
    clsLIRCclient - this class handles the TCP/IP connection between the client and the server program and raises events when remote control data arrives.
    PerformanceTimer - a class that handles the timing of pulse width measurements.

  3. #3
    New Member
    Join Date
    Jul 2009
    Posts
    3

    Thumbs up Re: Homemade Infra-red remote control

    Hi, I buid the Infra-red circuit some days ago and i find your code , that this awesome!!. But this seems has a problem, not even detect a code keys. sometimes arrive another code with the same button. Where is the problem?. WinLirc work fine.


  4. #4

    Thread Starter
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: Homemade Infra-red remote control

    If Winlirc works fine then I suggest you use it. I couldn't get WinLIRC to work while any video was playing.

    I suppose the problem you are seeing could be coming from one of several sources:
    1. you have a slow cpu that cannot keep up. Try running a compiled version of the code.
    2. try changing the adjustable parameters in the code.

  5. #5
    New Member
    Join Date
    Jul 2009
    Posts
    3

    Re: Homemade Infra-red remote control

    Quote Originally Posted by moeur View Post
    If Winlirc works fine then I suggest you use it. I couldn't get WinLIRC to work while any video was playing.

    I suppose the problem you are seeing could be coming from one of several sources:
    1. you have a slow cpu that cannot keep up. Try running a compiled version of the code.
    2. try changing the adjustable parameters in the code.
    Hi, WinLIRC work find but... And I have no problem playing video (I use crytal player to watch movies). I have a core 2 duo at 2.1, with 1gb of ram. wich part of code sould be modifiy?
    Attached Images Attached Images  

  6. #6
    New Member
    Join Date
    Feb 2012
    Posts
    6

    Re: Homemade Infra-red remote control

    Hi I built this circuit not long ago and was able to use WinLIRC and another program I know it definately works.

    What I am trying to do now is to make my own program that reads in the commands from the remote into my program and then depending on what the command is I get it execute a program with the shell command. I know DCD is not used to read in data but can it be used?

    And if so any sample code or ideas would be very useful!

    Thanks in advance

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width