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

Bizarre Behavior with N2 with Events, Interrupts, and other peripherals. Need Help.

interrupts events drivers tlc5940 rotary encoder

  • Please log in to reply
21 replies to this topic

#1 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 14 December 2013 - 04:14 AM

Hi There,

 

I am working through my projects and getting all the individual components working and now I'm bringing them together. When I've pulled it all together, I seem to be getting some bizarre behavior from my interrupts / event handlers.

 

I have a modified driver for a rotary encoder which works as I expected which triggers an event for each rotation "click"(right now its a simple debug.print). Next, I am pulling in some modified drivers for the TLC5940 chips based on Mark's work seen here. Those also work as expected. When I initialize the rotary encoder class and then then TLC5940 class, the interrupts/events seem to go haywire. When I spin the encoder, I get a very inconsistent output. Sometimes a few clicks and no response and then a single click and I get 4 outputs. another click and I get one output but the direction is wrong. Same thing goes for the push button. I get single events without the TLC driver, but erratic events with it initialized. Both rotary encoder and push button are hardware debounced.

 

Seems like there is something conflicting between the two, but I have no overlaps in the pins. What could it be? How should I go about checking this? Is there something fundamental that I'm missing? Or is this some deep issue? I'm a little baffled.

 

Thanks in advance.

I'm using the latest framework build 4.2.2.2



#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 14 December 2013 - 05:14 AM

Hi gismo, Is it possible that you're receiving events quicker than your code can handle them (on the rotary encoder)? If you just turn it one "click", do you consistently get a single event? One thing to be aware of is that NETMF is cooperatively multitasking. That means that threads are by default given up to 20ms of time before the CLR takes execution away and gives it to another thread. So generally you'll want to keep your functions simple and put your threads to sleep when they're not doing anything (rather than spinning in the background). Chris

#3 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 14 December 2013 - 06:50 AM

Hey Chris, Thanks for the quick reply! When the rotary encoder is the only object initialized, interrupts/events are fired almost as fast as I can spin it...Also it does seems to queue the interrupts(I think I read that in another post) That being said, my actual usage will be slower single "clicks" during the actual application. With the TLC object loaded, the erratic behavior occurs on single deliberate "clicks" with sufficient pauses between. At first I thought it was getting stuck in the queue, which still may be the case, but it doesn't add up. For example, I will make two deliberate clicks with no events fired and with the third deliberate click it will fire 4 events in a row. Regarding multitasking, interesting point. I'm not sure my project is there just yet and I'm starting to wrap my head around threading, let alone event handlers and subscribers. In short, my rotary encoder will be used to switch what sensor data is being sent to the TLC5950s.

#4 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 15 December 2013 - 11:37 PM

Update: I have further modified the rotary encoder driver. It uses significantly less code to get the results I'm looking for. I only have ONE interrupt on the rising edge. Now, the results see to be a bit more repeatable. With just the rotary encoder object loaded, I get single repeatable events and correct direction results. One "click" one event. Button works just fine. 

 

When I initialize both the TLC and the Rotary Encoder, I get precisely 32 events fired with each "click" of the encoder and the direction is incorrect. This happens in both directions.

 

The code looks something like this:

 

public static void Main()
        {
            // write your code here
            #region Initialize harware/drivers
         
            RotaryEncoderTEST Rotary = new RotaryEncoderTEST(Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1, Pins.GPIO_PIN_D2);
            Tlc5940 leds = new Tlc5940(32, Pins.GPIO_PIN_D7, PWMChannels.PWM_PIN_D6, Pins.GPIO_PIN_D4, PWMChannels.PWM_PIN_D10);
            //Rnd = new Random(0);
            GaugeSettings Settings = new GaugeSettings(Rotary);
            //Thread.Sleep(Timeout.Infinite);
         
            #endregion
 
            //leds = new Tlc5940(numberOfLEDs: 32);
            while (true)
            {
                Breathe(leds);
                //AllOff(leds);
                Thread.Sleep(500);
            }
}


#5 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 16 December 2013 - 02:39 AM

Another thing I'd like to add...Inside the event handler attached to the interruptport, I put a little bit of code to flash the onboard led and also put in a  debug.print. It seems like the when the TLC is loaded with the Rotary Encoder, the interrupt is constantly triggered. I got an memory error in output window. Is there some circuit or electrical noise from SPI that's causing this? Some bug in my code?

 

Still poking around and will keep making updates.



#6 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 20 December 2013 - 01:38 AM

Still can't figure this out. Anyone with the same hardware/components want to test to see if it's repeatable on their board?

#7 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 20 December 2013 - 02:02 AM

gismo -- one other thing -- what happens if you don't use D0/D1 but use any of pins D2-D13 with your rotary encoder instead?

#8 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 20 December 2013 - 02:27 AM

Same behavior. I even tried A1-A5

#9 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 20 December 2013 - 03:15 AM

Hi gismo, I don't have the other component you're using, but what I'd normally do to debug something like this is to rebuild that other component one piece at a time (comment it all out, and then uncomment one chunk at a time)--until things break. Knowing what was added that broke things can help understand what is broken. Also--if that component has any long loops on a background thread which keep its thread alive constantly, that could affect things. Threads run up to 20ms before the NETMF runtime forces execution to another thread--so a class which doesn't give up MCU cycles could cause you to miss events (or overflow a queue if too many pile up) in another thread. Chris

#10 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 23 December 2013 - 02:24 AM

Thanks Chris. I seemed to have isolated the issue and found fix that works. Maybe you can shed some light on this as well. 

 

I'm using SPI to drive the TLC5940 chips and also using PWM to drive the GSCLK signal for the chips as well(instead of an external clock). I'm using Pin10 on the Netduino 2. When I comment out the PWM constructor for pin 10 the interrupts work as expected with SPI for the encoder! 

 

So...I moved the PWM GSCLK to PIN9 and it now works! Is there something going on with Pin10 while SPI is being used?

 

 

On the side, I was reading a lot of other posts about getting the PWM frequency up in the Mhz range. Has that been implemented yet? 



#11 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 24 December 2013 - 12:35 AM

Hi gismo,

 

When you are using SPI, what pin are you using for SPI_CS?  Pin D10?  That's usually the pin used for SPI_CS--but you can use any unused pin.

 

For PWM MHz+ frequencies...what type of applications are you looking at?  There are some intricacies with PWM clocks across different MCU types which is why there's a lower base clock frequency.  But if we can build a library extension to support additional speeds and could enable additional usage scenarios...we'd like to explore that :)

 

Chris



#12 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 01 January 2014 - 06:26 AM

Hey Chris,

 

Thanks for the info. I'll consider that moving forward. I only have one SPI device currently connected, so I am using ChipSelect_Port: Pins.GPIO_NONE.

 

RE: Higher PWM frequencies. I'm using the PWM to drive the greyscale clock signal on the TLC 5940 chips. I'm doing this to simplify the circuitry and not wanting to create an external clock signal. I'd like to be able to accomplish this with the Netduino. From what I've read, when driving LEDs, they behave much better with a higher frequency. 8Mhz for example. I'm currently using 500kHz(anything higher and debugger locks up) and have some dimming issues. There's a little bit of pulsation and flickering in some scenarios. 

 

I'm really excited to see some extensions to the PWM/clock signal and test it with TLC5940. Where is this on the totem pole of features being worked on?



#13 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 01 January 2014 - 06:49 AM

Hi gismo, Right now we're making some enhancements to SPI idle clock support for an upcoming Netduino 4.3 beta firmware release. If you want to start a conversation about applications using custom PWM speeds and we can get some feedback on how people would use this so we expose it the best way...we can get an official feature task item in our system and work on this for a future firmware update. Chris

#14 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 01 January 2014 - 10:23 PM

Thanks.

 

Back to SPI issue...Was the issue I was having something in the firmware?Bug? Were you able to reproduce the error on your end with CS=GPIO_NONE and then trying to use Pin 10 for something else while having some interrupts fire?



#15 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 02 January 2014 - 08:49 AM

Hi gismo, The issue we're looking at with SPI is the timing of when the SPI chip select pin is asserted and when the SPI clock goes to idle state. In "idle high" mode, this can happen in backwards order and some devices might get 0.5 to 1.0 bits off. If we need to file a bug report on a SPI_CS + timer interrupt pin issue, then we can work through that process here. We'd need a simple repro (<= 10-20 lines of code), expected and actual results, etc. Chris

#16 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 31 March 2014 - 10:23 PM

Hey Chris,

 

I'm still having this problem on 4.3.  Interrupts from the rotary encoder get whacky when I'm using SPI and PWM and can't make any more progress with the components I am trying to use together.

 

Essentially, I have some SPI device doing something then introduce an interrupt and the interrupt response is bouncy and results are unreliable.

 

I'll work on some simplified code and paste it here in the thread.



#17 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 31 March 2014 - 10:42 PM

Here's the code:

 

PWM is the culprit.

 

Note: Changing the PWM frequency significantly lower affect the interrupts, but still does not behave as expected.

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 NetduinoApplication2
{
    public class Program
    {
        static InterruptPort PinA; 
        static InterruptPort PinB;
        static InterruptPort RotaryButton;
        static int InterruptCountA;
        static int InterruptCountB;

        public static void Main()
        {
            InterruptCountA = 0;
            InterruptCountB = 0;

            PinA = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);//Pins are pulled high.
            PinB = new InterruptPort(Pins.GPIO_PIN_D1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);//Interrupt Needed here.

            PinA.OnInterrupt +=PinA_OnInterrupt; 
            PinB.OnInterrupt +=PinB_OnInterrupt; 

            RotaryButton = new InterruptPort(Pins.GPIO_PIN_D2, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
            RotaryButton.OnInterrupt += RotaryButton_OnInterrupt;

            PWM PWMPin;

            //Interrupt Behavior is better where frequency<=200 but still not useable
            PWMPin = new PWM(PWMChannels.PWM_PIN_D9, 400000, .5, false);
            PWMPin.Start();

            while (true)
            {
                //do nothing wait for interrupts
            }

        }

        static void RotaryButton_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            Debug.Print("Button Interrupt");
            InterruptCountB = 0;
            InterruptCountA = 0;
        }

        private static void PinB_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            InterruptCountB++;
            Debug.Print(InterruptCountB.ToString() + " PinB Interrupt");
        }

        static void PinA_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            InterruptCountA++;
            Debug.Print(InterruptCountA.ToString() + " PinA Interrupt");
        }

    }
}



#18 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 12 April 2014 - 04:25 PM

Is anyone else able to reproduce the same thing I am seeing? 

 

Based on the code above, I tried the available PWM Pins individually with the PWMPin statement and here are my results.

 

Fail/Extra Interrupts:

PWMChannels.PWM_PIN_D9

PWMChannels.PWM_PIN_D11

PWMChannels.PWM_PIN_D6

 

Works Properly:

PWMChannels.PWM_PIN_D10

PWMChannels.PWM_PIN_D3

PWMChannels.PWM_PIN_D5

 

Edit:

 

They all fail when a Jumper wire is plugged into the PWM pin. With no jumper wire, they work fine.

 

 

I'm really having trouble pin-pointing this issue(pun intended). Thinking that I have found a work-around solution so I could move forward, I switched back to the code with the SPI and changed the PWM pins to the "working" pwm pins and the issue is still present! :wacko:Here's the weird thing, IF I UNPLUG the two PWM wires connected to the pins while the program is running, the Interrupts begin to work properly. As soon as I plug the PWM wires back in, the interrupts go bonkers. I can reproduce this with a single PWM with the code above. Simply pulling the jumper wire from the Netduino pin header and the interrupts will work fine.

 

I've tried different pins for PWM with the exact same result. Another even more bizarre thing to me is that the PWM jumper wire doesn't even need to be connected to a load(ex: LED) for this to happen.  :o

 

Lastly, the amount of "jitter" in the interrupt behavior seems to be a function of the PWM frequency as well. If you lower the frequency, there's less interrupt jitter.  :blink:



#19 gismo

gismo

    Advanced Member

  • Members
  • PipPipPip
  • 110 posts

Posted 19 April 2014 - 07:55 PM

Update:

 

It turns out, the PWM jumper wire(s) introduce some kind of noise or error in the interrupt jumper lines. When the PWM jumper gets within 1" of the interrupt jumper, the interrupts go haywire. So, I need to create a physical separation to get everything to work correctly. It's isn't ideal.

 

How can this PWM "noise" be eliminated in both the prototyping jumpers and with PCB traces.

 

Thanks.



#20 jrlyman3

jrlyman3

    Advanced Member

  • Members
  • PipPipPip
  • 67 posts
  • LocationNorth St Paul. MN

Posted 21 April 2014 - 02:07 AM

Gismo,

 

We have this sort of problem all the time at work, but we work at much higher speeds.

I don't think that I've ever read about this on a Netduino.  Sounds like you're just going

to need to isolate those two circuits :).  Great work tracking that down.







Also tagged with one or more of these keywords: interrupts, events, drivers, tlc5940, rotary encoder

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.