1

Im writing a Netduino 3 program that will control turn lights and other relays for hayrides. My program was written before I got the device, so Im not sure how well it will work, but Im already having a problem with one of the buttons (hazardButton). When applying 3.3v it doesn't cause the interrupt to trigger. Applying 5v does the same, however when applying GND it triggers the interrupt, but when re-applying GND it doesn't turn off the interrupt.

Here's my code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace Tractor_Mate
{
    public class Program
    {
        static InterruptPort hazardButton = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);

        static OutputPort hazardLights = new OutputPort(Pins.ONBOARD_LED, false);

        static bool hazardsActive = false;

        public static void Main()
        {
            Debug.Print("Initializing Inputs... ");

            hazardButton.OnInterrupt += new NativeEventHandler(hazardButton_OnInterrupt);

            Thread.Sleep(Timeout.Infinite);
        }

        static void hazardButton_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            while (data2 == 0)
            {
                hazardLights.Write(true);
                Thread.Sleep(500);
                hazardLights.Write(false);
                Thread.Sleep(500);

                hazardsActive = true;
            }
            hazardsActive = false;
        }
    }
}

Im getting the problem with the Hazard Lights and haven't tried any of the others yet. Im wiring the buttons up so that when the pin goes HIGH it will trigger, and then when LOW it turns it off.

hightekjonathan
  • 581
  • 1
  • 9
  • 29
  • Your post (source) is quite long, longer than necessary for debugging purposes. Please see [mcve] for more information. Note that you said you're having a problem with one button - but you didn't tell us which one. – KevinDTimm Dec 09 '15 at 20:28
  • @KevinDTimm I shortened the source, and hopefully clarified my question more. – hightekjonathan Dec 09 '15 at 20:32
  • Looks like you are triggering on both edges, for example it'll turn on when you apply GND, then turn off when you remove GND. If you want to have to push the button once to turn on, and once to turn off, you need to invert the logic. Also you should not have infinite loops in event handlers, you need to use a timer to perform the logic. – Ron Beyer Dec 09 '15 at 20:42
  • @RonBeyer which should I be triggering on? And the hazard is a push on push off button just like an actual hazard light signal In a car. Also what would be a more proper way of handling the event? – hightekjonathan Dec 09 '15 at 20:45
  • In the interrupt handler all you should do is if the hazards are on, turn them off. If they are off, turn them on (use a boolean flag for this). Use a timer that runs every 500ms, if the hazards are on and the output is on, turn the output off. If the hazards are on and the output is off, turn the output on. If the hazards are off turn the output off. You could also avoid the timer and just have the logic in the `main` method. – Ron Beyer Dec 09 '15 at 20:47
  • @RonBeyer do you mind writing out something this should look like? Or explain a little more? This is my first attempt with Netduino – hightekjonathan Dec 09 '15 at 21:18
  • I don't have the Netduino SDK installed, but I'll make an attempt at some... – Ron Beyer Dec 09 '15 at 21:26
  • @RonBeyer thank you, anything will be a helpful start. – hightekjonathan Dec 09 '15 at 21:27

1 Answers1

0
public class Program
{
    static InterruptPort hazardButton = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);

    static OutputPort hazardLights = new OutputPort(Pins.ONBOARD_LED, false);

    static volatile bool hazardsActive = false;

    public static void Main()
    {
        Debug.Print("Initializing Inputs... ");

        hazardButton.OnInterrupt += new NativeEventHandler(hazardButton_OnInterrupt);
        bool lightOn = true;

        while (true)
        {
            if (!hazardsActive)
            {
                hazardLights.Write(false);
            }
            else
            {
                hazardLights.Write(lightOn);
                lightOn = !lightOn;
            }
            Thread.Sleep(500);
        }
    }

    static void hazardButton_OnInterrupt(uint data1, uint data2, DateTime time)
    {
        hazardsActive = !hazardsActive;
    }
}

I'm unable to test this since I don't have the Netduino SDK installed (I have a NetDuino, but its been a while since I played with it). The principle is pretty easy:

The interrupt only toggles the hazards being on or off. The variable is marked volatile because it can be set from multiple threads and it needs to be read from the register not a thread cache, so volatile tells the compiler not to optimize it.

The main method has an infinite loop that examines if the hazards are on or off. When the hazards are off (first part of the if), it writes false to the output pin (presumably turning the lights off, unless the pin is inverted).

When the hazards are on (else part), it writes a value to the pin then inverts the value so the next time it turns it off, then on, then off, etc. The last part of the loop just waits 500ms before looping again.

Note

Depending on the "quality" of the contacts in the button you are using, you may need to add debouncing logic to the interrupt handler. "Bouncing" is a phenomenon with switch contacts (or any other mechanical contact) that can cause the contact to open/close many times very quickly when changing state. This is due to the electrical signal bridging the gap as the contacts are very close to each other (think static electricity jumping a gap). A lot of times this is handled on the hardware side by a capacitor, but I'm not sure for the Netduino how it handles it.

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • How would I adjust for the `bouncing`? Would I just check if the interrupt happened within a certain time, and if it has `return` away and ignore it? – hightekjonathan Dec 09 '15 at 23:45
  • That is one way, here is something specific to Netduino from [the Netduino forums](http://forums.netduino.com/index.php?/topic/2431-input-debounce/) for debouncing. – Ron Beyer Dec 10 '15 at 02:43