Infrared

There are 5 modes
3 edge modes (high, low and both)…these are supported
2 level modes (high and low) …these are currently not supported…and in 99% of applications are not needed

Ha, i was bit confused by the term edge because all 5 modes have that in there name :wink:

I liked the level modes because of the possiblity to trigger on event, do your stuff and reset (clearevent) and wait for the next event.

Here is a little progression report :wink:

My project is going smootly,
I now use the next Port.InterruptMode.InterruptEdgeBoth together with a timer to us as a sort of watchdog and that seems to work also.

The Domino is now outputting the received IR data to the C# IDE console and looks like this

37: ####_______#######_______####____#######_______#######_______####____####___####___####____####___####___####___####___####___####___####___####___#######_______####
3157 6479 6764 6160 3465 3076 6623 6225 6777 6153 3466 3085 3376 2998 3470 2995 3465 3079 3388 2995 3464 2998 3470 2993 3468 2993 3472 2994 3466 3033 3435 2990 3469 2996 6705 6221 3469 
35: ####_______#######_______####___#######_______#######_______####___####___####___####___####___#######_______####___####___####___####___####___#######_______####
3159 6475 6771 6158 3466 2999 6701 6227 6777 6146 3466 2998 3466 2996 3466 2995 3498 2968 3466 2994 6706 6223 3467 2996 3471 2992 3530 2934 3471 2991 3463 3005 6697 6233 3450 

As you can see the values vary very much. And i do not mean the 6000+ and 3000+ but between the 3000+ values like 3466 2998 3466 2996 3466 2995 my idea is that those need to be the same.
I take it that this is coming from the architecture of netMF. What kind of margin i need to calculate on the results?

Here is a snapshot of the code:

    public class MultiReceiver : TVRemoteReceiver
    {
        IRType[] defIRProtocols = new IRType[] {
          new IRType("RC5" ,1, true, true, 14, 889,889, 889,889, 889,889, 0,0,0, 0,0,0),
          new IRType("RC5x",0, true, true, 14, 889,889, 889,889, 889,889, 0,0,0, 0,0,0),
          new IRType("RC6" ,1, true, true, 14, 2667,889, 444,444, 444,444, 0,0,0, 0,0,0),
        };

        InterruptPort _irdaPort;
        ArrayList _pulses;
        Timer _timer;
        bool timerRunning = false;
        long lasttime;
        const int DATA_LENGTH = 255;
        const int MAX_DELAY = 15;

        /// 
        /// Creates new Multiple Remote Receiver instance
        /// 
        /// Infrared demodulator pin
        public MultiReceiver(Cpu.Pin receiverPin)
        {
            this.ReceiverPin = receiverPin;

            this._pulses = new ArrayList();
            _timer = new Timer(finishRead, null, Timeout.Infinite, Timeout.Infinite);
            _irdaPort = new InterruptPort(receiverPin, false,
                                          Port.ResistorMode.PullUp,
                                          Port.InterruptMode.InterruptEdgeBoth);
            // add an interrupt handler to the pin
            _irdaPort.OnInterrupt += new NativeEventHandler(IntButton_OnInterrupt);
            lasttime = 0;
        }

        void finishRead(object o)
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);
            if (!timerRunning)
            {
                Debug.Print("Time not running.");
                return;
            }
            _irdaPort.DisableInterrupt();
           
           /* Calculate returned remote codes */

            // OnDataReceived(command, address);
            _pulses.Clear();
            _irdaPort.EnableInterrupt();
            timerRunning = false;

        }
        
        void IntButton_OnInterrupt(uint port, uint state, DateTime time)
        {
            if (!timerRunning)
            {
                lasttime = time.Ticks;
                timerRunning = true;
                _timer.Change(MAX_DELAY, Timeout.Infinite);
            }
            else
            {
                _pulses.Add((time.Ticks - lasttime));
                lasttime = time.Ticks;
            }
        }

        /// 
        /// Dispose object
        /// 
        public override void Dispose()
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);
            timerRunning = false;
            _timer.Dispose();
            _irdaPort.Dispose();
        }
    }

Please when someone see anything i can do better on an other way please let me know, this is just to learn how i need to use C# and netMF.

greetings
Niels

You will never see the exact numbers you are expecting but very close. Your window should be large enough to cover any offsets but not too large to take errors as values.

I would use 10% as an easy starting point. Look how this code uses 0.9 and 1.1 to add a window http://www.tinyclr.com/downloads/Component/FEZ_Components_EasyRemote.cs

Thanks Champ,
I will this idea in my work :smiley:

Hello,

I have question about the code you shown me and the own i use.

             new InterruptPort(receiverPin, false,
                                          Port.ResistorMode.PullUp,
                                          Port.InterruptMode.InterruptEdgeBoth);
             new InterruptPort(receiverPin, false,
                                          Port.ResistorMode.Disabled,
                                          Port.InterruptMode.InterruptEdgeBoth);

What is difference in use when i use Port.ResistorMode.Disabled like in your code instead of the own i use now Port.ResistorMode.PullUp?

When you specify you want a pullup resister, the IO pin will be pulled up to (I think) 3.3V. When it is disabled, the pin will not be pulled up or down, it will be floating.

I think this is explained in the book.

Not exactly, There is some mansion about the pull-up and pull-down resistor, but not about the disabled option. And yeah i did know what it is for.

Maybe i explain my question wrong. I like to know why you did choice for disabled instead of pull-down. Do you not get more noise, when it is disabled?

Or is the noise i see now is just because i use the pull-down option?

thanks anyway for your big involvement with this forum.

greetings
Niels

You need to design your circuit to be pulled high or low by default. It isn’t really an issue of noise.

Here is a good example here that explains how a pull down resister works: Arduino Tutorial - Lesson 5

If you use the disabled option , you have to use an external pull up-/down resistor

There were no interference between the internal and external resistor

A pin that is not connected to anything is “floating” and this is very bad. This is why we need the pull up/down resistors.

When the pin is connected to your IR receiver then the pin is not floating and so using a pull up/down resistor is pointless. You can use it but it will not benefit you by any means.

thanks Gus, Cypher and Chris,

You helped a lot again.

No problem :slight_smile:

An other very odd, problem i see in the result is the the state flag of the first bit normally is 1 as it should be but after GC it is often set to 0 and all next IR codes the start always with 0.
Any idea what can be happened?

        void IntButton_OnInterrupt(uint port, uint state, DateTime time)
        {
            if (!timerRunning)
            {
                lasttime = time.Ticks;
                timerRunning = true;
                _pulses.Clear();
                _pulses.Add(state);
                _timer.Change(MAX_DELAY, Timeout.Infinite);
                
            }
            else
            {
                _pulses.Add(time.Ticks - lasttime);
                lasttime = time.Ticks;
            }
        }

Also i like to know something about the Timer object; When i do _timer.Change(MAX_DELAY, Timeout.Infinite); will the timer then start to count at 0 again?
I have tried to find some info about it on the web but did not see any good info yet.

When this thread began, I was hoping it was going to get into the sending IR side vs the receiving IR side. I have managed to get the receiving part down, and have recorded and decoded the pulse widths for the picture-in-picture button on my Vizio LCD TV.

My plan is to couple this with a sound level meter placed near my doorbell, and a surveillance camera always-on hooked up to an input port on the tv, so when the doorbell rings, the IR LED will simulate the picture-in-picture press to show my camera, then a timer will wait 30 seconds and send the signal twice more to cycle it off, cool huh? Anyway, I am having a hell of a time trying to send the IR signals with the IR LED component I purchased from robotshop.ca (http://www.robotshop.com/inex-infrared-led-board-2.html). At first the issue was trying to delay for a period of microseconds, when I was using an OutputPort. I had located and attempted to use :

private void DelayMicroSec(int microSeconds)
{
    DateTime startTime = DateTime.Now;    
    int stopTicks = microSeconds * 10;
    TimeSpan divTime = DateTime.Now - startTime;
    while (divTime.Ticks < stopTicks) { divTime = DateTime.Now - startTime; }
}

and when I recorded what I was sending, I was getting horrible transmissions that weren’t even half the pulses I was sending. I then found the OutputCompare class, and it looked like it could do what i needed, so I put together this class:


using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.FEZ;
using System.Collections;

namespace VizioIR
{
    public class VizioIR : IDisposable
    {
        OutputCompare c;
        private const int MAX_BUFFER_SIZE = 50;
        uint[] pulses;
        int curPulse = 0;

        public enum SignalType
        {
            Header,
            Zero,
            One,
            Gap,
            Repeat,
            Trail
        }

        #region Pulse Widths for Vizio LCD TV
        const int ZeroOn = 600;
        const int ZeroOff = 500;
        const int OneOn = 600;
        const int OneOff = 1600;
        const int HeaderOn = 9000;
        const int HeaderOff = 4500;
        const int GapOn = 40880;
        const int GapOff = 600;
        const int RepeatOn = 9100;
        const int RepeatOff = 2180;

        const int TrailOn = 600;
        const int TrailOff = 600;//doesnt matter.        #endregion

        #endregion
        public VizioIR(FEZ_Pin.Digital pin, bool initState)
        {
            c = new OutputCompare((Cpu.Pin)pin, initState, MAX_BUFFER_SIZE);
            pulses = new uint[72];
        }

        public void ClearPulses()
        {
            pulses = new uint[72];
            curPulse =0;
        }

        public void AddPulse(SignalType t)
        {
            switch (t)
            {
                case SignalType.Gap:
                    pulses[curPulse] = GapOn;
                    curPulse++;
                    pulses[curPulse] = GapOff;
                    curPulse++;
                    break;
                case SignalType.Header:
                    pulses[curPulse] = HeaderOn;
                    curPulse++;
                    pulses[curPulse] = HeaderOff;
                    curPulse++;
                    break;
                case SignalType.One:
                    pulses[curPulse] = OneOn;
                    curPulse++;
                    pulses[curPulse] = OneOff;
                    curPulse++;
                    break;
                case SignalType.Repeat:
                    pulses[curPulse] = RepeatOn;
                    curPulse++;
                    pulses[curPulse] = RepeatOff;
                    curPulse++;
                    break;
                case SignalType.Trail:
                    pulses[curPulse] = TrailOn;
                    curPulse++;
                    pulses[curPulse] = TrailOff;
                    curPulse++;
                    break;
                case SignalType.Zero:
                    pulses[curPulse] = ZeroOn;
                    curPulse++;
                    pulses[curPulse] = ZeroOff;
                    curPulse++;

                    break;
                default:
                    break;
            }
        }

        public void SendPulse()
        {
            c.Set(false, pulses, 0, pulses.Length, false);
        }



        #region IDisposable Members

        public void Dispose()
        {
            c.Set(false);
            c.Dispose();
        }

        #endregion
    }
} 

and when I try to send my 36 pulses, that fill the 72 uint[] on/off values, I get this exception:


 #### Exception System.Exception - 0xf6000000 (3) ####
    #### [b]GHIElectronics.NETMF.Hardware.OutputCompare::Set [/b][IP: 0000] ####
    #### VizioIR.VizioIR::SendPulse [IP: 0015] ####
    #### IRReceiveTest.Program::b_ButtonPressEvent [IP: 0013] ####
    #### GHIElectronics.NETMF.FEZ.FEZ_Components+Button+ButtonPressEventHandler::Invoke [IP: 59034] ####
    #### GHIElectronics.NETMF.FEZ.FEZ_Components+Button::OnInterrupt [IP: 0013] ####
A first chance exception of type 'System.Exception' occurred in GHIElectronics.NETMF.Hardware.dll
An unhandled exception of type 'System.Exception' occurred in GHIElectronics.NETMF.Hardware.dll 

So basically, I am having quite a bit of trouble sending my IR pulses, when I found that OutputCompare class in the documentation I was pretty sure that was exactly what I needed. Now I have the feeling I need another piece of hardware… Does anyone have any working code samples for SENDING infrared pulses in microsecond durations?

Thanks!

When debugging, check the size of pulses.Length. Is it under 50?

I upped the max_buffer_size to 72, exactly what my array size is, and I fired off the pulse… and my receiver only received 19 pulses back, with sizes inconsistent to what I was sending. i tried changing the default state from false to true, same deal. I got no response from my tv so it’s not a receive issue. Could it be a problem trying to send IR pulses, and having an interrupt fire events for receiving at the same time?

Dear All,

I bought my first mini robot kits just to play around with. The kit comes with 2 reflective sensors, not enough for what i am trying to do. I know you will want to say…buy more :-)… hehehe. I know, I know… I already spent more than $250 so far already for robot…anyway, if anyone have these sensors and no longer needed them for any reasons, please kindly throw them my way. I will be happy to cover the shipping cost or something.

Very appreciate!
-Hai

Hai,

You might get more responses by making a new thread. This one is for discussing the sending of data over IR.