Hello NETMF BrainTrust,
I am currently developing a product around the USBizi-144. One block of this product includes a human-actuated linear encoder with a quadrature output and index. The maximum frequency is less than 1kHz when considering both the end-to-end (of the physical strip) average frequency as well as the pulse-to-pulse, “instantaneous” frequency.
With my current test setup I can see nice pulses as expected at the input pin of the USBizi. However, I miss as many as, 2/3rds of the pulses in some cases. Now I am looking for a potential software solution to rectify this problem.
I have read, in some depth, about using the available timers through the Register class. This seems feasible, but I have read in other forum topics that access to the VIC registers is not available using the Register class. Can anyone confirm that this is the case? Is it all of them? I really only need access to one Vectored Interrupt Address to interrupt on the transition of one of the quadrature pulses and check the state of the 90-degree out-of-phase signal as well as the index signal and set the DAC register value.
Would this be a viable solution? Or maybe I am complicating the situation too much? Is there a way to give the interrupt more priority from the managed software? I have also read some mention of some encoder support from GHI, that was about a year ago. Has there been any development in that regard?
If these options are not viable, I will go for the hardware approach using an 8051 to keep track of the encoder position while polling the 8051 over a COM or SPI connection. But, I’m really hoping I can solve this through software instead of having to make additional hardware changes and use additional development tools.
I have also read some about using the RLP approach but after, albeit, a small amount of research on that technique, I feel as though I maybe more comfortable going with the 8051 solution.
For reference, the code below is generally what I have been using for this block. Please forgive extra commented code as I’ve been adding/commenting as I’ve been trying to debug. Many thanks in advance for everyone’s time and consideration.
using System;
using System.IO;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.USBClient;
namespace USBizi_EncoderInterfaceAndMotorControl
{
public class Program
{
static InterruptPort encChI;
static InputPort encChB;
static OutputPort stop, dir;
static bool fwd, rev, init;
static AnalogOut VoltLevel;
static int iVoltLevel;
static int aCount, bCount, iCount;
public static void Main()
{
Debug.EnableGCMessages(false);
InterruptPort encChA = new InterruptPort(USBizi.Pin.IO5, true,
Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh);
encChA.OnInterrupt += new NativeEventHandler(encChA_OnInterrupt);
/*InterruptPort*/ encChI = new InterruptPort(USBizi.Pin.IO1, true,
Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh);
encChI.OnInterrupt += new NativeEventHandler(encChI_OnInterrupt);
encChB = new InputPort(USBizi.Pin.IO11, true, Port.ResistorMode.PullDown);
//encChI = new InputPort(USBizi.Pin.IO1, true, Port.ResistorMode.PullDown);
fwd = false;
rev = false;
init = false;
stop = new OutputPort(USBizi.Pin.IO13, false);
dir = new OutputPort(USBizi.Pin.IO17, false);
VoltLevel = new AnalogOut(AnalogOut.Pin.Aout0);
VoltLevel.SetLinearScale(0, 3300);
iVoltLevel = 1450;
VoltLevel.Set(iVoltLevel);
aCount = 0;
bCount = 0;
iCount = 0;
Thread.Sleep(Timeout.Infinite);
} // public static void Main()
static void encChA_OnInterrupt(uint port, uint state, DateTime time)
{
bool stChB = encChB.Read();
Debug.Print(stChB.ToString() + "-" + aCount);
aCount++;
if (encChI.Read() == true)
{
Debug.Print("----->Zero");
}
//Debug.Print(aCount.ToString());
//if (encChI.Read() == true)
//{
// aCount = 0;
// Debug.Print("Zero");
// init = true;
// fwd = false;
// rev = false;
// VoltLevel.Set(1500);
//} // if (encChI.Read() == true)
/*else*/ if (stChB /*encChB.Read()*/ == true)
{
//Debug.Print("Reverse");
if (!fwd)
{
rev = true;
dir.Write(false);
//increase voltage
iVoltLevel = iVoltLevel + 6;
if (iVoltLevel > 2500) { iVoltLevel = 2500; }
VoltLevel.Set(iVoltLevel);
//if count gets to a certain level, delay then stop, or stop if endpoint
//switches are triggered, to avoid motor burnout
}
else
{
//decrease voltage
iVoltLevel = iVoltLevel - 6;
if (iVoltLevel < 1450) { iVoltLevel = 1450; }
VoltLevel.Set(iVoltLevel);
}
} // if (encChB.Read() == true)
else if (stChB /*encChB.Read()*/ == false)
{
//Debug.Print("Forward");
if (!rev)
{
fwd = true;
dir.Write(true);
//increase voltage
iVoltLevel = iVoltLevel + 6;
if (iVoltLevel > 2500) { iVoltLevel = 2500; }
VoltLevel.Set(iVoltLevel);
//if count gets to a certain level, delay then stop, or stop if endpoint
//switches are triggered, to avoid motor burnout
}
else
{
//decrease voltage
iVoltLevel = iVoltLevel - 6;
if (iVoltLevel < 1450) { iVoltLevel = 1450; }
VoltLevel.Set(iVoltLevel);
}
} // if (encChB.Read() == false)
} // static void encChA_OnInterrupt(uint port, uint state, DateTime time)
static void encChI_OnInterrupt(uint port, uint state, DateTime time)
{
Debug.Print("Zero-" + iCount.ToString() + "-FWD:" + fwd.ToString() + "-REV:" + rev.ToString());
init = true;
fwd = false;
rev = false;
VoltLevel.Set(1450);
iCount++;
} // static void encChI_OnInterrupt(uint port, uint state, DateTime time)
} // public class Program
} // namespace USBizi_MotorControlTest