Servo Axis Simulator - Hardware version

Contr_Conn

Member
Join Date
Sep 2003
Location
Ohio
Posts
2,557
I decided to create a separate topic to discuss Axis Simulator

Project started here: http://www.plctalk.net/qanda/showthread.php?t=34516

Original topic had different purpose and issue already resolved.

Here is a quick summary of the project:

I decided to finish never ending Axis Simulator poject I started 4 years ago and never finished.

Axis Simulator allows to debug motion systems without having actual drives - typically for motion controller that have no built-in software simulators or virtual axis.

Prototype version of the simulator saved me in 2003 when we did large retrofit and developed motion programs with servos 600 miles away.

I converted Simulator to microcontroller and finally it's in a good usable shape so I can finish firmware features.

Here is a prototype:

sim.jpg



Simulator takes +/-10V signal.
Encoder output comes directly from Microcontroller using 5V Outputs: A+/A-, B+/B-, Z+/Z-
Drive Enable signal - 24VDC.
Power 24VDC - simple regulator brings it down to 5V
Simulator can generate pulses up to 62,500 Hz at 10V - I think this is fast enough to simulate real world application

Currently I am trying to tweak firmware so it can have delays to represent real servo system response.

Just want to hear comments and feedback. Thanks
 
I have already said you need to put in a low pass filter as it will be much more realistic than a ramp.

countrate(n+1) = A * countrate(n) + (1-A) * K * control voltage

K is the count rate per volt. System gain.
A is the filter constant which is exp(-T/tau) where tau is the time constant and T is the update period.

As long as tau is much longer than T then you can approximate exp(-T/tau) with tau/(Tau+T).

You should have a way of changing K and tau. K adjusts the gain or how fast the system is and tau adjusts the response. The range for tau should be about 1 to 1000 milliseconds. You could add a serial port but you probably have extra analog inputs where you can add some pots. This would be cheap. A serial port for changing these parameters would be more repeatable but that would also require a computer.
 
Peter,

in your formula you are using "count rate" and "K - count rate per volt"
if I understood this correctly:
is countrate = ouput frequency?

same with K - countrate /volt ?

Like I said in the old post - I am looking at implementing this formula, but PIC has very limited calculation abilities in fast applications

The way I do it today is very simple
- frequency generated interrupt routine called by internal hardware timer.
- Timer base is 8MHz so I am changing presets based on the analog input.
- Minimum divider is 128 - gives me 62.5KHz,
- highest divider today is 65535 - lowest frequency 122Hz, but I can easily change it to 30Hz with 12 bit ADC (10bit today)

Because I have very limited processing time at high speeds but huge memory area I am using lookup table to select frequency values. This is not a linear finction DividerPreset = 1/Freq.

So I am trying to figure out if I have enough time to do filter calculations or I have to put it in a lookup table.

As I said I already have routine that implements delay and rapm using simple FIFO stack.
Changing gain with POT may be a good idea - I many I/O pins available - I will be looking at this.

I also have serial port pins, but this will complicate design.
The old version with hardware VF converter uses Microcontroller with high speed USB port on board that is probably better idea than serial, but my goal is to make design very simple and cheap.

So for now I probably will use constant values - same way I am using constant for:
- amount of pulses between Z markers (i.e. count/turn =1000)
- amount of pulzes Z-marker is ON (4)
- and Max/Min frequency (i.e. Max speed = 62.5kHz)
 
Last edited:
Peter:

I want to make sure I understood your foumula correctly:

Lets say:

update interval T=10ms and tau= 100ms
then A=~0.9

F(request)=Analog*K

Now looking at the main formula:
F(n+1)=F(n)*0.9 + F(request)*0.1

This makes sense for step up, we are using 90% of old value and 10% of the new command

But how this will work with "Step Down"?
Should F(request) be negative in this case?

may be it should be delta F(request)= F(request n+1)-F(request n) ?

please take a look.
 
Contr_Conn said:
Peter,

in your formula you are using "count rate" and "K - count rate per volt"
if I understood this correctly:
is countrate = ouput frequency?

same with K - countrate /volt ?
Yes, K determines the encoder output rate as a function of the control voltage.



Like I said in the old post - I am looking at implementing this formula, but PIC has very limited calculation abilities in fast applications
Yes, I know but the formula for the lag filter requires only two multiply and adds. All the other calculations should be done only once when the parameters are changed and stored. When you get around to the filter the ask how to do it efficiently. There are some DSP programming techniques that must be done in assembly to be efficient.
 
The delay queue is not the right way to go. Put an OP amp in front of the AtoD converter and use it as a buffer and low pass filter.

I would also consider using a voltage controlled oscillator and use the output as the input into the timers on the mircro controller. This would off load the micro controller a lot. The micro controller counters would then divide the oscilator signal into two phases. This means the oscillator output will need to run about 4 time higher than the desired encoder output to get all the phases.

The micro controller can also generate the z pulse and the + and - limit switches.
 
The delay queue is not the right way to go. Put an OP amp in front of the AtoD converter and use it as a buffer and low pass filter.
I had OP amp filter before - I am trying to use less components as possible
I would also consider using a voltage controlled oscillator and use the output as the input into the timers on the mircro controller. This would off load the micro controller a lot. The micro controller counters would then divide the oscilator signal into two phases. This means the oscillator output will need to run about 4 time higher than the desired encoder output to get all the phases.
I already made it 2 years ago - I gave it to TWControls some time ago - not sure if he tried it ;) - it uses hardware Voltage to Frequency converter as a interrupt source for micro.
It works just fine with much wider range of frequencies but it adds cost of VFC, OPAmps, +/-15V power supply, external components and as result triple the cost.

My goal is to make it affordable to everyone.

The micro controller can also generate the z pulse and the + and - limit switches.
I am already doing this in all versions: Z+/Z- signals generated and it supports homing.
 
Last edited:
Adding simple C-code line F(n+1)=F(n)*0.9 + F(request)*0.1 doubled code size from 340 to 720 words!
Simple multiplication routine took 700+ bytes.
This calculation is outside of interrupt routine, but takes too much time to execute.
I can see simulator response changed and have to re-tune this axis.
I have to figure out if I can used hardware multiplication functionality that this Micro has.

EDIT: I tried F(n+1)=F(n)*9/10 + F(request)/10 and it takes only 80 words - so here is big improvement

So I guess here is a question Peter is waiting for: any better ways to simplify these calulations?
 
Last edited:
You have just entered the DSP zone.

If you multiplied by 9 and then divided by 10 you did it ALL WRONG!
You should never do a real time divide!!!! You should only shift.

If you are doing 16 bit math then you multiply by 58982 and then shift right by 16 bit to do a multiply by .9 . Normally no shift is required because this just involves using the upper 16 bits.

58982/65536= about .9 Use the upper 16 bits when doing 16 bit math

230/256 = about .9 Use the upper 8 bits when doing 8 bit math.

You may need to use some assembly language to multiply 16 x 16 and get a 32 bit result.
 
I actually realized this myself but I did not post it ;)

First I found that I have better response if I used numbers around .95 and 0.05
closest will be 15/16 = 0.9375 and 1/16 = 0.0625
First I used ADD instead of to multiply by 15.
Next I did is to shift right 4 - same as divide by 16.

I think this will work - I have to test tonight.
I can't shift 8 (/256) because analog input is only 9 bit.
 
I guess it will take me another year to complete it.

Low end microcontroller finally arrived, I converted code to use it and looks like everything is working.
Low pass filter implemented and looks like working, I hope this is correct implementation:
Code:
// NewValue is 12 bits, AnalogIn is 9 , or 1/8 of New value
// We use 7/8 of NewValue and AnalogValue to form new reading
// NewValue=NewValue*7/8+AnalogIn
// This will simulate low pass filter 
 
NewValue= (((NewValue*7)>>3)+AnalogIn);
 
// in case value went over 4095 to prevent DIV by 0:
 
if (NewValue>4095) NewValue=4095;
Currently Simulator uses 24V power source (actual range 5V-35V) that I think is sufficient for most applications.
Drive Enable signal ises 24V sinking input.
Encoder output - 5V differential signals(A,A- B,B- Z,Z- that can be used as "A,B,Z only" as well.
 
Last edited:
Contr_Conn said:
I guess it will take me another year to complete it.

Low end microcontroller finally arrived, I converted code to use it and looks like everything is working.
Low pass filter implemented and looks like working, I hope this is correct implementation:
Code:
// NewValue is 12 bits, AnalogIn is 9 , or 1/8 of New value
// We use 7/8 of NewValue and AnalogValue to form new reading
// NewValue=NewValue*7/8+AnalogIn
// This will simulate low pass filter 
 
NewValue= (((NewValue*7)>>3)+AnalogIn);
 
// in case value went over 4095 to prevent DIV by 0:
 
if (NewValue>4095) NewValue=4095;
Currently Simulator uses 24V power source (actual range 5V-35V) that I think is sufficient for most applications.
Drive Enable signal ises 24V sinking input.
Encoder output - 5V differential signals(A,A- B,B- Z,Z- that can be used as "A,B,Z only" as well.
That isn't quite right:
On a 8 bit micro the multiplies can be expensive. Consider this:

NewValue=((NewValue<<3)-NewValue+AnalogIn )>>3

For a slower time constant try

NewValue=((NewValue<<4)-NewValue+AnalogIn )>>4

It is relatively easy to shift left and right rather than multiply

(NewValue<<3)-NewValue = NewValue*7

(NewValue<<4)-NewValue = NewValue*15

It will be interesting to see the final result.
 
This is a good idea use shift and substract instead of multiplication.

I actually looked at the decompiled code for multiplication and it is very short if second operand is a constant like in my case.
Micro I use has hardware multiplication 8x8 bit that compiler uses in case both operands are variables.
But I am sure your code will be even faster.

Now, looking at formulas and using your idea I think I can do this:

NewValue=NewValue-(NewValue>>3)+AnalogIn

While driving to the family dinner I realized that I have a problem when Command voltage changes sign: internally AnalogIn is absolute command value, with sign bit removed earlier and used to change direction only.
So when command V changes from +V to -V filter calculations will not work correctly as AnalogIn=ABS(V).
I will have to re-write section what converts command to AnalogIn variable to include sign as well.
 
Last edited:
I guess compiler is too smart, looks like they doing good multiplication:
Code with
NewValue=NewValue-(NewValue>>3)+AnalogIn => 448 words

Code with
NewValue= (((NewValue*7)>>3)+AnalogIn) => 451 words

I will try to disassemble this section to see how *7 is done
 

Similar Topics

I have to rollout a common CLX PLC program to a dozen or more installations, but each installation uses a different HMI front end. Some WW, some...
Replies
8
Views
851
Dear All: I have the flashing red light on the FDBK indicator. The manual said that it means: The axis servo loop error tolerance has been...
Replies
2
Views
612
Hi PLC experts :) I’m working on a project in studio 5000 Logix designer with several servo motors, I'm trying to set the properties for them...
Replies
1
Views
811
Hello automation experts, I'm trying to learn about servo axis control in AB ControlLogix PLCs (L33ERMS). Attached is an example of a servo...
Replies
4
Views
1,050
I have a virtual master that drives all servos. How do I make Virtual Master or any Servo to follow regular encoder which is driven by Regular...
Replies
5
Views
3,111
Back
Top Bottom