2 motors angle synchronization - help needed

More
06 Sep 2011 20:16 - 06 Sep 2011 20:17 #13009 by mkii
Hi,

I'm a newbie using EMC so maybe I've put this topic in wrong category.

I have one project where positions of 2 motors must be synchronized in some periodic time line.

I have following:
- 2 motors with attached pwm position encoders
- motor A is moved manually (for this prototype)
- motor B is moved by emc with possible feedback
- pwm encoder generates pwm signal based on motor position (angle)
- every 60 seconds system must check position of both motors and then move motor B to the same position (angle) where motor A stands
- for all this i need some nice gui (axis not needed)


So my concept goes in this direction:
- connecting both pwm encoders to parport
- every 60 sec check pwm values and based on results either do not move motor B (if is on same position as motor A is) or move morot B CW or CCW - - based on compares - for this I plan to use clacisladder
- for gui i'll use widgets for showing direction of both motors

Can you give me some directions on how to implement this?
Just for simulation I’ll have to generate pwm signals for both motors using hal components.


thx,
alek
Last edit: 06 Sep 2011 20:17 by mkii.

Please Log in or Create an account to join the conversation.

More
07 Sep 2011 12:47 #13028 by andypugh
mkii wrote:

I'm a newbie using EMC so maybe I've put this topic in wrong category.

No, this seems fairly advanced.

- 2 motors with attached pwm position encoders

This is the first problem. EMC2 has no way to read in a PWM value.
This isn't a huge problem, as it is fairly easy to write a HAL component to do it. It would look a bit like this:
component pwmread "convert PWM input to float value";
pin in bit pwm-in;
pin out float value = 0;
param rw float filter = 1;
variable float off-time = 0;
variable float on-time = 0;

function(_);
license "GPL"
;;
FUNCTION(_){
static int state = 0;
switch state{
    case 0: //this initialisation isn't strictly correct
        if (pwm_in){
           state = 1;
           on_time = 0;
           off_time = 1;}
        else {
           state = 2;
           on_time = 1;
           off_time = 0;}
        break;
    case 1; // pin-high counter
        on_time += fperiod
        if ( ! pwm_in){
           value = on_period / off_period;
           off_period = 0;
          state = 2;
        }
        break;
   case 2; // pin-low counter
        off_time += fperiod
        if (pwm_in){
           value = on_period / off_period;
           on_period = 0;
          state = 1;
        }
        break;
    case else: // How the heck did _that_ happen? 
       rtapi_print_msg("That's just bizarre")
    }
}

You would need to install that into EMC2 with "comp --install pwmread.comp"
linuxcnc.org/docs/html/hal_comp.html

This is a simplified version, it will dither a lot, and takes at least two PWM periods to produce any sort of correct value. It will only work at all if the PWM period is a large multiple of the EMC2 base period. Any practical implementation would include a low-pass filter to remove the sample-to-sample dither.
Also, this implemetation needs to handle flaoting-point calculations and run in the bas thread, which is unusual. The periods should be accumulated as integer nS (using period not fperiod) and a second "pwmread.N.calculate" function would be used to perform the FP calcs. However, for your simple system this implementation is probably OK

So my concept goes in this direction:
- connecting both pwm encoders to parport

Can be made to work, see above.

- every 60 sec check pwm values and based on results either do not move motor B (if is on same position as motor A is) or move morot B CW or CCW - - based on compares - for this I plan to use classicladder

Doing it every mS would be easier than every 60S. However, there is no need to use Classic Ladder. HAL is perfectly capable of doing this, the PID component would do it admirably.

- for gui i'll use widgets for showing direction of both motors

This is do-able too, your HAL file simply needs to start a PyVCP or GladeVCP standalone GUI.

Basically, you would write a HAL file something like
loadrt threads name1=base-thread period1=50000 fp1=1 name2=servo-thread period2=1000000 fp2=1
loadrt pwmread count=2
loadrt pwmgen count=2
loadrt pid
addf pwmread.0.base-thread
addf pwmread.1 base-thread
addf pwmgen.0 base-thread
addf pwmgen.1 base-thread
addf pid.0 servo-thread

start 

loadusr pyvcp mypanel.xml

setp pid.0.Igain 0.01
setp pwmgen.0.pwm-frequency 100
setp pwmgen.0.enable 1
setp pwmgen.1.pwm-frequency 100
setp pwmgen.1.enable 1

net master-motor-simulated mypanel.slider => pwmgen.0.value
net master-motor-pos pwmgen.0.pwm => pwmread.0.pwm-in
net slave-motor-simulated pid.0.value => pwmgen.1.value
net slave-motor-pos pwmgen.1.pwm => pwmread.1.pwm-in

net pid-cmd pid.0.command <= pwmread.0.value
net pid-fb pid.0.feedback <= pwmread.1.value


So, it can be done. I am puzzled about the "why" part. This seems like a job better suited to nothing more complicated and expensive than an arduino. In fact if they are stepper motors I think you can simply couple them together.

Please Log in or Create an account to join the conversation.

More
07 Sep 2011 13:28 #13030 by mkii
andypugh thx for detailed info!

I'll follow your sample in a hope to get it work :)

Please Log in or Create an account to join the conversation.

Time to create page: 0.228 seconds
Powered by Kunena Forum