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.

gismo

Member Since 19 Oct 2013
Offline Last Active Aug 11 2016 12:20 AM
-----

#63964 I2C Bus Problem - Debugging

Posted by gismo on 24 August 2015 - 03:35 PM

Shouldn't you be connecting to the SDA (or SD) and SCL (or SC) lines (top left of the Netduino in your diagram)?

 

Regards,

Mark

 ^^ what he said. Your diagram shows an arduino SDA/SCL hookup.




#57376 Many Output toghete

Posted by gismo on 06 April 2014 - 04:19 PM

Hey Alex, 

 

I'm not sure you can do that at the same time with the standard firmware and netmf sdk...You would need to directly program the the chip register(s) with low-level instructions with native code and bypass the CLR to accomplish that.

 

BUT, you could accomplish the same "code" and simply write a method like this to simplify your code:

public void Pin1AndPin2(Cpu.Pin pin1, Cpu.Pin pin2, bool onOrOff)
{
pin1.Write(onOrOff);
pin2.Write(onOrOff);
}

and in your program code you would call:

Pin1andPin2(pin1_object, pin2_object,true);



#54254 Interrupts, Queue, Events, and Event Subscriber Class with Rotary Encoder

Posted by gismo on 23 November 2013 - 06:51 PM

Hey Guys,

 

I have got a couple of questions regarding interrupts and events and then subscribing to events/interrupts created by the encoder class/driver. With specific regards to a 3 pin (A C B) rotary encoder with gray code output:

 

Specifically:

https://www.sparkfun...s/TW-700198.pdf
 

Some background, I found a rotary encoder driver on the forums and the output was not consistent due to what I believed was bounce in the encoder..so I've found a sufficient debounce circuit:

Posted Image

Now, I've wired up the encoder with a hardware debounce and I'm getting consistent and correct output from the rotation. Yay! But still a problem...the interrupt fires twice with each detented rotation/click. Because there are two 4 pulses per click. this makes sense to me...The driver works perfectly if I rotate the encoder between half way between the detents..But this is obviously not how I want to use the device. With each detent click, I only need one event fired. In efforts to optimize the code and not get a double event, is there a way to clear the interrupt queue or disable and re-enable the interrupt? Is that the right way to handle it?

 

That all being said, I'm really trying to wrap my head around the driver code and subscribers to the events created by the driver. I understand a basic interrupt and the handler, but I need to use the encoder for more several functions..this is where Subscriber come into play. I've spent hours googling, youtubing, MSDNing(the least useful resource IMO) researching this. I'm no c#.net expert and need an explanation on how this works, in understandable terms. Otherwise seems like black magic when stepping through the code..

 

I'll write out some abbreviated code:

namespace RotaryEncoderDriver
{
    public class RotaryEncoder
    {
        private static InterruptPort PinA = null;
        private static InterruptPort PinB = null;
     
        public event NativeEventHandler RotationEventHandler=null;
     
        public static byte CLOCKWISE = 0;
        public static byte COUNTERCLOCKWISE = 1;
 
        public struct ResultSet
        {
            public bool PinA;
            public bool PinB;
        }
 
        private bool InProcess;
        private ResultSet[] results = new ResultSet[2];
 
        /// <summary>
        /// This is the main constructor
        /// </summary>
        /// <param name="pinA"></param>
        /// <param name="pinB"></param>
        public RotaryEncoder(Cpu.Pin pinA, Cpu.Pin pinB)
        {
            InProcess = false;
            PinA = new InterruptPort(pinA, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            PinB = new InterruptPort(pinB, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
 
         
            NativeEventHandler RotationEvent = (data1, data2, time) =>
            {
                NewNotaryResult(PinA.Read(), PinB.Read(), ref InProcess, ref results,RotationEventHandler);
            };//this line is black magic to me. How/Why does this work?
 
            PinA.OnInterrupt += RotationEvent; // attached event to interrupt. 
            PinB.OnInterrupt += RotationEvent;
 
 
        }
 
        /// <summary>
        /// Creates the event for subscribers
        /// </summary>
        /// <param name="type">CLOCKWISE or COUNTERCLOCKWISE uint value</param>
        private static void OnRaiseRotationEvent(uint type, NativeEventHandler handler)
        {
            // Event will be null if there are no subscribers
            if (handler != null)
            {
                handler(0, type, DateTime.Now);
            }
        } 
     
        /// <summary>
        /// Used to record a rotary result.  If rotary result is initial, we enter an "in process" state.
        /// If we are already in process, then the results will be processed and an event raised from another method.
        /// </summary>
        /// <param name="pinA">Tested result of Pin A on Encoder</param>
        /// <param name="pinB">Tested result of Pin B on Encoder</param>
        private static void NewNotaryResult(bool pinA, bool pinB, ref bool InProcess, ref ResultSet[] results, NativeEventHandler RotationEventHandler)
        {
            // Set the appropriate result items
            byte bytebool;
         
            if (InProcess)
            {
                bytebool=1;
            }
            else
            {
                bytebool=0;
            }
            results[bytebool].PinA = pinA;
            results[bytebool].PinB = pinB;
 
            // If already in process we need to process the rotation
            if (InProcess)
            {
                ProcessRotation(results, RotationEventHandler);
//This seems like a good place to clear the interrupts
 
 
            }
            // Toggle the InProcess
            InProcess = !InProcess;
        }
 
        /// <summary>
        /// Processes a rotation event and raises an event to public interface with result
        /// </summary>
        /// <param name="results"></param>
        private static void ProcessRotation(ResultSet[] results, NativeEventHandler RotationEventHandler)
        {
            // false result, cancel
            if (results[0].PinA == results[1].PinA && results[0].PinB == results[1].PinB)
                return;
 
            NativeEventHandler handler = RotationEventHandler;
            // if pin A high
            if (results[0].PinA == true)
            {
                //   if pin B went down then counter-clockwise
                if (results[1].PinB == false)
                    OnRaiseRotationEvent(RotaryEncoder.COUNTERCLOCKWISE, handler);
                //   else clockwise
                else
                    OnRaiseRotationEvent(RotaryEncoder.CLOCKWISE, handler);
            }
            // else pin A low
            else
            {
                //   if pin B went up then counter-clockwise
                if (results[1].PinB == true)
                    OnRaiseRotationEvent(RotaryEncoder.COUNTERCLOCKWISE, handler);
                //   else clockwise
                else
                    OnRaiseRotationEvent(RotaryEncoder.CLOCKWISE, handler);
            }
        }
 
 
    }
}

Main/Subscriber

public class Program    {        public static void Main()        {            RotaryEncoder RE = new RotaryEncoder(Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1);            Subscriber sb = new Subscriber(RE);//instantiate the subscriber                        Thread.Sleep(Timeout.Infinite);        }    }        public class Subscriber        {            public Subscriber(RotaryEncoder rotary)            {                rotary.RotationEventHandler += HandleRotation;            }            public static void HandleRotation(uint data1, uint data2, DateTime time)            {                Debug.Print("EVENT @ "+ time.TimeOfDay);                Debug.Print("Handle Rotation " + data2);            }        }    }

I hope this is clear and thanks in advance for reading through all this.




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.