UNSUBSCRIBE
----- Original Message -----
From: "Keith R. Bolson" <krbolson-at-visi.com>
To: "Multiple recipients of list" <emc-at-nist.gov>
Sent: Thursday, January 31, 2002 4:29 AM
Subject: RESOLVED: EMC is poorly designed and implemented.
>
> RESOLVED: EMC is poorly designed and implemented.
>
> I'm an old gray haired assembly hacker and cycle counter with some
> experience in closed-loop motion control. I have been investigating
> EMC, principally emcmot.c and have come to the conclusion that EMC is
> poorly designed and implemented. I don't mean to be discourteous,
> but you do not have a good solid product, nor will you without
> a major redesign. I will support this conclusion in the following.
>
> What I see in the implementation is wasteful, redundant access to
> I/O ports, lack of insight into floating point speed considerations,
> poor factorization into subroutines and far too many scattered ifdefs
> for reliable code.
>
> Modern motion control should be adaptive, using Kalman filters, and
> state-space or observer predictor methods. EMC by design uses PIDs,
> which are from old 1930s analog computers. PIDs tuned via Ziegler
> Nichols methods are inherently prone to oscillation and instability.
> (The zeros don't cover poles, or drift into right hand plane, etc
> as the dynamics of the plant change with temperature and load.)
>
> A 8-bit 6502 or 8051 running at 1 MHz could do a nice job of running
> stepper motors in 1978. Without double precision, 32-bit integers
> or 800MHz clock rates. Servos were harder, but still possible. Today
> yoy can go to http://www.jrkerr.com/ and buy a PIC-STEP or PIC-SERVO
> with software for a reasonable price with software that'll get you up
> and running twenty times faster than EMC.
>
> Look at the source code (30-Jan-2002 sourceforge emcmot.c), lines 2422ff
> the polling of the max and min limit switches, home and axis fault bits.
> This is within the for loop on line 2373
>
> L2373 for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
>
> This is very poorly done, the exact same bits are read repeated,
> (for extsmmot.c) with over one microsecond per pptDioRead inportb
> call. That's (3 axes)*(4 switches)=12 microseconds, with 16 us
> listed as the max. Only one 1 us read is required. The situation
> is worse in stgmod.c, where 4 bytes are read, so it takes 48 us.
> Folks - i/o port access always takes over a microsecond, regardless
> of the speed of your i86 processors. Reading the same bits
> repeatedly in critical code is foolish and wasteful.
>
> I believe the choice to poll and debounce these switches within
> the motion loop (rather than, say, using a hardware interrupt or
> a slower emcio task read and debounce), is a very unwise design
> decision. Furthermore, American and European safety standards
> REQUIRE that hard limit switches bring the machine down even if
> the processor is non-functional. Meaning the limit switches, through
> a dumb relay, should drop main power to the motors. So on commercial
> machines, you don't need to check the limit switches, you'll E-stop
> if you hit them. As implemented here, EMC is likely to be HAZARDEOUS
> to the health of its users.
>
> And there's this over-dependence upon double precision numbers
> when single or integers will suffice. For example, in the external
> interface to stgmod.c, passing the raw encoders and dacs as double arrays,
> when they're integers on all hardware, doubles the subroutine call time,
> and then the subroutine itself has to convert it to an integer.
>
> Floating point is very fast these days, but it still takes time.
> Even on Pentiums, double precision floating point is about half as fast
> as single or integer arithmetic. Divides take about twice as long as
> multiples. A subroutine call takes about as long as an integer add
> for each 32-bit parameter. These are ballpark figures, much affected
> by caching, out-of-order and speculative execution.
>
> So code like on emcmot.c line 2397,
> L2397 if (fabs(emcmotStatus->input[axis] - emcmotDebug->oldInput[axis])
/
> L2398 emcmotConfig->servoCycleTime > emcmotDebug->bigVel[axis]) {
> Would be 50% faster if expressed as
> M2397 if (fabs(emcmotStatus->input[axis] - emcmotDebug->oldInput[axis])
> M2398 > emcmotConfig->servoCycleTime * emcmotDebug->bigVel[axis]) {
> But both servoCycleTime and bigVel are infrequently changed - on a
> explicit command, dump bigVel for bigLeap=bigVel*cycleTime and have
> N2397 if (fabs(emcmotStatus->input[axis] - emcmotDebug->oldInput[axis])
> N2398 > emcmotDebug->bigLeap[axis]) {
> which by my tests on 233 and 800MHz machines, would take about a third
> as long. I see the "debounce bad feedback" has been changed, it indicates
> a very serious hardware error which still is not logged or reported.
>
> You may consider this the ranting of a dinosaur or as constructive
> critism - as you choose.
>
> God Bless America, President Bush and our fighting men and women.
> --krb
>
>
>
>
Date Index |
Thread Index |
Back to archive index |
Back to Mailing List Page
Problems or questions? Contact