Open J-Dunn opened 6 years ago
as far a remember the idea was to always have the timer running because the check of the limit and control pins were called from the timer instead of using pin change interrupt, using the pin change interrupt would limit what pins could be used for limit/control
Thanks, I just wanted to check that it was not something more subtle that I was over-looking.
I'm trying to understand the workings of the STEP01 and it's driving me nuts. I used TESTP pin you used and I'm seeing pulses 8 times too often. The scope output below is the sense resistor on the IHMO3A1 board, the step pulses are about right for 1500mm/min on my h/w. 0.5ms steps at half step mode. Timebase is 0.5ms / div.
However, I have to skip 7 out of 8 test pulses to match the Step pin. This seems crazy since they are get and reset immediately round the step pin changes. I've been messing with this all day. Can you point out what I can't see ??
Thx.
BTW I've turned off STEP_PULSE_DELAY #define and do it directly with delay() to try to pin it down in a simpler implementation.
volatile uint16_t test=0;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if ( TIM2_running ) set_dir_pins(st.dir_outbits,st.step_outbits); // ??? why TIM2_running ? this will never becalled is TIM2 disabled ! ###
test=test&7;
if ( ! test++) GPIO_SetBits(TESTP);
#ifdef STEP_PULSE_DELAY
st.tmp_step_bits = st.step_outbits; // Store out_bits to prevent overwriting.
#else
_delay_us(1); // ensure min delay after setting dir pins
set_step_pins(st.step_outbits);
_delay_us(25); // ensure fSTCK<2MHz
set_step_pins(step_port_invert_mask);
#endif
GPIO_ResetBits(TESTP);
the step interrupt runs at 8x time the step rate "Adaptive Multi-Axis Step-Smoothing(AMASS)" it makes the steps smoother when running with multiple axes at the same time.
the _delay_us(25) is a lot of wasted cycles, the step pin on STEP01 only needs 300ns pulse width
Ah, right, I should have sussed that. Thanks. The 25us was intended to be wasteful, it's just to make it more visible on the scope at those slower step rates. I was running with 1us for delay and step pulse; not needing to push too close to the limit and keeping the handy _delay_us() fn.
It does seem to work fairly well even at high speed where the current does not have time to reach a decent amplitude. Bench testing suggests I'll get useful torque upto about 4000mm/min before resonance kills the current. That's just about enough for a decent cut on a larger tool, if my mechanics are up to it :?
I'm having a little difficulty identifying the four parts of the half step cycle in that image and marrying that with what the RM says the chip will do but I'll think it's time to throw it all together and see what happens.
thanks.
// AMASS_LEVEL0: Normal operation. No AMASS. No upper cutoff frequency. Starts at LEVEL1 cutoff frequency.
#define AMASS_LEVEL1 (F_CPU/8000) // Over-drives ISR (x2). Defined as F_CPU/(Cutoff frequency in Hz)
#define AMASS_LEVEL2 (F_CPU/4000) // Over-drives ISR (x4)
#define AMASS_LEVEL3 (F_CPU/2000) // Over-drives ISR (x8)
does this mean that AMASS levels may need reviewing for STM32 with much higher clock speeds?
I have noticed that if I do a long move at a slow feed rate, the step rate drifts audibly and after a few seconds skips back and drifts again. I have not tested whether this occurs on std GRBL. Have you noted anything like that?
F_CPU is set to 25MHz which is the timer speed so all the speed calculations are correct, nothing else is needed. AMASS just means that when you have multiple axis moving at different speeds at the same time the step pulses get more regular.
I don't remember any odd step rate drifting, any example at what step rates it happens?
Actually I think the drift is happening all the time but is more obvious on a run where there is a very long plateau in the block planning. This usually occurs when I type something like $110=150 instead of 1500, so my test run becomes 10x longer duration than I intended and much slower. Over 5 - 10 seconds it drifts up slowly but audibly then skips back by about one musical tone and drifts again. Half way through the plateau the pattern reverses: drifting down in pitch and skipping up.
I'm running just one STEP01 on a NEMA23 motor on the bench. So if I make an error in the params I may get a run which lasts about 30s and this pattern becomes noticeable. I recall also noticing an audible irregularity while doing a relatively slow displacement of my y axis ( 1.2m ) .
This may be due to the constant recalculation of the planning buffer and rounding errors due to integer arithmetic getting corrected. I suspect this is a GRBL "feature".
// Compute segment step rate. Since steps are integers and mm distances traveled are not,
// the end of every segment can have a partial step of varying magnitudes that are not
// executed, because the stepper ISR requires whole steps due to the AMASS algorithm. To
// compensate, we track the time to execute the previous segment's partial step and simply
// apply it with the partial step distance to the current segment, so that it minutely
// adjusts the whole segment rate to keep step output exact. These rate adjustments are
// typically very small and do not adversely effect performance, but ensures that Grbl
// outputs the exact acceleration and velocity profiles as computed by the planner.
I realised why I did not spot the x8 thing. I still had the understanding from the original GRBL code where the timer interval was already 8x slower, cf. :
TIM_SetCompare2(TIM2,(settings.pulse_microseconds)*TICKS_PER_MICROSECOND);
OCR0A = -(((settings.pulse_microseconds)*TICKS_PER_MICROSECOND) >> 3)
Aside the minor difference between Uno's 16Mhz and 25MHz, doesn't this mean the stm code is firing 8x more often, probably for no gain?
The Uno uses timer1 for step, and timer0 for pulse delay. The STM uses multiple compares on the same timer
if the interrupt was running at 8x all the feedrates would be 8 times too fast
somewhat unrelated but having got a single STEP01 board working fairly well I want to stack them. I had a stack of four L6474 boards daisy-chained and working but can't see how this can be done with the IHM03A boards since they only have link resistors on MISO and MOSI, but not on STCK. Since all boards have the same step pin how can they be wired to stack up, without some ugly hacking and surgery?
Thanks.
bend legs and add wire link, not too ugly
Oh wow. I thought I was missing something because ST provide a pdf saying you can stack up to 3 motors but don't mention you have to bodge around like that.
It's not exactly the way I like to do things when building a working machine but I suppose it's better than doing open heart surgery on the boards. Many thanks for the tip anyway. It's probably about the best option.
if you only use the internal motion engine you can stack three boards by moving around link resistors
Ah , of course. They seem to be pushing that way of doing things and kinda leaving a step pin for "legacy" reasons. Unfortunately that's not much use for machine control which requires coordinated axis movements. It seems these chips are more aimed at banal things like car window winders .
Since those pins remain unused, it's a shame that they did not retain the flexibility of the L6474 boards. For the cost half a dozen 0R SMC resistors ... pennies. :(
using the step pin makes no sense, and defeats the purpose of the motion control engine. Of course its possible to use that for multi axis machine control. The way to do it is to command a velocity, and read the abs_pos register. in the controller you then have a p ff controller. the ff term does most of the work, and the p term takes care of any clock drift. the controller can be running very slowly, like 1 khz. so you only need to have a spi transfer every ms. here is a example of this: https://youtu.be/hVCuPgjcF8g 4 powersteps in daisy chain, controlled by a f4 via ethernet. the actual p ff controller runs on the computer at 1 khz.
almost every hardware step generator works this way, you have a high speed timer, and then a low speed control loop that commands a velocity, and looks at the actual position.
using the step pin makes no sense,
It makes sense since I already have working tested software (GRBL) which operates on the basis of direct step control. I would have to write and test an alternative solution to do what you suggest.
Since that is a fundamentally different solution I'd be throwing out the whole thing and basically starting from scratch.
Since you do not give anything more than "p ff" and no details on performance criteria and testing beyond a lame YT vid, that is not much help really. It amazes me why technical folks bother with such vids. No use to anyone. They give no idea whether the system works beyond just spinning a motor on the bench, nor any info about how to achieve a similar result should one decide it may be useful.
I've had my fill of watching other people's bench testing. Really not informative or even interesting.
Also going to the trouble of designing and testing a closed loop solution to run an open loop motor control is a joke.
I think that GRBL is not the right starting point for powerstep01 or all spi based drivers. I’m trying to work on a new code.
@rene-dev It might be possible in theory but you'll be fighting the motion engine acc-/dec-celeration, show it on a real machine
p is the proportional gain of the controller, ff is feed forward. https://en.wikipedia.org/wiki/PID_controller#Feed-forward show it on a real machine? look at any stepper machine running linuxcnc, softstepping or with fpga. both work the same. there is no fighting between the limits, other than clock drift. you usually set the hardware limits few % higher than the machine limits to account for clock drift. p ff controller in linuxcnc: https://github.com/LinuxCNC/linuxcnc/blob/master/src/hal/drivers/mesa-hostmot2/stepgen.c#L84-L193 bit that transfers that stuff to the powerstep registers(code from the video): https://github.com/rene-dev/netbob/blob/master/Src/hm2_dspin.c#L21-L55
won't the powerstep01 adhere to the programmed max acceleration programmed so if you program different speeds for different axis they will reach the programmed speed at different time and tend to do "dog leg" moves?
dSPIN_Run_chain(dir, speed, STEPGENS);//0x50
It seems that that code is not using STEP01 to go to an APOS using internal accel but directly setting step speeds with command 0x50. So it is doing a similar thing to GRBL: creating sequence of constant speed segments to produce a stepwise approximation to the acceleration. ie it also "defeats the purpose of the motion control engine."
If I was going to the trouble of setting up a PID type control system I would not be do it to running open loop steppers. I'd put encoders on the axes, run servos and "do it properly". With hindsight I would have done my current project that way.
You neither understand the problem, nor why my solution works, and is much easier than what you are doing.
It would be helpful if you said who you replying to and what exactly you are referring to. Setting up a PID or p-ff control is not "easier" than using well tested GRBL code. We have not seen "your solution" you linked a lame video and then referred to LinuxCNC code, which does not seem to use the STEP01 internal motion engine but a piecemeal stepwise accel like GRBL. If you disagree with that, say why.
the 2 bits of lame code I linked is what drives the lame steppers in the lame video.
let me explain how the hardware(fpga) stepgen with linuxcnc works. the linuxcnc planner runs at 1 khz, and outputs position and velocity. the velocity is used to clock a timer in an fpga, connected to pci or ethernet. thats the ff term. in theory you would be done here. but in practice the positions will drift slowly, due to the different clock domains. Thats where the p term comes in. So you check where the timer actually is, vs where you expect it to be, and correct the velocity command.
I just replaced the fpga with a stm32 with ethernet, and the timer with the velocity command in the powerstep. the stm32 takes a velocity at 1 khz via ethernet, and returns the position. linuxcnc does the rest.
Thats basically how any velocity mode servo drive in any cnc machine since 1980 is controlled. Please stop saying that it doesn't work.
I dont know the grbl code, but there should be some more or less fixed period which runs the planner. just take its velocity output, put that in the powerstep, and then check the position error, multiply by a constant, and add that to the velocity. thats it.
I did not say the code was lame. My original criticism of the YT vid stands. I've seen a thousand like it.
In control terms, I don't see a great difference between GRBL running constant velocity segments via step pulses and doing the same thing by sending velocity commands via SPI except the latter will add some extra jitter to the timing.
Please stop saying that it doesn't work.
Please stop saying I said something I did not without quotes justifying your claims.
There are other GRBL derivatives like TinyG and Smoothieware which do variable accel profiles and position calculation correction ( not position f/b ) . GRBL is simply by design; uses fixed accel and does not need position correction.
I would like to implement non fixed accel though that it not a priority issue on the current machine. Looking at the linuxCNC code may be useful. Thanks for bringing it to my attention.
PID controllers need tuning and parameter setting to the target. This is non trivial to get it reliable. If was to go to that effort I would probably not bother on open loop stepper control but implement ACTUAL position feedback using encoders.
thousands like it? I am very interested, as I have not seen anything like it. show me. I only found this guy, he controls them via spi on from a pi. https://github.com/dabit20/rpi_cnc/blob/master/linuxcnc/modules/dspin.c#L875-L910 with the same method that I use. here is the p ff controller: https://github.com/dabit20/rpi_cnc/blob/master/linuxcnc/modules/dspin_test.hal#L13-L18
the PID controller does not need tuning. ff1 has to be 1, and you only need a bit of p. you can calculate that. once set up it will never change, as you are not really controlling anything unpredictable. you only compensate the drift, which is very small.
using an encoder for that will not help, as it will increase the speed with more error, which does not help. You need to increase the current, and align the field properly to keep the torque. All those closed loop steppers available from china only monitor lost steps. to do closed loop steppers properly and operate them like servos, you need a completely different driver, and use field oriented control. Thats something else Im working on, but its not finished yet. sorry, I dont have a video. https://discourse.odriverobotics.com/t/foc-driven-hybrid-stepper-motor/255/10 but thats a completely different problem. I would still run a closed loop stepper in velocity mode.
you are right, it is basically the same. but the point is, you dont need to generate the steps. and you are wrong about the jitter. the powerstep by default uses a 4Mhz clock, giving a step resolution of 250ns. And you can increase the clock. the fpgas used with linuxcnc use a 80 Mhz clock. what sort of jitter can you get with grbl?
this is getting way off topic, this is a port of GRBL so it works like GRBL.
Thanks, by thousands like it I mean videos of people's bench tests with no technical description or written information to allow reproduction or understanding of what was done; how it was done which would make it useful. I explained that in my original comment .
The alternative to open loop steppers does not imply closed loop steppers. Servos with conventional motors would make more sense. Isn't that what stmbl is about?
you are wrong about the jitter.
If you interrupt the control loop to send a serial command to change the driver speed you have no control over exactly when the next motor step will happen. That will by definition introduce more jitter. You can then try to measure whether it is significant but it will happen.
as you are not really controlling anything unpredictable.
Mechanical resonances are unpredictable and amongst other things will depend on machine rigidity, axis position; mechanical load: the work-piece shape, material, tool shape, feed rates etc. They cannot realistically be calculated in advance. Calculations are merely a starting point.
I did provide links to all the source code. its not in the video, the video was not made for you, but for the guy I am designing this for. That code was already used successfully by other people.
I am not interrupting any control loop. I know exactly when they go to the new speed, as I am commanding that. And yes, they all do that at the same time, as they are daisychained.
you are wrong about resonances and stuff. The feedback of the controller is not the actual position, its the timer value/abspos register. That changes even without any motor connected. The purpose of the controller only to compensate the drift, nothing else. Its all open loop.
this is getting way off topic, this is a port of GRBL so it works like GRBL.
As langwadt says, this is way off topic for the context of this port of GRBL. Not much point in discussing every aspect of CNC control here. Since what you are doing does not seem to use the internal motion engine any more than this port , I don't think it is directly relevant.
GRBL does not have any drift.
When I get the opportunity to improve on GRBL's fixed accel code, I will look at stmbl . Thanks for the link.
your answer proves again that you neither understand the problem, nor why or how my approach works, or even how the different parts in grbl/any motion controller work together. Keep doing it your way, or the grbl way, I will keep quiet now. Sorry to bother you.
Hi,
I've been debugging using your code on IHMO3A1. I wondered why you set TIM2 running straight away and then used a global to keep track of whether GRBL needs step pulses created.
why was that needed?
thx