PWMInput driver

I may be reinventing the wheel, but I wrote this anyway to cut my teeth on FEZ. (FEZ ROCKS, btw, in case anyone wasn’t sure.)

So I’m working on gyro stabilization using a gyro sensor pulled from a Wii Motion. I am taking inputs from an RC receiver processing them (that’s in dev now) and outputting to the servos. I wrote a simple PWM wrapper using interrupts.

I share because I love. (not sure it’s useful to anyone but me but there you go)


   class PWMInput : IDisposable
    {

        private long pulseTicks = 0;
        private long lowHighTicks = 0;
        private InterruptPort ppmInputPort;

        // todo: publish event 

        public PWMInput(Cpu.Pin inputPin)
        {
            ppmInputPort = new InterruptPort(inputPin, false, Port.ResistorMode.Disabled, 
                Port.InterruptMode.InterruptEdgeBoth);

            ppmInputPort.OnInterrupt += new NativeEventHandler(ppmInputPort_OnInterrupt);
        }

        void ppmInputPort_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            if (data2 == 1)     // low -> high
            {
                lowHighTicks = time.Ticks;
            }
            else                // high -> low
            {
                pulseTicks = time.Ticks - lowHighTicks;
            }
        }

        public int Value
        {
            get
            {
                return (int)pulseTicks / 10;
            }
        }



        public void Dispose()
        {
            ppmInputPort.DisableInterrupt();
        }
    }


Thanks for sharing. Stick around and you will see a lot of contributions from everyone in this community. Helping each other is what makes it happen :wink:

i have modified one of the ppm classes i found kicking about on this forum, below is the implementation of the class i`ll post the class next, i was going to do a wiki on this but here it is anyway, hope this helps

IMPLEMENTED CLAS

 using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

using PPM_Application.API;

namespace PPM_Application
{
    public class Program
    {
        static RC_Input Throttle;
        static RC_Input Yaw;
        static RC_Input Pitch;
        static RC_Input Roll;

        public static void Main()
        {
            Throttle = new RC_Input(FEZ_Pin.Interrupt.Di7, false, 10000, 20000, -100, 100);
            Yaw = new RC_Input(FEZ_Pin.Interrupt.Di6, false, 10000, 20000, -100, 100);
            Pitch = new RC_Input(FEZ_Pin.Interrupt.Di5, true, 10000, 20000, -100, 100);
            Roll = new RC_Input(FEZ_Pin.Interrupt.Di4, false, 10000, 20000, -100, 100);

            while (true)
            {
                Debug.Print(" Throttle: " + Throttle.ActualPosition.ToString() + " Yaw: " + Yaw.ActualPosition.ToString() + " Pitch: " + Pitch.ActualPosition.ToString() + " Roll: " + Roll.ActualPosition.ToString());
                Thread.Sleep(2000);
            }
        }
    }
}

 

ACTUAL CLASS


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace PPM_Application.API
{
    class RC_Input
    {
        int internalRead = 0;
        long ticks = 0;

        int InputMin = 0;
        int InputMax = 0;
        int ScaledMin = 0;
        int ScaledMax = 0;
        bool Direction = false;

        int Result = 0;
        
        public RC_Input(FEZ_Pin.Interrupt inputPin, bool InvertPolarity, int Input_Min, int Input_Max, int Scaled_Min, int Scaled_Max)
        {
            InterruptPort inputHandle = new InterruptPort((Cpu.Pin)inputPin, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            inputHandle.OnInterrupt += new NativeEventHandler(inputHandle_OnInterrupt);
            InputMin = Input_Min;
            InputMax = Input_Max;
            ScaledMin = Scaled_Min;
            ScaledMax = Scaled_Max;
            Direction = InvertPolarity;
        }


        void inputHandle_OnInterrupt(uint port, uint state, DateTime time)
        {
            if (state == 0)
            {
                internalRead = (int)(time.Ticks - ticks);
            }
            else
                ticks = time.Ticks;
        }

        public int ActualPosition
        {
            get 
            {
                Result = (internalRead - InputMin) * (ScaledMax - ScaledMin) / (InputMax - InputMin) + ScaledMin;
                if (Direction == false)
                {
                    return Result;
                }
                else
                    return (Result * (-1));
           
            }
        }

    }
}



to explain initilisation

Throttle = new RC_Input(FEZ_Pin.Interrupt.Di7, false, 10000, 20000, -100, 100);

create new instance of class, (interruptpin,invertresults ie stick upsidedown, max in , min in,scaled min output, scaled max output).

which equates to being able to set the positive direction of the rc input and scale it from 1to2millisecond input pulses to -100to100 engineering outputs

I have a similar driver that comes in a suite of RC drivers. See: http://files.chrisseto.com/c5V