Welcome to the Parallax Discussion Forums, sign-up to participate.

# Help, Please. Generate multi phase sine wave.

• Posts: 1,981
edited 2019-02-03 - 02:46:55
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
• Posts: 3,990
• Posts: 1,981
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.
• Posts: 13,561
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  ０ １ ２ ３ ４ ５ ６ ７ ８ ９
VOHGA Ｈ Ｈ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｈ
VOHGB Ｌ Ｈ Ｈ Ｈ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ
VOHGC Ｌ Ｌ Ｌ Ｈ Ｈ Ｈ Ｌ Ｌ Ｌ Ｌ
VOHGD Ｌ Ｌ Ｌ Ｌ Ｌ Ｈ Ｈ Ｈ Ｌ Ｌ
VOHGE Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｈ Ｈ Ｈ
VOLA  Ｌ Ｌ Ｌ Ｌ Ｈ Ｈ Ｈ Ｌ Ｌ Ｌ
VOLB  Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｈ Ｈ Ｈ Ｌ
VOLC  Ｈ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｈ Ｈ
VOLD  Ｈ Ｈ Ｈ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ Ｌ
VOLE  Ｌ Ｌ Ｈ Ｈ Ｈ Ｌ Ｌ Ｌ Ｌ Ｌ

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.
• Posts: 1,532
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
"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".

Larry

If the grass is greener on the other side...it's time to water your lawn.
• Posts: 56
Something I came across.

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.
• Posts: 1,981
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
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
• Posts: 22,341
edited 2019-02-03 - 22:16:26
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       ph0pin,phase0
shr       ph0pin,#16
and       ph0pin,#\$ff
mov       ph1pin,phase0
shr       ph1pin,#8
and       ph1pin,#\$ff
and       phase0,#\$ff
mov       phase1,phase0

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

cmp       phase0,#sine+250 wz
if_z  mov       phase0,#sine
cmp       phase1,#sine+250 wz
if_z  mov       phase1,#sine
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      \$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      \$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      \$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      \$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

clkpin        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.)

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
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
• Posts: 13,561
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.

• Posts: 22,341
edited 2019-02-03 - 22:33:21
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
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
• Posts: 56
Thank you for both.
• Posts: 5,852
edited 2019-02-04 - 02:50:32
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.

Novel Solutions - http://www.novelsolutionsonline.com/ - Machinery Design  -  Product Development
"Necessity is the mother of invention." - Author unknown.

• Posts: 1,981
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.
• Posts: 13,561
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
• Posts: 22,341
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.

"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
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
• Posts: 13,561
...
"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."

• Posts: 22,341
edited 2019-02-04 - 04:17:54
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
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
• Posts: 13,561
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/
• Posts: 1,532
edited 2019-02-04 - 20:11:39
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.)
Larry

If the grass is greener on the other side...it's time to water your lawn.
• Posts: 525
Question - why can't you just use 5 cogs and time it out to get the frequency you need?
• Posts: 13,561
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.
• Posts: 5,852
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.

Novel Solutions - http://www.novelsolutionsonline.com/ - Machinery Design  -  Product Development
"Necessity is the mother of invention." - Author unknown.

• Posts: 1,532
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.
Larry

If the grass is greener on the other side...it's time to water your lawn.
• Posts: 56
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])
______________________________________________________________________________________________
• Posts: 1,051
No way to tell until you post as code since cannot see indentation.
Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
• Posts: 1,981
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
• Posts: 56
Thank you, Mark_T
• Posts: 56
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?
mov ph0pin,phase0
shr ph0pin,#16
and ph0pin,#\$ff
mov ph1pin,phase0
shr ph1pin,#8
and ph1pin,#\$ff
and phase0,#\$ff
mov phase1,phase0

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

cmp phase0,#sine+250 wz---Why add 250 to sine?
if_z mov phase0,#sine
cmp phase1,#sine+250 wz
if_z mov phase1,#sine
jmp #main_lp
________________________________________________________________________________________________

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

-Phil
Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
• Posts: 1,981
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)