langwadt / grbl_stm32

grbl for stm32 with nucleo stepper drivers
32 stars 33 forks source link

some corrections ... #7

Open J-Dunn opened 8 years ago

J-Dunn commented 8 years ago

I'm trying to find out why the lower priority serial link is distrupting the stepper motor pulses. As a result I have been examining exactly how the interrupts have been ported.

Digging through how the interrupts have been ported from AVR, it seems there are some ( non critical ) errors. From the doc it seems these lines can be removed. Initial, trivial, testing shows no breakage.

Firstly on NVIC interrupts are not disabled on entering an ISR. An interrupt can break into a running ISR. The line below from GRBL AVR is redundant:


// interrupts are NOT disabled inside ISR on stm32 !
 // sei(); // Re-enable interrupts to allow Stepper Port Reset Interrupt to fire on-time.
         // NOTE: The remaining code in this ISR will finish before returning to main program.
} // end stepper_interrupt1()

Similarly, the state of DMA1_Stream7_IRQ changes from pending to active on entering the ISR. Clearing pending is superfluous. NVIC_GetPending() shows it is already zero.


void DMA1_Stream7_IRQHandler(void)
{
    uint16_t inttime;
    uint16_t intpercent;
    uint16_t intperiod = TIM2->ARR;

    GPIO_SetBits(TESTP);

//  NVIC_ClearPendingIRQ(DMA1_Stream7_IRQn);  // why ? pending is cleared on entry.

Another redundant line. The temporary bit mask is only used once. Step pins are reset using the invert mask explicitly.


void stepper_pinset_interrupt()
{
    set_step_pins(st.step_bits);
//  st.step_bits = step_port_invert_mask;
}

Since there is always a need for a minimum delay on STM32, it may be best to take out the ifdefs and always run the same code path, rather than marking time with __delay_us().

J-Dunn commented 8 years ago

EDIT, I've rethought some of this and got rid of the extra long count. This allows removing all the timerrunning hack and using simple enable and disable on the timer.

stepper.c


void enable_timerint()
{
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//  timerrunning = 1;
}

There is also some imprecision in when this flag variable gets set. I have already suggested similar fix in mainline GRBL. Note I've also given it a more explicit name so we don't have to wonder what or who is "busy" somewhere else in the code.

There should be a one to one relation of calls to stepper_interrupt1() and stepper_interrupt2(); no need to test timerrunning either. The re-rentry test should be done on entry to the IRQ handler, not in what is now a later call, since this will result in an unwanted call to NVIC_SetPendingIRQ(DMA1_Stream7_IRQn);

void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        if (TIM2_update_IRQ_active) { return; } // The TIM2_update_IRQ_active flag is used to avoid reentering this interrupt
        TIM2_update_IRQ_active = true;

//      if(timerrunning)  // update int is disable when timerrunning=0
        {
            stepper_interrupt1();
            NVIC_SetPendingIRQ(DMA1_Stream7_IRQn); // this is a hack to get to a lower priority so the CC1 interrupt can get through
        }

The problem with the long count comes from doing the accounting AFTER stepper_interrupt2() which is setting up the next step, not the current one.


    _delay_us(20);
//  if(timerrunning) // needed to avoid false long time from stepper shutdown
    {
        inttime = (TIM2->CNT) / 25; // TICKS_PER_MICROSECOND / (1<<(TIM2->TIM_Prescaler-1));

        if(inttime > maxinttime) maxinttime = inttime;

        intpercent = (inttime*100) / (intperiod/TICKS_PER_MICROSECOND);
        if(intpercent > maxintload) maxintload = intpercent;

    }

    //  if(timerrunning)
        {
            stepper_interrupt2();
        }

    GPIO_ResetBits(TESTP);
}

the 'busy' flag should be set on leaving not in st_go_idle()

    // Segment buffer empty. Shutdown.
      st_go_idle();
      system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
      TIM2_update_IRQ_active = false;
      return; // Nothing to do but exit.
    }  

As a bonus the global volatile is no longer needed and the maxint values are coming out just a little shorter as well.

Cleaning up the logical structure would seem to be a good idea in itself.

langwadt commented 8 years ago

Correct, clearing the pending bit is redundant.

Stopping the timer and changing how the timer_running flag is set will have side effects, because the check for limits and control pins are tacked onto the end of the interrupt.

The clearing in stepper_pinset_interrupt() is a "safety" to insure that the timer can't just keep setting the step pins without interaction from the main stepper interrupts.

The accounting need to be after stepper_interrupt2(); or you'll only get the time used by the short stepper_interrupt1(); (the 20us delay is a test I forgot to delete)

I'm reconsidering whether it even makes sense to keep split the interrupt and the option to have a pinset/pinclr interrupt, with stepper drivers that only need a few 100ns step pulses it makes more sense to do it all in a single interrupt; step set on entry, step clear on exit, direction set when setting up the period

J-Dunn commented 8 years ago

re liniits: I figured that if the stepper timer is stopped nothing can hit a limit switch. I have not thought through all the implications for control pin but it seems a similar argument. In fact I'd rather look at getting all limits on one port and using a h/w interrupt as on AVR. Limits switches are an emergency situation and I'd prefer that to have a h/w trigger, not rely on program flow.

Pulse delay in mandatory on faster hardware. It was only optional on AVR because it was slow enough to provide enough delay while it was executing a few lines of code. I think the #define for PULSE_DELAY can be removed and a default of 1us used.

You did a good job of replicating exactly how this was done on AVR but the way interrupts work on NVIC is rather different. Like your comment says, it seems like a bit of a hack. I'm thinking of using two timers to create the delayed pulse in a way which is more native to STM32.

J-Dunn commented 8 years ago

Isn't the whole stream7 thing unnecessary?

The same TIM2 interrupt will get called and interrupt the stepper_interrupt1() and stepper_interrupt2() calls if necessary. This has the same effect as doing SEI() on AVR since interrupts are not not disabled in an ISR on NVIC. The priority hack is not needed.

Forgetting the stats output for the moment

void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        if (TIM2_update_IRQ_active) { return; } // The TIM2_update_IRQ_active flag is used to avoid reentering this interrupt
        TIM2_update_IRQ_active = true;

        stepper_interrupt1();
        limitpin_check();
        control_pin_check();
        stepper_interrupt2();

    }

#ifdef STEP_PULSE_DELAY
    if(TIM_GetITStatus(TIM2,TIM_IT_CC1) != RESET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);
        set_step_pins(st.tmp_step_bits);
    }
#endif
    if(TIM_GetITStatus(TIM2,TIM_IT_CC2) != RESET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_CC2);
        set_step_pins(step_port_invert_mask);
    }
}

CC1 , CC2 and ARR give the three periods needed for a delayed, variable width pulse of the required period. This covers all cases currently supported and eliminates the need for #ifdef PULSE_DELAY.

Seems to work on trivial testing.

langwadt commented 8 years ago

To me it makes sense to have the limit check in the stepper int, because the state of the limit switches only matter if you intend to move the motors and keeping it as a software check doesn't put limits on the pinout.

The delay and extra interrupts wouldn't be needed with a single interrupt like this: if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); set_step_pins(st.step_outbits); stepper_interrupt2(); set_dir_pins(st.dir_outbits,st.step_outbits); set_step_pins(step_port_invert_mask); }

The pulse width on the step pin will be variable but only the rising edge matters, the direction and clearing will always happen at least a whole step period before it is needed

You are misunderstanding how the NVIC works, the stream7 thing is needed because, while other higher priority interrupts are not disabled, The TIM2 interrupt is disabled until you return from the TIM2 interrupt. So in your example the TIM2_CC1/CC2 interrupts will not happen until the stepper_interrupt2() has finished

J-Dunn commented 8 years ago

The TIM2 interrupt is disabled until you return from the TIM2 interrupt.

Ah thank you, a detail I had misunderstood:

When the processor is executing an exception handler, the exception handler is preempted if a higher priority exception occurs. If an exception occurs with the same priority as the exception being handled, the handler is not preempted, irrespective of the exception number. However, the status of the new interrupt changes to pending.

J-Dunn commented 8 years ago

I'm reconsidering whether it even makes sense to keep split the interrupt and the option to have a pinset/pinclr interrupt, with stepper drivers that only need a few 100ns step pulses it makes more sense to do it all in a single interrupt; step set on entry, step clear on exit, direction set when setting up the period

The original GRBL comments say sei(); // Re-enable interrupts to allow Stepper Port Reset Interrupt to fire on-time. Now there is a broad set of hardware that is supported but are there any cases which require the step pin reset to be "on time", rather than just ensuring a minimum delay for the step pin to be asserted?

What you outlined above will be good enough for stm32+L6474, but may be too restrictive for broader support of GRBL driven h/w.

settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;

Would it be sufficient to regard this as a minimum delay rather than a precise, fixed delay?

I'm thinking of something like this on exiting the stepper interrupt: if ( (remaining = (STEP_PULSE_DELAY + settings.pulse_microseconds )*TICKS_PER_MICROSECOND - TIM2->CNT ) > 0 ) delay (remaining);

langwadt commented 8 years ago

A minimum time is easy, just run the whole stepper interrupt on UPDATE, and the reset on CC1. if the stepper interrupt is shorter than the minium the reset will happen when CC1 fires, if the stepper interrupt is long CC1 will be pending and happen after the stepper interrupt is done.

The only problem is that the low time on the stepper pins are then limited to the time the stepper interrupt is finished to the next update, so if the time ti takes for the stepper interrupt get too close to the stepper period it might be too short

But at that point you are running out of cycles for the main loop so you might be in trouble anyway

J-Dunn commented 8 years ago

Yes, if the low time is getting critical the assumption that the interrupt will return in time ( which is the basic assumption on which GRBL works ) will not be satisfied. This is the upper limit of the stepper pulse rate anyway. I was still thinking of keeping STEP_PULSE_DELAY functionality, probably with a default of 1us which is more than enough for L6474.

My question was not really how to do this but whether such an approach covered all types of supported h/w. This may be a question better asked on grbl/grbl where those with deep knowledge of all the things GRBL gets used on will be.

J-Dunn commented 7 years ago

Hi , looks like you have been doing other things too. ;)

I just found some time to get back into L6474 and STM32 this week. After carelessly blowing out one of my F411RE's with a bit of stray charge left in an electrolytic, I'm limping along on two axes.

My rig is working quite well but I'm way from getting a decent current into my NEMA23 motors.

I have a 50 mohm resistor in line with the power supply to a stack of three L6474 demo boards on top of a Nucleo F411RE. I have a minimal holding torque TVAL=2 so most of what I measure is going to the single motor I am moving.

Total input current is about 0.6A RMS, with TVAL=108 , which is over 3A peak current. At this rate, I may as well be using a Polulu !

So far I can not get faster than 3m/min off load. $112=3200.000 (z max rate, mm/min)

The degree of control offered by the L6474 is really nice but actually setting it up seems to be bit of a black art. Do you have any suggestions of where to find a guide on getting the best config for a given system?

TIA.

langwadt commented 7 years ago

I have not seen anything about setup other that the little there is in the datasheet. I'm not sure I follow your measurement. As far as getting high speed, you should look at the coil currents to see if the driver voltage is high enough to reach a reasonable current.

I have a system running with powerstep01drivers, they can handle much higher currents and voltages

J-Dunn commented 7 years ago

Thanks for the reply. I had looked at the powerstep01, good spec and functionally very similar to L6474, so should be easy to switch. However the eval boards are a bit dear and the format of the bare chip is not going to be easy to work with.

The idea of measuring the power at the supply end was to see what was being drawn and whether is was limited by the supply ( an HP 32V x 3A switchmode ) .

Putting a similar 50 mohm shunt in line with one of the coils gives 6-8A pk-pk at the constant, max pulse rate and about 60V RMS. The current waveform looks basically sinusoidal with a couple of lumps, which does not seem to correspond to the diagrams in the RM, since I'm running half-step mode.

I have OCD set at L6474_OCD_TH_5250mA . This is not making a lot of sense to me in relation to the doc.

langwadt commented 7 years ago

X-NUCLEO-IHM01A1 is ~$13 at digikey, X-NUCLEO-IHM03A1 is ~$10 at digikey so the powerstepboard is cheaper

J-Dunn commented 7 years ago

Thanks for that ref. I had only seen an 'eval' board for that chip at $36. At $10 and what looks like a drop in replacement I'll order them straight away. Sadly my scope has died which is somewhat limiting ! Waiting for a replacement.

I have put lead-acid batteries powering the driver stack with circa 39V. That is getting pulse rate a little higher, so it looks like those stepOne boards will allow me to up the tension and push some more amps into the motors. It looks like the 45V limit is the limiting variable not the current setting I'm still getting fastest pulse rates while dropping TVAL to 69.

I think the PSU was not supplying enough peak current. I am way lower on TVAL now and it is still reliable. This is more sensible values for an unloaded axis. I was seeing glitches on the pulse train and I think this may be what was provoking the stall condition.

I can't do much w/o a scope but at least I think I've found the bottleneck. Thanks for pointing me to those boards. A steal at ten bucks a piece. :)

J-Dunn commented 7 years ago

HI, I've ordered three of those boards, should get them on Monday. Very similar but different. It's going to need some careful porting.

They have resistor links for the SPI to stack them in a similar way but don't seem to have the same for the "PMW" lines for STCK. DIR has to be done through SPI but how are the different STCK lines to be connected?

Do I have to get out a scalpel ?! Are you using more than one ?

thx

langwadt commented 7 years ago

I'm actually using 4 with 2 for my Y axis so I have to do some trickery with the spi too, but I just bend pins out of the way and add wire links. i.e. for 3 boards

top: add link between pwm1 and pwm3 in female connector, bend pwm1 and pwm2 on male connector

middle: add link between pwm1 and pwm2 in female connector, bend pwm1 on male connector

bottom: standard

J-Dunn commented 7 years ago

Thanks, I thought I was missing something. Seems odd they way they have provided links for daisy-chaining the SPI but leave all the STCK lines hard-wired together. They made rather a good job of it on the 01A0 boards.

Are you still driving this with GRBL?

langwadt commented 7 years ago

I think they are mostly meant to use the build in motion engine with commands via spi so stck isn't used. But I don't see how that is possible when you need to coordinate multiple axis moving in sync.

yes it is still done with grbl, just added the configuration of the controllers to init and spi writes of the directions at the top of the step interrupt

J-Dunn commented 7 years ago

Yes, the chips seem to have been designed to work both ways but the demo boards, not so much.

I think I will keep track of direction which can only change when a motor is stopped. It seems crazy doing a pointless 3 or 4 board SPI communication at every single step. Unless I'm mistaken, it will not change inside a GRBL planner block anyway.

I'd much rather have this on a h/w pin but these chips look quite good otherwise.

langwadt commented 7 years ago

looking at the code I only set the direction for every new segment, 3 spi commands is roughly 8us max spi clock for the powerstep is 5MHz but with a 100MHz cpu clock you can only use 3.125MHz spi clock, the next up is 6.25MHz

J-Dunn commented 7 years ago

OK, that makes more sense. It's still going to be doing a relatively slow operation at critical max speeds when it is absolutely not needed. Here may be better:

 void st_prep_buffer()
  ...
  if (pl_block == NULL) {

1/3.125 8 2 *4 = 20us , are you breaking the communication without recovering the return bytes?

J-Dunn commented 7 years ago

Well, I just got the IHM03A1 boards but see that they are marked on the legend Vin-Vgnd "max 50V"

WTF? that's only 5V more than the 01A0 L6474 boards.

The product pdf clearly states 85V in the "feature" list. Chip datasheet says "Operating voltage: 7.5 V - 85V" http://www.st.com/en/ecosystems/x-nucleo-ihm03a1.html http://www.st.com/resource/en/data_brief/x-nucleo-ihm03a1.pdf

I'll bet that they have had problems with the electrolytics C14,C15 and failed to amend the product description. Seems like I'm going to need to start hacking the boards before I've even go the wrapper off. :(

The identification on the cap. looks like a Cornell-Dubilier part. in which case 2A would be a 100VDC rated but I guess they must not be well spec'ed driving larger inductive loads.

langwadt commented 7 years ago

The chip is spec'd for 85V and on the BOM all the relevant capacitors are spec for 100V, the only thing I can think of is that they are concerned capacitor value is too small to keep the voltage within spec with a big motor forcing the supply under deceleration

J-Dunn commented 7 years ago

I'm having some trouble getting the new Step01 boards to spin anything. As soon as I try to move D2 comes back on. I am trying to set up an IRQ on the FLAG pin to catch what is going on when it fails. It is not getting called when FLAG drops.

Can you see what I have messed up? Thanks for any tips.


void init_FLAG_IRQ(void)
{
    // FLAG = D2 = PA10 (ARD pin 3) ; use EXTI10
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource10);  

    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStruct;

    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStruct.EXTI_Line = 10;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
} // end init_FLAG_IRQ()

void EXTI15_10_IRQHandler(void)
langwadt commented 7 years ago

change EXTI_InitStruct.EXTI_Line = 10; to EXTI_InitStruct.EXTI_Line = EXTI_Line10;

it is a bit map not a bit number

J-Dunn commented 7 years ago

Many thanks. That explains my mistake. However, a breakpoint on the first line of the handler never gets control; the program is now stuck in a loop when I use _delay_us() . :(

langwadt commented 7 years ago

forget the EXTI_ClearITPendingBit(EXTI_Line10); in the handler?

J-Dunn commented 7 years ago

OK, that is working as expected now, thanks. The IRQ allows me to trap when the FLAG pin is dropping and examine the status bits. This has enabled me find out what the problem is, at least. In STEP01_init() it am getting it to a state which is as expected :

status=E713

The last step is to drop the HiZ condition as would be done by L6474 single byte command L6474_ENABLE = d184 , what is the equivalent on STEP01?

Chapter 11.2 says that both HardStop and SoftStop stop do that , but when I try sending that, both will triggering the FLAG IRQ which then shows the following status bits:

[FLAG IRQ handler 
 raw: bH 00000110
 raw: bL 00010011
]

ie status=0613 : both phases stalled ; OCD (!?) and now dropped out of step clock mode. The low byte shows STEP01 is still in HiZ state.

When the motor is in high impedance state, a HardStop command forces the bridges to exit high impedance state; no motion is performed.

  STEP01_SetParam( ALL_SHIELDS, STEP01_TVAL_RUN,  STEP01_TVAL_1092mA );   // =13
  STEP01_SetParam( ALL_SHIELDS, STEP01_TVAL_HOLD, STEP01_TVAL_2028mA );  // =25
  STEP01_SetParam( ALL_SHIELDS, STEP01_OCD_TH, STEP01_OCD_TH_5A );  //  =15;   def=8=3.375A

I'm unclear whether it is TVAL_RUN or TVAL_HOLD which is relevant in step clock mode but don't see why I'm getting OCD nor why it is losing step clock mode.

This has been far more work than I anticipated, hopefully it is nearly ready to make something move !

Can you see what I'm overlooking? Thanks.

langwadt commented 7 years ago

I fetch clear all status, setup parameters, issue a CmdHardHiZ ( a 0xA8) and then a CmdStepClock ( a 0x58) at which point the stepper "turn on"

only TVAL_HOLD matters in stepclock mode

J-Dunn commented 7 years ago

thanks, that confirms what I was guessing to be the case for TVAL_HOLD.

I found an error where I was intending to current mode and didn't. That removed the stall conditions but I still get OCD every time I try to move. I've been over it a thousand times now and can't find the problem.

What are you setting to the CONIFG register?

J-Dunn commented 7 years ago

BTW green D8 seems excessively bright, is that normal on these boards?

langwadt commented 7 years ago

D8 is bright but it's nothing extreme.

I pretty much use the code and setting from the x-cube-spn3 examples.

http://www.st.com/en/embedded-software/x-cube-spn3.html

J-Dunn commented 7 years ago

Thanks, I found the problem anyway. It was not the params as such just a stupid error using an & where there should be an | . Thanks for the help. Now perhaps I get something done !

J-Dunn commented 7 years ago

OK the object of getting these boards was to supply more voltage. Since they have down graded the spec from what was advertised that did not quite work out. I pushed it to 57V since I am way under the max current. This has made a notable improvement to the max step rate I can get without a stall ( +75% )

However, I am still not getting much power into these motors. I'm measuring the current applied at Vin since it is smoothed and most of it going into the motor windings. It's still only about 0.6A RMS in half step mode. Upping TVAL_HOLD or IGATE does not make any increase. Despite the very complex control offered by these chips, I am a long way from driving a credible current into the windings. I get the impression I'm not getting the best from chips.

Do you have any suggestions on where to look or is this probably just limitations due to the physical properties of motor windings? Thanks.

BTW. Heat dissipation is a lot better on these boards than the L6474 ones.

langwadt commented 7 years ago

at what conditions are you measuring 0.6A? Don't forget that the driver works like a switch mode supply

J-Dunn commented 7 years ago

Indeed, that means that I am getting about 35W into the motor but only gives a comparative indication of the mean current. What seems odd is that upping TVAL from 2A to 3A does not increase the overall current, so I conclude it is not affecting the motor current. Setting PRED_EN did increase the current but did not help get faster movement.

I'm using 200 step motors on a 5mm ball screw in half-step mode. The best I can get is: $100=80.000 (x, step/mm) $110=5600.000 (x max rate, mm/min)

I tell GRBL 80 since it does not know I'm using halfstep. This agrees with timing the movement. Now I make that 5600 * 80 / 60 = 7467 Hz or 134 us pulses however, it's more like 1100 us on the 'scope. That is a complete 1 - 0.7 - 0 - 0.7 cycle, that's still off by a factor of four.

I am thinking that these control pulses are too short and the motor is stalling because the pattern is not regular.

langwadt commented 7 years ago

have you looked at the torque curve for your steppers?

if you want to see whats possible without putting grbl in the mix, you could try doing movements with the build in motion engine

J-Dunn commented 7 years ago

Thanks. The torque curve is down 50% at 4400 pps, measured at 3A and 30V, I'm way under that step rate and pushing almost twice the voltage. Since changing TVAL from 2A to 3A makes no change to the supply current I am still under the conclusion that I'm not getting more that 2A into it.

Using the internal firmware is a very good idea, I'll look into that.

J-Dunn commented 7 years ago

Right, using internal motion control I have 22" run down from 6s to under 4s in half step mode. I had to hack the calculations since the doc does not seem to make much sense.

Maximum speed parameter ranges from [ 1 to 2^10-1 ] · 2^-18 step/tick (equivalent to 15.25 to 15610 step/s).

They seem to forget to tell us what a "tick" is and I would guess that it is the internal oscillator, however: (step/s) / (step/tick) = tick/s ; 15.25 / 2^-18 = 2^18 * 15.25 = 4MHz , the default clock is 16MHz :?

A similar result is obtained from the default speed settings:

MAX_SPEED def 0x41 248e-6 step/tick (991.8 step/s) 991.8 / 248e-6 = 4 MHz 'ticks' ; d65*15.259=992

STEP01_ACC def = 0x8A=d138; 125.5e-12 step/tick^2 (2008 step/s^2); 2008 / 125.5e-12 = 16x 10^12 = (4MHz)^2

I get overall speed at $110=5600 similar to grbl speed using the following settings, the factor is 6 being tweaked to get the same run time.

int32_t steps_per_second = (settings.max_rate[0] ) / (60 /6) ;  //  #### trial and error hack 
  driver_SetParam(0,STEP01_MAX_SPEED,(uint32_t)steps_per_second*15.259);

I'm suspecting a documentation fault / omission , do you know what this is about ?

This was done with the same 57V supply and TVAL et al all at 2A . Current drawn from supply is very similar to what it is under grbl at 5600 mm/min

langwadt commented 7 years ago

the datasheet I looked at says 250ns tick on all the speed calculations

I'd say your speeds are at a the top end of what can be expected from a stepper

J-Dunn commented 7 years ago

Thanks, indeed.

where SPEED is the integer number stored in the register and tick is 250 ns. The available range is from 0 to 15625 step/s with a resolution of 0.015 step/s. The range effectively available to the user is limited by the MAX_SPEED parameter.

So that fits the 4MHz.

The torque curve I have for this motor only goes as far 4500 pps where it shows 50% of peak torque. With the extra volts and only driving frictional load it will go a lot higher. If I can get $110=9000 mm/min on internal I should be able to get that from GRBL

Maximum MAX_SPEED is 15625 step/s so it should not be the chip which is limiting, unless the chip works less well when driven directly from Step pin. Maybe it can act more predictively when it has a predefine flight plan.

It may be that I have not configured it optimally or that the fancy adaptive current control features are not stable enough at high switching rates. It does not look really stable on the scope. If I'm near the motor's limit some irregularity could be causing the stall.

Looking on the 'scope, the way TVAL_RUN is controlled looks very different from TVAL_HOLD in step clock mode.

langwadt commented 7 years ago

I believe the internal motion engine it switches to full step mode at high speeds.

The problem with running steppers at such high speeds is that you hit all kinds of resonances and it only take one missed step before the motor loses sync and stops. You have to get the stepmode and acceleration just right, a mass damper on the stepper can work too to push the resonances out of the working range

J-Dunn commented 7 years ago

Thanks, the Step01 has a programmable threshold for switching to FS mode, I set that to full speed to prevent that happening.

I am aware of the kind of resonance problems that you point out but that is not the key issue here. I get notably different waveforms from internal moves and GRBL moves. The internal is rock solid and nearly square wave, GRBL is jittery and has glicthes in the wave form. It seems that the chip is doing notably different things on internal to what it does on step pin driven pulses.

Here are 'scope images of the two cases ( A- terminal) : 3000mm/min half-step : GRBL https://github.com/J-Dunn/grbl_stm32/blob/master/step01_grbl_3000_half.jpeg?raw=true 3000mm/min half-step : Step01 internal https://github.com/J-Dunn/grbl_stm32/blob/master/step01_internal_3000_half.jpeg?raw=true

The GRBL trace shows jitter in the timing and glitches during each step cycle ( about 2.25ms long ) . Either the jitter or the glitches could be the cause of the earlier drop out when using GRBL.

Do you have an idea what those gliches are any why I'm only seeing that on step mode under grbl and not on the internal motion.

J-Dunn commented 6 years ago

Hi langwadt , I'm hoping that you can point me in the right direction here since you are familar with these chips. I'm not making any sense out of these powerSTEP chips and you may be able to put straight and tell me what I just can't see.

step01_grbl_1000_half

0.2ms/div , the repetition cycle = 6 divs : about 833Hz.

This is with the probe on the current sense resistor on the nucleo demo board , so it's exactly what the chip uses to monitor current. I'm running half step mode at $110=1000 mm/min on 200 step motors; 5mm pitch ballscrew. I make that 267Hz pulse rate from GRBL.

I'm expecting a step cycle 0 0.7 1.0 0.7 ; followed by a similar cycle for the other side of H-bridge, also positive on the sense resistor. I don't see such a symmetry and I'm unable to interpret this as powerSTEP01 producing such a cycle.

Is this some "feature" of the chip that I am not understanding, or am I just misreading the 'scope?

Thanks for any light you can shine.

BTW I am aware that slow rise is due to the inductance smoothing out the ideal step levels, what I don't get is that the falling side of the step cycle does not seem to be there.