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.
Photo

This looks like a bug in InterruptPort


  • Please log in to reply
21 replies to this topic

#1 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 26 June 2011 - 10:01 PM

I am almost certain that I'm seeing a bug in InterruptPort on my Mini. This is the setup:

1. I have a pressure switch that is either open or closed (short circuit). When there is light weight on it, it is closed. When there is heavy weight on it, it is open.

2. One side of the switch is connected to ground, the other to pin 5 of the Mini.

3. The port is configured as follows:

weightSensor = new InterruptPort(Pins.GPIO_PIN_5, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
weightSensor.OnInterrupt += OnSenseWeight;

private void OnSenseWeight(uint pin, uint state, DateTime time)
{
    if (state == 0)
        Debug.Print("Weight Off");
    else
        Debug.Print("Weight On");
}

4. When the weight is removed from the sensor, it bounces 2 or 3 times before coming to a stop. This is just how it works and I can't change it.

Here's the problem: About 25% of the time, the final state of the pin gets out of sync with the actual state of the switch. I would get a series of interrupts, but the last debug output would then show "Weight On", when in fact the weight has been removed. I can see that the switch is closed, the voltage is 0V, and an oscilloscope shows the signal is clearly going to 0V. There is no other noise on the signal - it is very clean, other for the bouncing of the switch.

I tried to pass in "true" for "glitchFilter" but it doesn't make any difference.

To me this clearly looks like a bug since I'm just not getting the final event when the voltage on the pin goes to 0V. The only way I can currently think to work around this is to create a polling loop that continuously checks the state of this pin.

I'm currently using build 4.1.2821.0.

Any ideas what is going on here?

#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 26 June 2011 - 10:21 PM

Hi BitFlipper, If you take a jumper wire and connect it to GND and then unplug it, repeatedly, do you see the same behavior? [Using the same Mini pin 5--just to isolate any issues there first.] Also, the latest firmware for the Mini is either 4.1.1 beta or 4.1.0.6. The ".2821" version # is an internal version for the Micro Framework itself. Try reading the "Device Capabilities" in MFDeploy to see if you have the latest Netduino Mini firmware. Chris

#3 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 26 June 2011 - 10:59 PM

Chris,

I was working on this software for about 2 weeks now and during that time I have always used a simple toggle switch to simulate the weight sensor. In all that time I have never seen it get out of sync. But today was the 1st time I connected it to the actual weight sensor, and the 1st time I experienced it getting out of sync. To confirm this, I reconnected the simple switch and could not get it to go out of sync. It looks like the bouncing of the switch is confusing the InterruptPort code.

As far as the firmware version, this is everything I see from MFDeploy:

Pinging... TinyCLR
HalSystemInfo.halVersion:               4.1.2821.0
HalSystemInfo.halVendorInfo:            Netduino Mini by Secret Labs LLC
HalSystemInfo.oemCode:                  34
HalSystemInfo.modelCode:                177
HalSystemInfo.skuCode:                  4098
HalSystemInfo.moduleSerialNumber:       00000000000000000000000000000000
HalSystemInfo.systemSerialNumber:       0000000000000000
ClrInfo.clrVersion:                     4.1.2821.0
ClrInfo.clrVendorInfo:                  Netduino Mini by Secret Labs LLC
ClrInfo.targetFrameworkVersion:         4.1.2821.0
SolutionReleaseInfo.solutionVersion:    4.1.0.5
SolutionReleaseInfo.solutionVendorInfo: Netduino Mini by Secret Labs LLC
SoftwareVersion.BuildDate:              Nov  7 2010
SoftwareVersion.CompilerVersion:        400771
FloatingPoint:                          True
SourceLevelDebugging:                   True
ThreadCreateEx:                         True
LCD.Width:                              0
LCD.Height:                             0
LCD.BitsPerPixel:                       0
AppDomains:                             True
ExceptionFilters:                       True
IncrementalDeployment:                  True
SoftReboot:                             True
Profiling:                              False
ProfilingAllocations:                   False
ProfilingCalls:                         False
IsUnknown:                              False


#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 26 June 2011 - 11:01 PM

SolutionReleaseInfo.solutionVersion:    4.1.0.5
You might want to update to 4.1.0.6 or 4.1.1 beta 1.

That said, is it possible that the sensor is not driving the voltage to the input pin all the way to 0V? Are you measuring pin 5 and one of the Mini GND pins directly to get the 0V reading on your multimeter?

Chris

#5 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 26 June 2011 - 11:15 PM

SolutionReleaseInfo.solutionVersion:    4.1.0.5
You might want to update to 4.1.0.6 or 4.1.1 beta 1.

That said, is it possible that the sensor is not driving the voltage to the input pin all the way to 0V? Are you measuring pin 5 and one of the Mini GND pins directly to get the 0V reading on your multimeter?

Chris


Was anything related to this fixed after version 4.1.0.5? I'll upgrade but if nothing in this area was fixed I wonder if it is even worth upgrading since everything else works as expected.

The voltage is less than 4mV when the sensor is closed, and this is when measuring close to the Mini's ground and pin 5. An oscilloscope shows that there is no noise on this pin, and the transitions are very clean.

Here is more proof that something has to be wrong with the InterruptPort code: I re-wrote my code to use InputPort instead of InterruptPort. I now use a polling loop to query the state of the pin every 100ms. To mask the bounce, I only toggle the bool value representing the pin's state if it was in either the low or high state for 5 consecutive InputPort.Read() calls. Using this code, I get 100% accurate results, and I am unable to get it out of sync.

The above proves that: Reading the pin's state using InputPort gives accurate results (and proves all input voltages are correct), yet InterruptPort can get into a situation where it never sends the final event to indicate the final state of the pin in the presence of "bounce".

#6 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 26 June 2011 - 11:35 PM

BitFlipper, Could you please copy and paste this code to a new project and test it there? And then if it fails, post the code? I believe that the bugs fixed in 4.1.0.6 were SPI- and UART-related. Chris

#7 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 27 June 2011 - 12:44 AM

OK, I got some simple code that reproduces the problem. I could not initially reproduce the problem, but while trying to figure out what was different between the simplified code and my main project, I realized that there is a small amount of work being performed during the InterruptPort.OnInterrupt callback. As soon as I added a tiny amount of work to this call, the problem reproduced. When the "DoWork()" line is commented out, the problem does not reproduce.

Prerequisites:

1. You need a noisy switch between pin 5 and ground.
2. Pins 13 and 14 are driving two LEDs.

When the code below is run, the two LEDs should stay in sync (within a few hundred ms). But as the switch is operated, they might get out of sync (and stay permanently out of sync). Commenting out the "DoWork()" line will result in the two LEDs staying in sync.

Obviously the two LEDs should never be out of sync, and it points to a bug in the InterruptPort implementation.

EDIT: BTW, I noticed that there are ~80 interrupts for one switch open/close transition.

EDIT EDIT: My guess is that what is happening is that if a pin transition occurs while a previous pin event is still being processed, that next pin transition is lost.

public class Program
    {
        private static object m_lock = new object();
        private static OutputPort m_outPort1;
        private static OutputPort m_outPort2;
        private static InterruptPort m_inPort;
        
        public static void Main()
        {
            m_outPort1 = new OutputPort(Pins.GPIO_PIN_13, false);
            m_outPort2 = new OutputPort(Pins.GPIO_PIN_14, false);
            
            m_inPort = new InterruptPort(Pins.GPIO_PIN_5, false, 
                Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);

            m_inPort.OnInterrupt += OnInPortInterrupt;

            while (true)
            {
                lock (m_lock)
                {
                    m_outPort2.Write(m_inPort.Read());
                }

                Thread.Sleep(100);
            }
        }

        static void OnInPortInterrupt(uint pin, uint state, DateTime time)
        {
            lock (m_lock)
            {
                m_outPort1.Write(state != 0);
                DoWork();
            }
        }

        static int DoWork()
        {
            var result = 0;

            for (var idx = 0; idx < 100; idx++)
            {
                result += idx;
            }

            return result;
        }
    }


#8 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 27 June 2011 - 06:41 PM

So Chris do you have any idea what could be causing this behavior? I can use my polling mechanism in the meantime but now I worry that I cannot trust InterruptPort where I use it in other places to give me the accurate state of a pin.

#9 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 27 June 2011 - 06:55 PM

Hi BitFlipper,

So Chris do you have any idea what could be causing this behavior? I can use my polling mechanism in the meantime but now I worry that I cannot trust InterruptPort where I use it in other places to give me the accurate state of a pin.

My thoughts...

1. It appears that this may be a glitch in the interrupt handling and/or queueing code in the core .NET Micro Framework. Can you please post a work item (bug report) at netmf.codeplex.com -- so the NETMF team can look at fixing it across the board for the .NET MF 4.2 release?

2. In the meantime, one possible workaround is to create a background thread which waits for the interrupt...and then makes sure that the interrupt is manually called the final time. You'd basically set an AutoReset event in your interrupt handler (which the background thread would be waiting for--and then the background thread would check for pin changes for up to ##ms). The background thread would then fire off the interrupt again when the final interrupt needed to be called, before going back to Waiting on the AutoResetEvent to be set.

Chris

#10 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 27 June 2011 - 07:04 PM

OK thanks Chris, I will post a bug report on Codeplex. I was actually thinking of implementing my own class that wraps InputPort and uses a polling timer to query pin states and fires events when it detects pin state changes. This will work as long as one doesn't need the exact DateTime when a pin state changed.

#11 Dan Morphis

Dan Morphis

    Advanced Member

  • Members
  • PipPipPip
  • 188 posts

Posted 27 June 2011 - 10:14 PM

4. When the weight is removed from the sensor, it bounces 2 or 3 times before coming to a stop. This is just how it works and I can't change it.



What about adding a debounce circuit? That should clear up your issues.


-dan

#12 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 28 June 2011 - 03:36 PM

What about adding a debounce circuit? That should clear up your issues.

-dan


It is actually easy to add debouncing to software (which is what I'm doing right now), so I would say the extra effort to add external circuitry is not required. Especially since I already ordered the PCBs.

I think the bigger issue is that there is a bug somewhere and that right now we cannot rely 100% on what InterruptPort tells us the state of a pin is.

BTW I plan to post a bug report on Codeplex tomorrow when I'll have little bit more time available.

#13 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 28 June 2011 - 04:36 PM

BTW I plan to post a bug report on Codeplex tomorrow when I'll have little bit more time available.

Thank you!

Chris

#14 Arron Chapman

Arron Chapman

    Advanced Member

  • Members
  • PipPipPip
  • 289 posts
  • LocationOregon, USA

Posted 29 June 2011 - 01:48 AM

Maybe I missed something, or maybe I'm just daft, but couldn't you read the state of the port in your interrupt handler?
static void OnInPortInterrupt(uint pin, uint state, DateTime time)
{
      bool saneState = interupPort.Read();
      lock (m_lock)
      {
           m_outPort1.Write(state != 0);
           DoWork();
      }
}

When you talk EE use small words, I'm just a Software Developer :)
My Blog/Site and Everything Else

If my post helped you please consider pressing the "Like This" button in the bottom right-hand corner.

 

Oh my. So many things, so little money!!

 


#15 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 29 June 2011 - 06:15 AM

Maybe I missed something, or maybe I'm just daft, but couldn't you read the state of the port in your interrupt handler?

static void OnInPortInterrupt(uint pin, uint state, DateTime time)
{
      bool saneState = interupPort.Read();
      lock (m_lock)
      {
           m_outPort1.Write(state != 0);
           DoWork();
      }
}


Well the problem in that case is that you would never get the final interrupt and hence you won't know that the port needs to be read. This is why you need an external way of triggering a read on the port, like a loop or a periodic timer.

#16 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 29 June 2011 - 10:45 PM

I posted a bug report here.

#17 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 29 June 2011 - 10:49 PM

I posted a bug report here.

Thanks!

#18 <Jeremy>

<Jeremy>

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationNorthern Ireland

Posted 18 July 2012 - 10:56 PM

Hi BitFlipper Could you confirm if the fix in .NET MF4.2 for issue 1073 (http://netmf.codeple...m/workitem/1073) actually solved the problem for you? I'm coming across a similar InterruptPort issue myself and just wanted to check if your issue was resolved by the change. Thanks! Jeremy

#19 BitFlipper

BitFlipper

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts

Posted 19 July 2012 - 06:30 AM

Hi BitFlipper

Could you confirm if the fix in .NET MF4.2 for issue 1073 (http://netmf.codeple...m/workitem/1073) actually solved the problem for you?

I'm coming across a similar InterruptPort issue myself and just wanted to check if your issue was resolved by the change.

Thanks!
Jeremy


Jeremy, to be honest, I don't believe I ever tried the version where this bug was marked as fixed. The polling loop ended up working well enough for my purposes so I never tried the later version.

#20 <Jeremy>

<Jeremy>

    Advanced Member

  • Members
  • PipPipPip
  • 31 posts
  • LocationNorthern Ireland

Posted 19 July 2012 - 09:08 AM

Hi BitFlipper - thanks for replying, that's useful information anyway. My issue sounds possibly related to yours. I've a sensor sending 43 bits of information, and the Netduino only picks up around 30-40 - I've found that it "loses" interrupts in the middle of the signal. I'll keep looking for a solution :) Thanks again, Jeremy




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

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.