Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.

darko

Member Since 08 Feb 2011
Offline Last Active Mar 22 2011 10:57 AM
-----

Topics I've Started

NEC Protocol IR Decoder

18 February 2011 - 08:35 AM

I purchased an IR kit from DFRobot for a project that I am working on. The remote control sends pulses encoded in the NEC protocol. The following is a class which I wrote which handles decoding the ir command.
The idea of how to implement it was based on how the forum member 'phil' did it in his RC6 Decoder class.
When a code is received, the OnIrCommandReceived event is called and is passed the decoded 32 bit number. Eg. on the remote the 0 button returns 217268479, the 1 returns 284115199.
Note: apple remote controls also use the NEC protocol, so its possible to decode apple remote commands with this class.

public class NecRemoteControlDecoder
{
    private Cpu.Pin _irReceiverPin;
    private long[] pulses;
    private int currentPulseIndex;
    private Timer irPulseTimeOutTimer;
    public delegate void IrCommandReceivedEventHandler(UInt32 irData);
    public event IrCommandReceivedEventHandler OnIrCommandReceived;
    private InterruptPort irReceiverPort;

    public NecRemoteControlDecoder(Cpu.Pin irReceiverPin)
    {
        _irReceiverPin = irReceiverPin;
        pulses = new long[200];
        currentPulseIndex = 0;
        irReceiverPort = new InterruptPort(irReceiverPin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
        irReceiverPort.OnInterrupt += new NativeEventHandler(irReceiverPort_OnInterrupt);
        irPulseTimeOutTimer = new Timer(new TimerCallback(IrPulseTimeOut), null, Timeout.Infinite, Timeout.Infinite);
    }

    private void irReceiverPort_OnInterrupt(uint data1, uint data2, DateTime time)
    {
        if (currentPulseIndex >= 200) currentPulseIndex = 0;
        pulses[currentPulseIndex] = time.Ticks;
        currentPulseIndex++;
        irPulseTimeOutTimer.Change(10, Timeout.Infinite);
    }

    private void ConvertPulsesToMicroseconds(long numberOfPulses)
    {
        var firstMicrosecondsValue = pulses[0] / (TimeSpan.TicksPerMillisecond / 1000);
        var lastMicosecondsValue = firstMicrosecondsValue;
        for (int i = 1; i < numberOfPulses; i++)
        {
            var currentPulseMicrosecondsValue = pulses[i] / (TimeSpan.TicksPerMillisecond / 1000);
            var currentPulseLength = currentPulseMicrosecondsValue - lastMicosecondsValue;
            lastMicosecondsValue = currentPulseMicrosecondsValue;
            pulses[i - 1] = currentPulseLength;
        }
    }

    private void IrPulseTimeOut(object state)
    {
        var numberOfPulses = currentPulseIndex;
        currentPulseIndex = 0;
        irPulseTimeOutTimer.Change(Timeout.Infinite, Timeout.Infinite);

        ConvertPulsesToMicroseconds(numberOfPulses);
        if (numberOfPulses != 68) return;
        if (!IsPulseMatch(pulses[0], 9000) || !IsPulseMatch(pulses[1], 4500)) return;

        UInt32 data = 0;
        for(int i = 65; i >= 3; i--){
            if((i % 2) == 1){
                data = data << 1;
                if (IsPulseMatch(pulses[i], 565))
                    data = data | 1;
            }
            else{
                if(!IsPulseMatch(pulses[i], 560))
                    return;
                }
        }

        if (OnIrCommandReceived != null)
            OnIrCommandReceived(data);
    }

    private bool IsPulseMatch(long actualValue, long expectedValue)
    {
        var marginOfError = 200;
        if ((expectedValue - marginOfError) < actualValue && (expectedValue + marginOfError) > actualValue)
            return true;
        return false;
    }
}

Sample usage:
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace Netduino.NecRemoteControlDecoderApp
{
    public class Program
    {
        public static void Main()
        {
            var necRemoteControlDecoder = new NecRemoteControlDecoder(Pins.GPIO_PIN_D0);
            necRemoteControlDecoder.OnIrCommandReceived += necRemoteControlDecoder_OnIrCommandReceived;

            Thread.Sleep(Timeout.Infinite);
        }

        static void necRemoteControlDecoder_OnIrCommandReceived(UInt32 irData)
        {
            Debug.Print("Ir Command Received: " + irData);
        }
    }
}

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.