Shop OBEX P1 Docs P2 Docs Learn Events
Help, Please. Generate multi phase sine wave. - Page 2 — Parallax Forums

Help, Please. Generate multi phase sine wave.

2

Comments

  • Mark_TMark_T Posts: 1,981
    edited 2019-02-03 02:46
    bteddy wrote: »
    Thank you for the replies.

    My stepper is a Pentagon 5-wire motor.

    Right, that requires all the outputs to be in step, basically one DDS generated signal controls all the pins.

    As background the standard trapezoidal step pattern is something like:
    1 00111110000011111000
    2 00001111100000111110
    3 10000011111000001111
    4 11100000111110000011
    5 11111000001111100000
    
    On each step one winding goes high or one winding goes low, snaking around the 5 phases.
    I'd recommend first tackling this as it will prove the rest of the hardware and is much easier to
    get working in the first instance.

    sinusoidal PWM involves synchonizing 5 PWM clocks and providing duty cycles of the form

    50% + amplitude% * sin (phase)

    The synchronization is required with a 5-wire motor as the windings cannot be independently
    driven. The amplitude controls the strength of drive (there is no equivalent to this with trapezoidal
    drive method).

    Note that is amplitude is zero, all the PWM channels are at 50% duty cycle and exactly in phase.
    The windings see no drive at all in this condition.

    So on every PWM cycle you need to provide a new sin(phase) value to each PWM cog that are 72 degrees
    apart. A DDS loop can dole out the values, using a sine lookup table (alas the ROM table is probably too slow
    to use for 5 waveforms, a complete 360 degree table that's a power-of-two in size in RAM is the way
    to go.

    Scaling by the amplitude involves a multiply - that's best farmed out to the PWM cogs to share the
    workload.
  • BTW in case its not obvious 5 phase PWM control is analogous to 3 phase control, you just replace 3 by 5 and 120 degree by 72 degree, so any 3-phase code can be adapted.
  • jmgjmg Posts: 15,140
    Mark_T wrote: »
    ...
    As background the standard trapezoidal step pattern is something like:
    1 00111110000011111000
    2 00001111100000111110
    3 10000011111000001111
    4 11100000111110000011
    5 11111000001111100000
    
    On each step one winding goes high or one winding goes low, snaking around the 5 phases.

    The Oriental Motor docs have a slight variant on that, with a 3-on-7 off step mapping, which looks to always have 3 driving.
    Step  0 1 2 3 4 5 6 7 8 9
    VOHGA H H L L L L L L L H
    VOHGB L H H H L L L L L L
    VOHGC L L L H H H L L L L
    VOHGD L L L L L H H H L L
    VOHGE L L L L L L L H H H
    VOLA  L L L L H H H L L L
    VOLB  L L L L L L H H H L
    VOLC  H L L L L L L L H H
    VOLD  H H H L L L L L L L
    VOLE  L L H H H L L L L L        
    
    An “H” represents that the respective MOSFET is active.
    
    

    and there is also this useful chestnut
    "This results in the 2-phase having 200 steps per rotation, 1.8° per step, while the 5-phase has 500 steps per rotation, 0.72° per step. The increased resolution of the 5-phase is inherent to its design. When coupled with a microstepping driver, the 5-phase motor can make steps as small as 0.00288°, however, position accuracy and repeatability are still subject to the motor's mechanical accuracy. The mechanical accuracy of both the 2-phase and 5-phase motor is ± 3 arc minutes (0.05°)."

    that Mechanical limit, is Step/14.4, which explains why Microsteps above 32 are not really mentioned.
    It does mean the 256 steps mentioned is outside the scope of these motors, but PhPi's nifty code can manage higher PWM kHz for reduced steps.
  • Mark_T wrote: »

    50% + amplitude% * sin (phase)
    .........................................
    A DDS loop can dole out the values, using a sine lookup table (alas the ROM table is probably too slow
    to use for 5 waveforms, a complete 360 degree table that's a power-of-two in size in RAM is the way
    to go.

    Scaling by the amplitude involves a multiply - that's best farmed out to the PWM cogs to share the
    workload.
    "Sine wave" in the thread title got my attention because I have wondered what it would take to design a variable frequency drive for a three phase induction motor for a possible future project. This looks like good information. I get the sense that I'm going to have to learn about "DDS loops".

  • Something I came across.
    https://www.analog.com/en/analog-dialogue/articles/all-about-direct-digital-synthesis.html

    It is possible to use two single DDS devices that operate on the same master clock to output two signals whose phase relationship can then be directly controlled. In Figure 8, two AD9834s are programmed using one reference clock, with the same reset pin being used to update both parts. Using this setup, it is possible to do I-Q modulation.
    Figure 8
    Figure 8. Multiple DDS ICs in synchronous mode.

    A reset must be asserted after power-up and prior to transferring any data to the DDS. This sets the DDS output to a known phase, which serves as the common reference point that allows synchronization of multiple DDS devices. When new data is sent simultaneously to multiple DDS units, a coherent phase relationship can be maintained, and their relative phase offset can be predictably shifted by means of the phase-offset register.
  • DDS loop:
    loop
        waitcnt time, #delay
        add     phase, frequency  ' phase increment
        mov     ph0, phase
        mov     ph1, phase
        mov     ph2, phase
        mov     ph3, phase
        mov     ph4, phase
        add     ph1, H33333333  ' 5 equally spaced phases
        add     ph2, H66666666
        add     ph3, H9999999a
        add     ph4, Hcccccccd
        shr     ph0, #24         ' take high bits to index lookup table...
        shr     ph1, #24
        shr     ph2, #24
        shr     ph3, #24
        shr     ph4, #24
        ....
        jmp     #loop
    
    Just a phase variable in binary radians and lockstep timing. Use the phase as you like each time
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2019-02-03 22:16
    FWIW, here's a program that outputs analog sine waves 72° apart:
    CON
    
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    
      CLK_PIN       = 6
      PH0_PIN       = 1
      PH1_PIN       = 2
      PH2_PIN       = 3
      PH3_PIN       = 4
      PH4_PIN       = 5
      NO_PIN        = $ff
    
    PUB start
    
      cognew(@wavegen, @group0)
      cognew(@wavegen, @group1)
      cognew(@wavegen, @group2)
      waitcnt(cnt + clkfreq / 10)
      dira[CLK_PIN]~~
      frqa := $10000000
      ctra := %00100 << 26 | CLK_PIN
      repeat
    
    DAT
    
    group0        long      CLK_PIN << 24 | PH0_PIN << 16 | PH1_PIN << 8 | 0
    group1        long      CLK_PIN << 24 | PH2_PIN << 16 | PH3_PIN << 8 | 100
    group2        long      CLK_PIN << 24 | PH4_PIN << 16 | NO_PIN  << 8 | 200
    
                  org       0
    wavegen       rdlong    phase0,par
                  mov       clkpin,phase0
                  shr       clkpin,#24
                  mov       clkmask,#1
                  shl       clkmask,clkpin
                  mov       ph0pin,phase0
                  shr       ph0pin,#16
                  and       ph0pin,#$ff
                  mov       ph1pin,phase0
                  shr       ph1pin,#8
                  and       ph1pin,#$ff
                  and       phase0,#$ff
                  add       phase0,#sine
                  mov       phase1,phase0
                  add       phase1,#50
                  
                  cmp       ph0pin,#NO_PIN wz
            if_nz movs      ctr0,ph0pin
            if_nz mov       ctra,ctr0
            if_nz mov       acc,#1
            if_nz shl       acc,ph0pin
            if_nz mov       dira,acc
            
                  cmp       ph1pin,#NO_PIN wz
            if_nz movs      ctr0,ph1pin
            if_nz mov       ctrb,ctr0
            if_nz mov       acc,#1
            if_nz shl       acc,ph1pin
            if_nz or        dira,acc              
    
    main_lp       movs      loadfrqa,phase0
                  movs      loadfrqb,phase1
                  add       phase0,#1
                  cmp       phase0,#sine+250 wz
            if_z  mov       phase0,#sine     
                  add       phase1,#1
                  cmp       phase1,#sine+250 wz
            if_z  mov       phase1,#sine
                  waitpne   clkmask,clkmask
                  waitpeq   clkmask,clkmask
    loadfrqa      mov       frqa,0-0
    loadfrqb      mov       frqb,0-0
                  jmp       #main_lp
    
    ctr0          long      %00110 << 26    
                  
    sine          long      $7fffffff,$83377685,$866e67e4,$89a44f0c,$8cd8a718
                  long      $900aeb61,$933a9798,$966727da,$999018c3,$9cb4e786
                  long      $9fd51201,$a2f016d2,$a605756b,$a914ae2b,$ac1d426b
                  long      $af1eb49b,$b2188850,$b50a425b,$b7f368dd,$bad38358
                  long      $bdaa1ac6,$c076b9ab,$c338ec28,$c5f0400b,$c89c44e7
                  long      $cb3c8c21,$cdd0a905,$d05830d6,$d2d2bae1,$d53fe08b
                  long      $d79f3d64,$d9f06f39,$dc33161d,$de66d480,$e08b4f3b
                  long      $e2a02d9e,$e4a5197f,$e699bf49,$e87dce08,$ea50f778
                  long      $ec12f00d,$edc36f07,$ef622e77,$f0eeeb4c,$f2696561
                  long      $f3d15f81,$f5269f79,$f668ee1c,$f798174a,$f8b3ea00
                  long      $f9bc3858,$fab0d796,$fb91a02d,$fc5e6dc3,$fd171f3b
                  long      $fdbb96b7,$fe4bb9a1,$fec770a8,$ff2ea7ce,$ff814e5f
                  long      $ffbf5701,$ffe8b7aa,$fffd69ab,$fffd69aa,$ffe8b7a7
                  long      $ffbf56fb,$ff814e57,$ff2ea7c2,$fec7709b,$fe4bb990
                  long      $fdbb96a5,$fd171f26,$fc5e6dab,$fb91a013,$fab0d77a
                  long      $f9bc3839,$f8b3e9de,$f7981726,$f668edf6,$f5269f51
                  long      $f3d15f57,$f2696534,$f0eeeb1d,$ef622e46,$edc36ed4
                  long      $ec12efd8,$ea50f740,$e87dcdcf,$e699bf0d,$e4a51941
                  long      $e2a02d5e,$e08b4efa,$de66d43d,$dc3315d8,$d9f06ef2
                  long      $d79f3d1c,$d53fe040,$d2d2ba95,$d0583088,$cdd0a8b5
                  long      $cb3c8bd0,$c89c4495,$c5f03fb8,$c338ebd3,$c076b955
                  long      $bdaa1a6f,$bad382ff,$b7f36883,$b50a4201,$b21887f5
                  long      $af1eb43f,$ac1d420e,$a914adcc,$a605750c,$a2f01672
                  long      $9fd511a0,$9cb4e725,$99901861,$96672777,$933a9735
                  long      $900aeafe,$8cd8a6b4,$89a44ea9,$866e6781,$83377621
                  long      $7fffff9b,$7cc88916,$799197b6,$765bb08e,$73275883
                  long      $6ff5143b,$6cc56804,$6998d7c2,$666fe6da,$634b1817
                  long      $602aed9d,$5d0fe8cd,$59fa8a34,$56eb5175,$53e2bd35
                  long      $50e14b06,$4de77752,$4af5bd48,$480c96c8,$452c7c4e
                  long      $4255e4e0,$3f8945fc,$3cc71381,$3a0fbf9f,$3763bac5
                  long      $34c3738d,$322f56aa,$2fa7cedb,$2d2d44d2,$2ac01f29
                  long      $2860c251,$260f907e,$23cce99c,$21992b3b,$1f74b082
                  long      $1d5fd221,$1b5ae641,$19664079,$178231bc,$15af084f
                  long      $13ed0fbb,$123c90c3,$109dd156,$0f111483,$0d969a71
                  long      $0c2ea052,$0ad9605c,$099711bd,$0867e891,$074c15dd
                  long      $0643c787,$054f284b,$046e5fb7,$03a19224,$02e8e0ae
                  long      $02446934,$01b4464d,$01388f48,$00d15825,$007eb196
                  long      $0040a8f7,$00174850,$00029652,$00029656,$0017485b
                  long      $0040a909,$007eb1b0,$00d15847,$01388f71,$01b4467e
                  long      $0244696c,$02e8e0ee,$03a1926a,$046e6005,$054f28a1
                  long      $0643c7e4,$074c1641,$0867e8fb,$0997122e,$0ad960d5
                  long      $0c2ea0d2,$0d969af7,$0f111510,$109dd1e9,$123c915d
                  long      $13ed105c,$15af08f5,$17823269,$1966412c,$1b5ae6fa
                  long      $1d5fd2df,$1f74b146,$21992c05,$23ccea6b,$260f9153
                  long      $2860c32b,$2ac02008,$2d2d45b5,$2fa7cfc3,$322f5798
                  long      $34c3747f,$3763bbbb,$3a0fc09a,$3cc71480,$3f8946ff
                  long      $4255e5e6,$452c7d57,$480c97d4,$4af5be58,$4de77865
                  long      $50e14c1c,$53e2be4e,$56eb5290,$59fa8b51,$5d0fe9ec
                  long      $602aeebe,$634b193b,$666fe7ff,$6998d8e9,$6cc5692b
                  long      $6ff51563,$732759ad,$765bb1b8,$799198e1,$7cc88a40
    
    clkpin        res       1
    clkmask       res       1
    ph0pin        res       1
    acc           res       1
    ph1pin        res       1
    phase0        res       1
    phase1        res       1
    
    It uses three PASM cogs and their counters to produce five DUTY-mode outputs. Phase advancements are synchronized to an NCO clock output on P0. I filtered the outputs with an RC filter (1K, 220pF) to produce the following scope trace. (My scope has only four channels, so I couldn't show the fifth channel. But I did verify that it was there and correct.)

    pentaphase.png

    The unfiltered DUTY-mode output changes state way too fast to input to a PWM-style driver. But there are chips that convert analog voltages to a proper PWM signal. Alternatively, one could produce a sawtooth output on another pin and use that with comparators to produce the PWM'd signals.

    -Phil
    640 x 480 - 30K
  • jmgjmg Posts: 15,140
    FWIW, here's a program that outputs analog sine waves 72° apart:

    Very nifty.
    The unfiltered DUTY-mode output changes state way to fast to input to a PWM-style driver. But there are chips that convert analog voltages to a proper PWM signal. Alternatively, one could produce a sawtooth output on another pin and use that with comparators to produce the PWM'd signals.

    There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2019-02-03 22:33
    In case anyone's interested, here's the Perl code that generated the sine table:
    use strict;
    
    foreach my $i (0 .. 249) {
      if ($i == 0) {
        print "sine          long      "
      } elsif ($i % 5 == 0) {
        print "              long      "
      }
      printf "\$%8.8x", int((sin($i * 6.2831854 / 250) * 0.5 + 0.5) * 0xffffffff);
      print $i % 5 == 4 ? "\n" : ","
    }
    

    -Phil
  • Thank you for both.
  • idbruceidbruce Posts: 6,197
    edited 2019-02-04 02:50
    Way back when.... When I was choosing steppers and drivers, I clearly saw that Oriental Motors was going in a proprietary direction.... So I ran the other way, and instead I chose the norm. I would hate to be in your shoes.

    EDIT: Sell those motors and buy normal stepper motors, and you will be glad you did. Just my two cents.
  • jmg wrote: »
    There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
    But not a 5-wire 5-phase motor surely, as the windings are not independent.
  • jmgjmg Posts: 15,140
    Mark_T wrote: »
    jmg wrote: »
    There are also Class-D audio amplifiers and the TI ones spec around 70KHz of power bandwidth, so they might conveniently drive sine voltages into motors.
    But not a 5-wire 5-phase motor surely, as the windings are not independent.

    Well, yes, clearly not from a single channel of Class-D :)
  • idbruce wrote:
    Sell those motors and buy normal stepper motors, and you will be glad you did. Just my two cents.
    Despite the five-phase motors being more complicated to interface and program, I believe they do have an advantage when it comes to smooth running. Mercedes Benz recognized such an advantage when they came out with their 300D (a five-cylinder diesel) many years ago.

    From this article:

    "Depending on your particular application, a 2-phase motor may suffice. However, 5-phase stepper motors offer higher resolution, lower vibration, higher acceleration and deceleration rates (due to smaller step angles), and are less likely to lose synchronization due to overshooting/undershooting than a 2-phase stepper motor. For applications requiring high precision, low noise and low vibration, 5-phase is the better technology."

    -Phil
  • jmgjmg Posts: 15,140
    ...
    "Depending on your particular application, a 2-phase motor may suffice. However, 5-phase stepper motors offer higher resolution, lower vibration, higher acceleration and deceleration rates (due to smaller step angles), and are less likely to lose synchronization due to overshooting/undershooting than a 2-phase stepper motor. For applications requiring high precision, low noise and low vibration, 5-phase is the better technology."

    All of that is true, until you bring micro-stepping to the table.
    Of course, they rather skirt around that, with statements like this
    "Vibration
    Because of the smaller step angles in 5-phase stepper motors, 0.72° versus 1.8° in a 2-phase motor, the vibration in a 5-phase motor is much less than in a 2-phase."


  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2019-02-04 04:17
    And nothing was said in the article about resonance. Two-phase steppers can have terrible resonance characteristics (cogging and losing steps), unless they are physically damped and/or employ clever programming to minimize time spent in the resonance zone. (Maybe even dithering would work here?) I once had to incorporate a spring-loaded cork-and-metal drag mechanism (as in a fishing reel) to dampen out resonance in a stepper drive.

    I do not know how five-phase motors' resonance characteristics compare.

    -Phil
  • jmgjmg Posts: 15,140
    And nothing was said in the article about resonance. Two-phase steppers can have terrible resonance characteristics (cogging and losing steps), unless they are physically damped and/or employ clever programming to minimize time spent in the resonance zone. (Maybe even dithering would work here?) I once had to incorporate a spring-loaded cork-and-metal drag mechanism (as in a fishing reel) to dampen out resonance in a stepper drive.

    I do not know how five-phase motors' resonance characteristics compare.

    -Phil

    Resonance also improves with microstepping. Some nice plots here : https://www.trinamic.com/technology/std-technologies/microstepping/
  • lardomlardom Posts: 1,659
    edited 2019-02-04 20:11
    I had to look up to see what "cogging" was.
    In one of my stepper projects I dealt with the cogging problem by reducing the PWM duty cycle whenever the stepper was rotating slowly or during acceleration/deceleration. I inserted a PNP transistor into the power supply. (Low side NPN did not work.)
  • Question - why can't you just use 5 cogs and time it out to get the frequency you need?
  • jmgjmg Posts: 15,140
    AIman wrote: »
    Question - why can't you just use 5 cogs and time it out to get the frequency you need?

    Of course, that is possible.
    Phil's code could have used one timer per COG, rather than the 2 timers each COGs already has, and consumed 5 COGs instead.
  • Phil
    Despite the five-phase motors being more complicated to interface and program, I believe they do have an advantage when it comes to smooth running.

    Perhaps this is true, but there are always pros and cons to every trade off. To me, simplicity, and readily available, inexpensive parts, are worth there weight in gold. As I have told you before, the best advice you ever gave me, was to purchase some of the readily available PWM stepper drivers. Prior to purchasing those drivers, I was going in circles and wasting a lot of time and money.
  • idbruce wrote: »
    Perhaps this is true, but there are always pros and cons to every trade off. To me, simplicity, and readily available, inexpensive parts, are worth there weight in gold. As I have told you before, the best advice you ever gave me, was to purchase some of the readily available PWM stepper drivers. Prior to purchasing those drivers, I was going in circles and wasting a lot of time and money.
    Absolutely agree: Phil Pilgrim's advice is worth its weight in gold.
  • Hello,

    I have a question.
    In the code below, If "i" (is from 0 to 7), why in "duty" is it only shifted left 6 times not 7?

    Thank you
    ________________________________________________________________________________________
    From PWMx8.Demo.spin

    PUB start | i, duty

    ' Program to demonstrate the pwm_x8 object.

    pwm.start(base_pin, %1111_1111, 23000) 'Setup for PWM output on pins A16 - A23 at 23KHz.
    repeat
    repeat value from 0 to 511
    repeat i from 0 to 7
    duty := ((value + (i << 6)) & 511)
    if duty > 255
    duty := 511 - duty
    pwm.duty(base_pin + i, duties[duty])
    ______________________________________________________________________________________________
  • No way to tell until you post as code since cannot see indentation.
  • 0 to 7 is a 3 bit value. Shifting a 3 bit value left by 6 makes it a 9 bit value, which agrees with the 511 mask
  • Thank you, Mark_T
  • I have been reading thru code/manuals/forum posts and application notes and I am crossed eyed now.
    I am getting there but need a little help.

    Code below. Questions in red.

    Thank You

    ________________________________________________________________________________________________
    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    CLK_PIN = 6
    PH0_PIN = 1
    PH1_PIN = 2---Pin assignments with base 10? Should be binary right?
    PH2_PIN = 3
    PH3_PIN = 4
    PH4_PIN = 5
    NO_PIN = $ff

    PUB start

    cognew(@wavegen, @group0)
    cognew(@wavegen, @group1)
    cognew(@wavegen, @group2)
    waitcnt(cnt + clkfreq / 10)
    dira[CLK_PIN]~~
    frqa := $10000000
    ctra := %00100 << 26 | CLK_PIN----Is this OR'ng 26 and clk_pin
    repeat                                          or binary number shifted left 26 times then OR'ed
                                                         with a base 10 number?



    DAT

    group0 long CLK_PIN << 24 | PH0_PIN << 16 | PH1_PIN << 8 | 0
    group1 long CLK_PIN << 24 | PH2_PIN << 16 | PH3_PIN << 8 | 100---What it this?
    group2 long CLK_PIN << 24 | PH4_PIN << 16 | NO_PIN << 8 | 200---What is going on here?

    org 0
    wavegen rdlong phase0,par
    mov clkpin,phase0
    shr clkpin,#24--\
    mov clkmask,#1----\Why shr/mov/shl when it was done above?
    shl clkmask,clkpin--/
    mov ph0pin,phase0
    shr ph0pin,#16
    and ph0pin,#$ff
    mov ph1pin,phase0
    shr ph1pin,#8
    and ph1pin,#$ff
    and phase0,#$ff
    add phase0,#sine
    mov phase1,phase0
    add phase1,#50

    cmp ph0pin,#NO_PIN wz
    if_nz movs ctr0,ph0pin
    if_nz mov ctra,ctr0
    if_nz mov acc,#1
    if_nz shl acc,ph0pin
    if_nz mov dira,acc

    cmp ph1pin,#NO_PIN wz
    if_nz movs ctr0,ph1pin
    if_nz mov ctrb,ctr0
    if_nz mov acc,#1
    if_nz shl acc,ph1pin
    if_nz or dira,acc

    main_lp movs loadfrqa,phase0
    movs loadfrqb,phase1
    add phase0,#1
    cmp phase0,#sine+250 wz---Why add 250 to sine?
    if_z mov phase0,#sine
    add phase1,#1
    cmp phase1,#sine+250 wz
    if_z mov phase1,#sine
    waitpne clkmask,clkmask
    waitpeq clkmask,clkmask
    loadfrqa mov frqa,0-0
    loadfrqb mov frqb,0-0
    jmp #main_lp
    ________________________________________________________________________________________________

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2019-02-25 07:52
    Put your code between [ code ][ /code ] (without the spaces) tags so we can read it, please.

    -Phil
  • shift binds more tightly than or, its generating bit fields by oring them together, and individual fields
    by shifting them left. Basically most of this code is packing several fields into one long.

    The thing with sine is a table in cog ram, whose first entry has the label sine. The code is traversing
    phase0 & phase1 from sine to sine+250, ie phaseX are register numbers (used by the MOVS instructions
    to modify the instructions that set FRQA and FRQB)
Sign In or Register to comment.