Main Site Documentation

G30 rlp spi


#1

First Off,

Where can I find the files listed in the below GHI Doc for installing the RLP compiler?

https://old.ghielectronics.com/docs/50/rlp

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).

@Justin Have you ever tried this?

P.S. My title keeps getting auto formatted to lowercase for some reason.


#2

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.


#3

Hi,

A couple things:

  1. 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.

  1. 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?

#4

@jwizard93 So you have used RLP on the G30?

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.


#5

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.


#6

@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.


#7

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


#8

@jwizard93 Ah ok I wasn’t sure if maybe you accomplished what Gus said has not been done yet.

I can’t ask GHI for help, as I don’t have $10,000 to drop on a driver. Would be easier to just implement RS485/the next level of encoder (AMT21).

Here is the Datasheet for my current encoder (the AMT203). The AMT21 takes care of multi turn tracking which would eliminate the need for RLP.


#9

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?


#10

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){}
                 }

Let me know if you see a way to speed this up.


#11

Hmm. tough one. This looks good to me.

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.


#12

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?


#13

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.


#14

@jwizard93 How do you suggest I do the subtraction / comparison of uint position and temP without casting to double?

@Gus_Issa Can the G80 handle RLP?

@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?


#15

What are the types of the two variables involved in the subtraction before the cast?


#16

@jwizard the positions are returned as “unit” from the encoder read.


#17

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.


#18

@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.


#19

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.


#20

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.