I have problem with DL40 module, when I want to use interrupt. I use I/O Module Firmware from taylorza. This is my code:
DLIOModule dlioModule = new DLIOModule(11);
IInterruptPin interruptPin = dlioModule.CreateInterruptPin(3, 1, Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh);
int counter = 0;
interruptPin.Interrupt += (pin, interruptCount) =>
Debug.Print("Interrupt [" + (counter++) + "] - " + interruptCount);
Wires (from the video below) are connected as folows:
Black - ground
Red - 3.3V
Yellow - pin 3.1 - interrupt
White - pin 2.3 - unused
In most cases I get two interrupt events, when I connect wires. Each event changes the state of the led, so two events turn the led on and then off. This behavior can be seen on this video:
Why this happens? Is there something I can change to get only one event? Another strange thing is when I change Interrupt Mode to InterruptEdgeLevelHigh. I get the same two interrupt events, but I would expect many interrupt event til I have the wires connected.
If you are connecting the wires by hand as you are in the video, you are experiencing what is called “bounce” and is normally seen with switches. The same thing happens with your manual contact, you don’t see it, but the computer detects the multiple contacts as you touch the wire.
You’ll need to add a small timer to the handler. You simply ignore any pulses during this time after the first one fires. This is the preferred way to handle bounce of switch inputs with a microcontroller.
You could just try a Thread.Sleep(100) after the LED is switched and see if that cures the issue?
@ Lubos - As @ Dave McLaughlin has said, the issue you are facing is with electrical bounce. I will look at adding a glitch filter to the DL40 IO driver, but in the meantime you should follow Dave’s advice.
Just to double check that it is in fact an issue with “bounce” I repeated your test and got the same results and then swapped the mechanical switching with an optical switch which triggered the signal on the pin when a beam of light was interrupted. Using the optical switch, the interrupts came through perfectly each with an interrupt count of 1.
I used @ Justin’s BeamBreaker as the optical switch
Thank you, Dave. But adding Thred.Sleep() only makes a delay before the second interrupt event. I will try to remember last time the event was rised and during next event compare it to current time and then to decide, whether the interval is greater then X ms. If true, to event will continue, else it will ends.
@ Lubos - If you are building the firmware yourself, I have just uploaded a new version with support for glitch filtering on the interrupt pins. I have only carried out basic testing so you can consider this experimental.
Try using a glitch filter time of 100ms.
Let me know if you want me to send you a build. As soon as I have done more complete testing to ensure that the changes did not negatively affect anything else I will put a new build on codeshare as well.
Wow, taylorza, it was fast!
I don’t know how to make a build of your firmware (is there a guide somewhere?), wo I will have to wait for your build
@ Lubos - I put the latest build on code share so you can grab it from there.
With regard to building the firmware, you basically need Keil uVision (free version) to compile the code, just open the project and hit Compile. The output is the bin file you need. I am currently using uVision V22.214.171.124.
Just a quick update if you are interested in building the Firmware I just upgraded to the latest MDK uVision 126.96.36.199 and it all works perfectly.
Thank you, taylorza, very much! I tried you new firmware, and glitch filter works. Some unwanted interrupts can now be filtered.
But what I can see now, maybe there’s a problem with interrupt mode parameter in CreateInterruptPin() method. It seems, like the interrupt event is raised on both low and high edge, no matter what the value of the parameter is. When I connect the wires for longer time than the event is raised first when I connect the wires and second when I disconnect them. Is that normal?
When the event is raised on connect, the value of the interrupt pin is True (I mean the result of pin.Read() method). On disconnected, the value is False. I can ignore the event, when the pin has False value, but I would expect, that this way the event is raised only when interrupt mode parameter is set to InterruptEdgeBoth.
And what should be the behavior when parametr is set to InterruptEdgeLevelHigh or InterruptEdgeLevelLow? Should the event be raised repeatedly in some short interval till the wires are connected?
Have I understood th interrupt mode parameter properly?
@ Lubos - I expect that you are just seeing the effects of electrical wiring because when I use the optical switch I get the interrupts only on the edges that I expect the interrupt.
The level edge interrupts will raise the interrupt continuously while the interrupt is in the state, it will be raised very quickly so you will get very high interrupt count count values on the interruptCount argument to the handler method.
I have to agree with Taylorza, if you are doing this with a switch or the wire test, then when you release the wire, most of the time it might work but sometimes you will see this multiple contact.
You’ll need to do the timing check on both up and down detection if you intend to use a switch or other mechanical device. If the input is an optical switch then it will be fine.
Yes, I will use it for a mechanical switch, so I hope my filtering will work properly. I want to use it for controlling blinds. It will be the subject of my tests
[quote=“taylorza”]The level edge interrupts will raise the interrupt continuously while the interrupt is in the state, it will be raised very quickly so you will get very high interrupt count count values on the interruptCount argument to the handler method.
Yes, this is behavior, I would expect, but I get only one interrupt on connect (and one on disconnect). Could you please check you get continuous events on level edge?
@ Lubos - The LevelEdge interrupts are getting raised on the DL40 as expected, the problem is that they flood the CPU with so many interrupts that it is not able to do anything else, ie. send a message back to the mainboard to raise the mainboard interrupt.
Why do you want to use the Level Edge interrupts? As an alternative you could set the interrupt to fire when the edge is high and when it is low then you can track the state of the pin that way or do you for some reason require continuous interrupts to fire?
@ taylorza - I think I don’t need to use Level Edge interrupts, I only try to understand it and then to decide which way to go.
Last evening I tried to do very short test - I defined an output pin and connected it with interrupt pin. Then I used common button (as a gadgeteer module) to set output pin to high when button was pressed and to low when button was released. For this test I turned off the glitch filter. Then the interrupt was raised as expected, I saw no bounce. Is this test the same as using optical switch?
I made this test only with InterruptEdgeHigh mode, this evening I want to test other modes. I think I will need InterruptEdgeBoth, because finally I want to have something like SwitchAdapter (over one interrupt pin) with some events to be able to detect (for example):
- short press (to turn lights on/of)
- long press (to move windows blinds until the switch is pressed)
- double press (like mouse double click)
taylorza, I tried to compile your firmware with Keil uVision. Everything seems to work, but I get different binary output then you. I just opened DL40.uvproj and just pressed “Build”. Do I have to change some environment properties for example?