Second, does anyone have a basic RLP driver that can do SPI Read/Writes for the G30? I read another thread on here about RLP SPI and will do initialization outside of the RLP. However, the old thread stores registers in RLP, it does not execute the read/writes.
I need to continuously do SPI read/writes in order to track a rotary encoder. NETMF is too slow to handle this without error. Writing SPI transactions in C is a nightmare for me as it is a read only language for me (barely that).
There is no RLP on G30, IIRC. What you need is probably a custom driver. Typically, in cases like yours we build a special firmware for the customer or add the feature. This goes under our consulting services. Please contact us directly if this is something that interest your company.
This blog was a lifesaver when I needed to implement SPI transactions in C
The above effort was not for the motor side of my application but just some RGB that I wanted to be able to set without having to tie up PWM pins on the G30. I have another more expensive CoPro doing some fast operations built in C++ on analog encoder output for motor stuff… it is actually responsible for motor position, safety, etc… so it runs at 20 kHz. G30 can’t loop that quickly… at least I can’t make it loop that fast because my program loses stability without Thread.Sleep(1) at the end of the loop.
Which brings me to number 2: What do you need to do with the encoder output? What is the actual rate of SPI transactions that you need? Are you sure it is possible to communicate over SPI at that rate?
I am simply monitoring the position of the shaft (which is hand turned) and displaying the resultant position on an i2C display. It works great unless you spin it hard, then there is a chance that it will miss detecting the revolution “marker.” Even 1 kHz should be enough for this application…I have a Thread.Sleep(1) if no change in encoder position is detected, and if one is, a few ms to WriteNibble to my parallel display. Very little code in the program so it runs fine but I need to fool proof it. Was hoping to speed some things up with RLP as I have read great things but if not…I will have to go RS485 interface route and use their upgraded encoder that handles multi turn tracking so the G30 doesn’t have to calculate it.
If it takes a few ms to write to the display than you will not reach 1kHz. If this is your requirement you are only allowed 1ms per transaction while actively reading. And I do think in this case it will be hard to poll for this with a G30.
You can put an analyzer on the buses to get an idea of the timing that is occurring. And I would highly recommend taking some time to devise a method of determining the exact frequency that you need. It may save you some time and effort in the long run.
Is it necessary to print every single reading to the display?
Maybe you can save some time there by waiting sometimes to print a value if they are going to be rapidly changing anyway.
@jwizard93 So have you tried RLP on a G30 or not? I just need to get it as fast as possible, shouldn’t have to even be as high as 1 kHz. There isn’t an exact frequency requirement - the faster I can do SPI reads the higher the max velocity of the shaft can be without throwing off the position tracking. The frequency only needs to increase slightly.
Yes it is necessary to print the value every time it changes…it is the same concept as scrolling through the measurement readings on calipers…the values display with each change so that you always know the measurement as its changing. Was a stated design requirement.
No I have not tried RLP on the G30. If I were going to try this I would have a lot to learn about NETMF. I would not have a clue on how to start modifying the code to implement RLP.
And I’d be damn sure it was going to fix the problem… with target numbers recorded and reasons why it would fix the problem before asking for cash to get GHI to implement it.
I am interested in this problem though. Do you have datasheets for the valve/encoder? Things of that nature
It says the SPI bus uses absolute position… can you read fast enough to assume that the shaft was rotated in the direction of least travel between reads?
Is that the issue you are facing? IE if I’m at position zero and at the next read I’m at position 4000… you cant assume I traveled -96 counts because I could have easily also traveled 4000 counts in the other direction?
Are you reading over SPI all the time or just whenever a pulse is sensed on another pin outside of the SPI bus?
I can read fast enough 99% of the time…the 1% comes in when I fling the shaft as fast as I can (trying to account for customers being customers). I read the position then immediately read the position again, depending on which position is bigger (and by how much) I know the direction / if a revolution has been completed. I am only using SPI as the index channel physical position that triggers a pulse cannot be changed.
display.Clear();
AMT.SetAMT203ZeroPosition();
position = AMT.ReadAMT203Position();
if (position == 0)
{
for (; ; )
{
try
{
temP = position;
position = AMT.ReadAMT203Position();
if (temP != position)
{
fiddle = (double)(position) - (double)(temP);
if (fiddle > 2000)
{
turnPos = turnPos - 4095;
}
else if (fiddle < -2000)
{
turnPos = turnPos + 4095;
}
totalPos = turnPos + (double)position;
display.Clear();
display.Print(totalPos);
}
else{Thread.Sleep(1);}
}
catch(Exception Ex){}
}
I maybe wouldn’t cast to double to do the subtraction and comparison. There’s faster ways of making this comparison I think. But that is probably not going to make considerable gains.
I would remove the display stuff from this thread and put it in a lower priority thread with some kind of buffer in between this threads output and the display thread IE avoid locks if possible. That way you can read more often. And there is no way a human is reading your display that fast! Who would even notice the difference? Be sure to clear that with whomever set the requirement if you want to try this out.
And finally now with the input and output sufficiently isolated you have more room to maneuver… maybe use 2 or 3 consecutive reads to determine a rotation direction with higher accuracy if still needed.
So, quoting the master… assuming that’s right, talk of RLP on G30 is not going to get you anywhere. If you need to focus on something, make sure it’s not trying to get a mythical beast running on an impossible platform, ok?
that my friend is the exact way to do this. Screen displays cost more time than you have, so do that as a lower priority and spend what little time you have reading the thing that needs to go flat out.
@Brett I will try to optimize display calls / run some tests without the display on at all to see if that changes anything.
It is looking like an upgrade to the G80 + changing to this RS485 encoder that handles multi turn tracking on its own (or wait till “around July” for the newest SPI version. Dreading interfacing RS485…does anyone have a suggestions on an interfacing chip?
okay. temP, position, and totalPos all be type int?
Now you can
try
{
temP = position;
position = (int)AMT.ReadAMT203Position();
if (temP != position)
{
fiddle = position - temP;
if (fiddle > 2000)
{
turnPos = turnPos - 4095;
}
else if (fiddle < -2000)
{
turnPos = turnPos + 4095;
}
totalPos = turnPos + position;
//display.Clear();
//display.Print(totalPos);
// don't display here, but when you occasionally update the display you an do a cast there if
// needed
}
else{Thread.Sleep(1);}
}
I really don’t know much this will save you if it is an acceptable change. It may also be possible to overflow this way more easily.
@jwizard93 back to your mention of a lower priority thread. Would that really improve things if the G30 is a single core processor? Thought it can only scan through one thread at a time.
True. You could also try statically scheduling this behavior by something like only printing the display every 10th time the loop executes. The result would be largely the same I think.
The difference being that if it is threaded then the CLR decides when the threads get to run. And it will run the higher priority thread more often.
I tried printing to the display every 2nd position change and it is not a good alternative. The slightest amount you can touch the knob changes the shaft output significantly and that change needs to be displayed…skipping the first position change screws things up (the device compares to a pair of calipers displaying the new value each movement, it is the same concept except it is a rotating shaft changing some microwave engineering signal stuff).
In toying with this I did notice a serious bug. The display seems to not respond to display.Print() every time…the actual value displayed tends to be multiple iterations of the loop behind even though all code appears to be executed.