Shop Learn
Idea for motor driver, ADC PWM control loop - Page 2 — Parallax Forums

Idea for motor driver, ADC PWM control loop



  • ManAtWork wrote: »

    Another nice design! Congrats.
  • Cluso99Cluso99 Posts: 17,419
    edited 2020-12-21 23:33
    ManAtWork wrote: »
    Nice board :)

    Never seen this in my 50 years in electronics. 1000uF and above were regularly used in power supplies (and still are btw). Possibly exceeded the rating by putting more than 10VDC (peak) on it - that'll do it!
  • Tantalum capacitors are even more fun when they go boom...
  • Cluso99 wrote: »
    ManAtWork wrote: »
    Nice board :)

    Never seen this in my 50 years in electronics. 1000uF and above were regularly used in power supplies (and still are btw). Possibly exceeded the rating by putting more than 10VDC (peak) on it - that'll do it!

    Indeed, very nice boards.

    The reason I mentioned this 1000uF/10V case was meant as a real life example of what might happen if one is abusing a design. This particular explosion happened by accident when I connected double the input voltage to the Graetz bridge (you surely remember these old transformers with split winding in the middle... :)). After that I did some controlled testing and these 10v caps proved to work fine abused up to 16 or so Volts.
  • I don't worry much about somebody burning the board by false connections. Those power stages are indeed quite robust against all sorts of abuse. If you use a switch mode supply with current limit nothing serious happens even if you connect it with the wrong polarity or exchange power and motor terminals. The reverse diodes of the MOSFETs limit the voltage to ~2V and can withstand>10A for some seconds. So the electrolytic cap won't blow unless you connect a big tranbformer or mains AC voltage directly. And even then all that happens is the shunt resistor in the DC link (R3) acts like a fuse. Usually, customers who damage a board like this immediately see and admit their error. If not I can spot it easily.

    The bigger problem is when something I sell doesn't work as expected without emmitting smoke. This generates support cases and I end up spending all my time debugging someone else's mess. I've seen a lot of electrical cabinets of home built machines that look like wire spaghetti (and, surprise... don't work). That's fun to watch as long as they don't blame me. :blush:

    So what I do worry about are the rules that need to be followed with analogue circuitry like star grounding, shielding, avoiding crosstalk or false feedback and so on. People that have nerver worked with analogue power amlifiers usually don't understand them.
  • MaciekMaciek Posts: 245
    edited 2020-12-22 19:21
    It's all crystal clear. A real product and an accessory board for development/testing are entirely different beasts.

    I would think if I buy a real product it should just work provided the requirements for its proper use are met - you know how to deal with that, I am sure :).

    On the other hand, if I buy a dev board, I assume it was tested and worked as expected before I touched it (in some cases it is possible to prove the board works, in some others it's not so obvious). If I use it in a right way it'll still work fine but if I abuse it or do something really stupid with it it is entirely my responsibility. There is not much you can do to prevent abuse but you may make the customer aware that you will not accept the responsibility for such things. If I do not like the rules, I do not buy.

    "People that have never worked with analogue power amplifiers usually don't understand them. " - true, but with such dev/test boards they get a chance to actually experience some of the things they should have read about before even starting :). Again, its their responsibility to gain some knowledge before attempting any testing, I would say.

    In short - a real product - a warranty of some sort; a dev/test board - no warranty, not even implied and no liability for whatever events/consequences associated with the board if it is legal (in some countries it might not be). Harsh, but simple.
  • Ok, I'm probably in the wrong business. Dealing with industry customers makes you careful and scary...

    So I totally agree.... a little bit less complaining and a little bit more action, please.
    Here we go:
    pull the plug of my telephone line - check!
    load FlexProp, look up all the thinks I've forgotten in the last two months of programming abstinence (PC and ARM don't count) - check!
    make some stupid mistakes, again, and find them - check!
    Finally get some results...

  • Absolutely wrong!

    You are in the right business and what we see above proves it without a doubt. Being careful is highly advisable and (in most cases) pays off. Saves a lot of trouble.

    Thanks for sharing.
  • The first demo runs without current feedback. The CORDIC is used to calculate sin/cosine waveforms which are output at a constant rate. And because the overcurrent protection isn't active yet I didn't dare to use a bigger supply with more than 24V.

    I've hoped that I cound use a single cog for handling all the ADC inputs. But that doesn't seem to work. Filtering and demodulation of a single input takes something like 13 instructions. I have to process 16 inputs for 4 motors so that would be more than 256 clocks. If I switch to 512 clocks sample time I have only 16 samples per PWM frame left. As I have to ignore 3 samples after each PWM state change that's not much.

    Maybe I can process the ADC inputs in the background as interrupt. If I dedicate one cog per motor that would take around half the computing power of each cog.
  • Yes interrupts could help. Are you using the hardware sinc filtering?
  • I'm still not sure what filtering mode I should use. SINC3 should give the best resolution but adds some complexity and time lag. I think I have to try all 3 possibilities from simple averaging to SINC3 to find out which one gives the best compromise of noise and resolution vs. response time.

    At low speeds low noise and high resolution are important. I can average over multiple samples becauise PWM is near 50% so that should be no problem.

    The most critical situation is when the duty cycle is just around 90% (I never get to 100% because the boost capacitor of the MOSFET drivers needs charging and that results in a minimum off-time). Then I only have one or two samples left.

    Plain averaging is probalby better than SINC filtering because I get more samples.

    I've watched the Zoom presentation, yesterday. Chip showed some example code using an interrupt to read the ADC. It looks like it's really not much overhead so it should be possible with interrupts.
  • Today I did something completely different but still related to this project. I'm too lazy to write test code that produces stimuli with varying speed so I just connect the driver to one of my existing CNC controllers.

    The step/dir input already works well. Theoretically it could be done completely in the smartpins. There is an up/down counting mode. But I also want timing information to calculate speed with good resolution. The period measurement modes are not good for this because they mess up when direction changes or the timer overflows at very low speed.

    So I dedicate a cog to take care of the time capturing.
    handles step dir inputs for up to 4 axes. Not only pulses are counted
    but also a timestamp is recorded at each counter change so that
    velocity or frequency can be calculated by dp/dt =
    number of pulses (delta position) divided by elapsed time (delta time) 
    between first and last pulses.
    Frequencies up to sysclk/2 can be counted but timestamps are accurate
    to ~1/4µs (one loop iteration) only.
      pinDir0  = 0
      pinStep0 = 1
      pinDir1  = 2
      pinStep1 = 3
      pinDir2  = 4
      pinStep2 = 5
      pinDir3  = 6
      pinStep3 = 7
      allPins  = 0 ADDPINS 7
      long	position0
      long	timestamp0
      long	position1
      long	timestamp1
      long	position2
      long	timestamp2
      long	position3
      long	timestamp3
      ' position counters and timestamps are stored interleaved so they can be read 
      ' in an atomic way with setq/rdlong for each axis
      byte	cog
    PUB Start ()
      cog:= cognew (@stepDirCode, @position0) + 1 ' @position0 into PTRA
    PUB Stop
      if cog
        cogstop (cog~ - 1)
    						fltl	#allPins		' reset smartpins
    						wrpin	mode_updown,#pinStep0
    						wrpin mode_dir,#pinDir0
    						wrpin	mode_updown,#pinStep1
    						wrpin mode_dir,#pinDir1
    						wrpin	mode_updown,#pinStep2
    						wrpin mode_dir,#pinDir2
    						wrpin	mode_updown,#pinStep3
    						wrpin mode_dir,#pinDir3
    						wxpin	#0,#allPins	' no period, continous
    						drvl	#pinStep0		' enable smartpins
    						drvl	#pinStep1
    						drvl	#pinStep2
    						drvl	#pinStep3
    						rdpin pos0,#pinStep0
    						cmp   last0,pos0 wz
    		if_nz		getct time0
    						mov   last0,pos0
    						rdpin pos1,#pinStep1
    						cmp   last1,pos1 wz
    		if_nz		getct time1
    						mov   last1,pos1
    						rdpin pos2,#pinStep2
    						cmp   last2,pos2 wz
    		if_nz		getct time2
    						mov   last2,pos2
    						rdpin pos3,#pinStep3
    						cmp   last3,pos3 wz
    		if_nz		getct time3
    						mov   last3,pos3
    						setq	#7
    						wrlong pos0,ptra
    						jmp   #loop
    mode_updown	long	P_MINUS1_B | P_SCHMITT_A | P_REG_UP_DOWN
    ' %0111_0000_000_0011000000000_00_01101_0 ' pin B = pin A - 1
    mode_dir		long	P_SCHMITT_A ' no smart mode
    last0				long	-1
    last1				long	-1
    last2				long	-1
    last3				long	-1
    pos0				res   1
    time0				res   1
    pos1				res   1
    time1				res   1
    pos2				res   1
    time2				res   1
    pos3				res   1
    time3				res   1
  • For reasons described here I had to implement my own version of a symetrical (triangle) PWM mode. This works well by triggering a timer interrupt 100 cycles before the end of the current PWM frame and then inverting the output pin polarity and setting output enable to float at the same time. The smart pin interrupt (set event on pin rise) happens shortly after the PWM Y register has been captured and sets the output to enabled again. So the output floats for half a microsecond to avoid glitches.

    ADC sampling with SINC3 filtering also works well. I get only +/- 2 digits noise at 12 bit resolution from a single 256 clock sample. So thats better than 10 bit accuracy with almost no noise without any averaging.

    I still have to sort out the timing of the AC demodulation (synchronous rectification) with blanking to mask out the invalid samples (due to filter settling).

    Thanks to Chips DAC presentation yesterday I was also able to successfully setting up a smart pin for the overcurrent comperator.
  • OK, the demodulation finally works and I can run the motor with closed loop current control. Park and inverse Park transformations for a rectangular coordinate system (2 phase stepper motor) are absolutely trivial with the P2 and only take a single QROTATE instruction each.

    My first approach used a variable length averaging filter. It (hardly) worked but I had problems with its complexity. I have replaced divisions by multiplications with the inverse from a 1/x lookup table to speed the math up. But the variable sampling window caused a variable phase shift and caused ripple when switching over from one ADC input to another and the motor ran quite noisy.

    Now I switched to a fixed and shorter sampling window, only 2 samples per PWM frame. The SINC3 filter mode gives quite good resolution (~12 usable bits at 256 cycle samples) so further averaging is not neccessary.

    I think I can even go without VIO/GIO calibration. The AC coupling cancels out any offset errors and the gain errors from pin to pin seem to be quite low (the resistor ratios on the chip match better than the transistor threshold voltages).
  • Excellent news.

    From what I understand, you're almost done with this stepper motor driver. Congratulations !

    Slightly off topic, but please allow me to ask why a stepper motor and not a three phase BLDC ? Possibly with an encoder of some adequate sort for precise control ? Or maybe you are done with that one too but never mentioned it ?
    That wouldn't surprise me at all :).

    The reason I'm asking is that industrial, real robots I came across mostly use the 3-phase BLDC ones (for torque characteristics and precision, I suspect, and for some other reasons as well).
  • For bigger machines or if high speed and high precision are required, servo motors (3-phase synchronous AC motors) are the better choice because they have higher efficiency and higher power density. But for smaller machines (3d printers, CNC routers...) stepper motors still can't be beaten because of their simplicity. You only need 4 wires, no encoder, no tuning.

    I've already built a servo driver with the P2 (see this thread). The hardware works but the software especially for tuning is a still uncompleted task.

    I think a simple but powerful driver for stepper motors would be a good demo of what the P2 is capable of. It doesn't need expensive components or high voltage so I think it has much more the potential for a "killer application". Futhermore, I'll soon need a replacement for my old (P1 based) stepper drives. They become 10 years old and instead of a partial redesign to replace EOL components I prefer making a real improvement.
  • Well "almost done" is a bit optimistic. I'd say I managed to prove that the original idea was feasible and the decicion to develop a real product out of it can be made. But there is still a lot to do. The low speed range where the motor runs under closed loop current control is only one part of the game. With increasing speed the PWM outputs begin to saturate. The supply voltage is no longer high enough to overcome the back EMF plus impedance (frequency dependent resistance) of the motor. The motor can still be run at higher RPMs but with decreasing torque. In this range the motor runs in "voltage mode". Seamless blending between the two ranges is the real "art" of driving stepper motors.
  • That "almost" was not put in there accidentally :).

    It is optimistic, yes, but it is also based on good grounds. I tend to be optimistic when it comes to recognizing somebody else's achievements and not so much at all when it comes to my own. Also, for a good reason :) .

    I think for a "killer application" demo it is good enough already at its present state.

    For an industrial quality stepper motor driver you are absolutely right, especially if you want to use it in your own pick and place machine :) but I am confident it is only a matter of time when you get there.

    Please, keep posting as this is very interesting stuff.
  • Hi
    Please, keep posting as this is very interesting stuff.


  • Cluso99Cluso99 Posts: 17,419
    tritonium wrote: »
    Please, keep posting as this is very interesting stuff.



  • Next step is the high speed part. Stepper motors running well above their corner frequency (usually >1200RPM or 1000Hz at the windings) are driven best with rectangular waveforms (same as full step mode). I thought I could also do this by clever adjustment of the PWM duty cycle values. But I need a different switching pattern.

    This is used at low speed:
    The triangle mode with alternating up/down counting has the advantage that the effective winding voltage and ripple current have double the switching frequency. This results in lowest possible switching losses and noise above the audible range.

    At high speed we have a different situation:
    The amplitude is saturated, this means the duty cycle is 100% for all frames except those containing a zero crossing. The zero crossings have to be carefully synchronized to the step input signal because the switching frequency can be a shigh as ~1/4 of the PWM frame rate meaning there's a zero crossing almost every 2nd frame. Wrong timing would lead to jitter or unwanted DC voltage.

    The difference is that for the low speed case both half bridges always switch in the same direction (rising or falling edges) inside one frame. In the high speed case both outputs switch in the opposite direction.
    569 x 170 - 3K
    570 x 175 - 3K
  • Just for an estimate how much board space would be required I pasted four of the accessory board layouts into one plus the components of the KISS eval board. Everything seems to fit well onto a 100x80mm board. This is about the size of one MD556 drive. If everything works (and there is still an "if") then this could drive four motors with 5A and 48V each. BOM cost is still <$25 but will increase a bit as I add some relays and interface logic.
    804 x 899 - 97K
  • MaciekMaciek Posts: 245
    edited 2021-01-07 17:45
    So, if I understand all this correctly, the most difficult part of the software driver would be to correctly determine the moment the transition between the low speed and high speed modes should occur and make that transition as smooth as possible for both the hardware driver and the motor itself. That may sound easy enough but when I think of the little details that come to play I think it's quite the oposite. This is all new (but fascinating) stuff to me so I may be wrong as well.
    The question that comes to my mind is this - what might be a real advantage of pushing the stepper motor to its high limit when the performance is sub optimal ? I'm sure there must be something but just can't figure it out at the moment.

    When you say BOM <$25 (plus the slight increase for the extra parts ) do you mean for a four motor driver board ? That would be impressive indeed.
  • Yes, you understand correctly. The most difficult part is the transition from low to high speed. I wouldn't call this "moment" because it has to be a continous fade-over instead of a instanous switch. Otherwise it would cause a click sound in the best and a jerk and stall of the motor in the worst case.

    What do you mean with "performance is sub optimal"? Yes, a stepper has decreasing torque with increasing speed. But that's ideal for CNC positioning applications. You need the highest force at low speeds when your tools are actually cutting. When doing rapid moves you only travel "through the air" and don't need much power.

    Yes, $25 for a four motor driver. Of course, this is not the end user price. It has to be produced, tested and sold (the dealer wants some profit). And we need a case, heatsink, terminals and so on. But even $100 would be quite competitive.
  • Thanks ManAtWork.

    The "moment" was a shortcut that I shouldn't really use and I'm glad you pointed that out. After all, we're engineers and we should express ourselves precisely :). I understand that the transition has to be continuous for reasons you described.

    You've just answered my question - I haven't thought of that but felt there must be something and indeed, I should have thought of the whole application and not just the stepper motor itself. I was under the impression the more flat torque vs speed characteristic the better hence my question.

    You said BOM and I meant BOM, not the total cost for the customer so that one at least I got right and I agree, even at a $100 for a complete product would be a rather attractive price.
  • So this is my plan:

    Case 2 (low speed) and case 3 (medium speed) show the same detail of the motor voltages, a slightly positive average voltage crossing the zero line in the middle and becoming a slightly negative average voltage.

    The difference is that in case 2 all PWM counters alternate between up and down counting at the same time. In case 3 counter 2 flips its direction in frame #2. This inverts the output of half bridge 2 and results in much wider voltage pulses at the motor winding. But the average voltage stays the same. So the pattern switching can be done without much disturbance.

    The key is that the duty cycles in frame #2 of case 3 are voltage-driven (goal is smooth average voltage) whereas the duty cycles in frame #2 of case 4 are time-driven (goal is exact phase shift of the square wave). As both numbers are a continous values it is possible to "blend" between them by weighted multiplication with a "fading slider" parameter. In contrary, the PWM counter direction and output polarity is a yes/no decision and no fading is possible.
    558 x 765 - 11K
  • To make the typical stepper noise softer and avoid vibrations in the frequency range where mechanical resonances occur (10..100Hz) I've experimented a bit with filters. The idea is to low-pass filter the step input with an adaptive filter where the cut-off frequency follows the input frequency. This turns the typical microstepping "minecraft world" (see this waveform) into a nearly perfect sine shape while keeping phase lag (and thus position following error) nearly constant.
      Step/Dir input signals control an up/down counter. Its output is used as an angle.
      Together with the current vector absolute it is used for a polar/cartesian
      transformation to generate (discrete stepped) sine/cosine waveforms as nominal
      values for the winding currents.
      To smoothen out the discrete steps the angle value is filtered with a second
      order low pass filter. This results in a continous velocity and finite
      acceleration. The time constant of the filter adapts to the current velocity
      propotional to the step frequency.
      Velocity is calculated as delta angle per PWM period.
      v = s * p / t
      Can be computed with CORDIC solver QDIV (64/32 bits)
      s = step angle (2^32 = 360° = 1 electrical turn = 4 full steps)
      p = PWM frame period in clocks
      t = time between to consecutive step signal edges in clocks
      3000RPM = 50RPS = 2500Hz (50/s * 50 pole pairs)
      2.5kHz * 4 = 10k full steps per second = ~1/2 full step per PWM frame
      vmin = 1 step/0.25s, tmax = 45_000_000 clocks
      fmax = 2.5kHz * 4 * 64 = 625 kHz (64 micro steps * 3000RPM)
      tmin = 180MHz / 625kHz = 288 clocks
      s*p < ~400*2^32 max @ 1/5 microstepping
      Low pass angle/position filter (RC type, e^-t decay), canonical formula:
      o:= k*i + (1-k)*o
      o = output, i = input, k = filter coefficient
      To avoid trouble with overflows and rounding errors, re-order formula:
      o+= k*(i-o)
      Advantages: term (i-o) never overflows, only one multiplication required
      k = p/(t+p)
      Can be computed with CORDIC solver (QFRAC)
    		setq  spHi
    		qdiv  spLo,deltaT
    		mov   temp,period
    		add   temp,deltaT
    		getqx velocity
    		qfrac period,temp
    		getqx filterK
    		shr   filterK,#16
    		mov   temp,filterI
    		sub   temp,filterO1
    		sar   temp,#16 wc
    		addx  temp,#0
    		abs   temp wc
    		mul   temp,filterK
    		sumc  filterO1,temp ' o1+= k*(i - o1)
    		mov   temp,filterO1
    		sub   temp,filterO2
    		sar   temp,#16 wc
    		addx  temp,#0
    		abs   temp wc
    		mul   temp,filterK
    		sumc  filterO2,temp ' o2+= k*(o1 - o2)
    It's amazing how simple the computations are on the P2. The code that does the same thing on the P1 spans multiple pages and takes all the resources of one cog. I even had to skip filtering at higher speeds to avoid cycle starving.
  • This is an interesting topic. I miss the update, if there is any, that is.
Sign In or Register to comment.