[PSR] PWM on new boards
Pavel Pisa
pisa at cmp.felk.cvut.cz
Tue Jan 2 00:08:20 CET 2018
On Saturday 30 of December 2017 14:25:19 klapajar at fel.cvut.cz wrote:
> > Good afternoon,
> > I would like to ask for some help on the matter of PWM on new
> > boards. This question appeared after a long time of me trying to
> > find some >information on this issue or a manual.
> > The question is well described for the old boards but the situation
> > is a bit different with the new ones. I have taken it the way that I
> > would have control of the motor if PWM_ENABLE is set to 0,
> > PWM_B_DIRECT and PWM_A_DIRECT to 1, PWM_PERIOD to 5000 and
> > DUTY_DIR_B and DUTY_DIR_A changing oppositely from 0 to 1 depending
> > on polarity of width and DUTY is set to any width less than period,
> > it will work somehow. Apparently, it doesn't.
> > I would appreciate any hints or a manual.
> > Thank you in advance.
> >
> > -- Sincerely yours, Aleksandra Pereverzeva
>
> Hello,
> in order to make motor spin, try to set CR register to zero
> (especially PWM_x_DIRECT to zero). I think these bits are used to
> generate your own signal without PWM_DUTY register. The rest should be
> correct.
You need to set PWM_ENABLE (control register bit 6) to 1
to control "dcsimpledrv" output peripherals by PWM state
machine implemented in VHDL code.
The option to control PWM outputs directly by control
register bits PWM_A_DIRECT and PWM_B_DIRECT is there
mostly for testing. The PWM_A_DIRECT and PWM_B_DIRECT
controls outputs only when PWM_ENABLE (bit 6 of the control
register) is set to zero (0). But for reasonable filtering
of PWM signals by an inductance of motor windings and to suppress
audible noise, the frequency of PWM should be at least 20 kHz.
Because pulse duty cycle should be controlled at least
at granularity of 1%, then software timing precision
about 500 ns is required to set and clear PWM_A_DIRECT
and PWM_B_DIRECT bits. Such accuracy is very hard to achieve
even in simple MCU with a single task or direct response
to interrupt event. If there should be another task running,
then some task delay function has to to be used,
but granularity of VxWorks timing functions
is defined by tick time, 200 usec min on Zynq.
So the task to generate PWM signal with required parameters
by software is not achievable.
That is why "dcsimpledrv" peripheral provides hardware
to generate periodic PWM signal PWM_PERIOD defines period
of the signal with the granularity 10 nsec given by peripheral
AXI bus clock 100 Mhz. Then the duty cycle is controlled
by bits 0 to 29 of PWM_DUTY register. A bit DUTY_DIR_B
(bit 31) and DUTY_DIR_B (bit 30) then controls to which
half of H-bridge is the generated PWM signal fed.
If both signals are enabled then both outputs
change synchronously and difference voltage is zero
so the effect on motor is same as if both halves are
switched off except for switching power loses caused
by semiconductors and wiring capacitances and need to
drive MOSFET gate and overcome Miller charge.
Usable combinations are "0,0" for zero action, "0,1"
for one direction and "1,0" for another.
For those who like more complete source code than the description
there are complete VHDL sources of the "dcsimpledrv" peripheral
peripheral which can be found on branch "microzed_apo_psr"
of the "canbench-sw" repository
git clone git://rtime.felk.cvut.cz/fpga/zynq/canbench-sw.git
git checkout microzed_apo_psr
the "dcsimpledrv" peripheral AXI bus component is located in subdirectory
"/system/ip/dcsimpledrv_1.0/hdl". You can browse it directory on the web
https://rtime.felk.cvut.cz/gitweb/fpga/zynq/canbench-sw.git/tree/refs/heads/microzed_apo_psr:/system/ip/dcsimpledrv_1.0/hdl
Registers which are writable and have effect on the peripheral
state are routed out from AXI peripheral by assignments starting
from the line 450
450 -- CR
451 irc_reset <= slv_reg0(8);
452 pwm_direct_a <= slv_reg0(4);
453 pwm_direct_b <= slv_reg0(5);
454 pwm_enable <= slv_reg0(6);
455
456 slv_reg0_wmask <= x"00000170";
457
458 -- STAT
459 slv_reg1 <= (8 => irc_a_mon, 9 => irc_b_mon, 10 => irc_irq_mon, others => '0');
460
461 -- PWM_PER
462 pwm_period <= slv_reg2;
463
464 slv_reg2_wmask <= x"3fffffff";
465
466 -- PWM_DUTY
467 pwm_duty <= slv_reg3;
468
469 -- IRC_POS
470 slv_reg4 <= irc_pos;
471 -- User logic ends
Actual PWM A and B signals (for positive and negative H-bridge output polarity)
are controlled by section
271 PWM_A <= (pwm_direct_a and not pwm_enable) or pwm_a_gen;
272 PWM_B <= (pwm_direct_b and not pwm_enable) or pwm_b_gen;
in the component top level VHLD file
https://rtime.felk.cvut.cz/gitweb/fpga/zynq/canbench-sw.git/blob/refs/heads/microzed_apo_psr:/system/ip/dcsimpledrv_1.0/hdl/dcsimpledrv_v1_0.vhd
If a "pwm_enable" signal is negated then direct signals are fed
to outputs and PWM state machine is forced to reset state.
When "pwm_enable" signal is asserted then PWM state machine
controls outputs. There is mapping of the PWM state machine
to the signals of the top level source
249 bidir_pwm_inst: bidir_pwm
250 generic map (
251 pwm_width => 30
252 )
253 port map(
254 clock => fsm_clk,
255 reset => pwm_reset_rq,
256 pwm_period => pwm_period(29 downto 0),
257 pwm_duty => pwm_duty(29 downto 0),
258 dir_a => pwm_duty(30),
259 dir_b => pwm_duty(31),
260 pwm_a => pwm_a_gen,
261 pwm_b => pwm_b_gen
262 );
The PWM state machine is implemented in the file
https://rtime.felk.cvut.cz/gitweb/fpga/zynq/canbench-sw.git/blob/refs/heads/microzed_apo_psr:/system/ip/dcsimpledrv_1.0/hdl/bidir_pwm.vhdl
The "dir_a" and "dir_b" signals are kept together with
the "pwm_duty(29 downto 0)" in the single peripheral register
to enable atomic change of the duty value and direction
(enable bits). Actual state machine is implemented such
way that if duty is changed asynchronously to the signal
generation then if change is done during active time interval
of the pulse then pulse can be prolonged or shortened (even cut)
immediately. If the direction is changed then the signal
output is negated immediately and the correct signal starts
with proper direction in the next period.
This solution requires more hardware resources than
solution with simple value match/equality compare
(n x 2-input xor and n-input nor) because
full adder (in the fact substract) unit has to be
used. But if the equality comparison is used then
the the duty and directions (and ideally even period)
has to be stored at each period start to ensure that
the value is not changed to the value below actual
counter state because in such case the match is missed
and instead of shorter pulse full fill is generated
for that one period. The registering of requested values
is no problem for serious design where complete
motor control is synchronized with PWM timing.
But for the case, when there are expected users
experimenting with PWM period registers and duty
register and flexibility of PWM period register
allows to set period to maximal value of 10 seconds
(2^30)/100e6 then keeping single parameters for whole
period can lead to confussion.
Best wishes,
Pavel Pisa
More information about the PSR
mailing list