Synchronous PWM stop, or best component to change frequencies?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
ScWi_1017771
Level 2
Level 2
First like given

Hi, looking at a design which uses a PWM to provide timing for a data acquisition subsystem.  The current asynchronous stop / update / start is causing problems.  Is there a way to get synchronous stops / starts under software control?

We need to scan 2 to 7 inputs at 30Hz per input (multiplexer feeding an alarm circuit and a DelSig ADC).  This means providing a variable clock signal at (2 to 7) x 30Hz = 60Hz to 210Hz. 

Each scan period includes:

  • Provide an initial pulse (1st output)
  • Delay 100us
  • Provide a separate pulse (2nd output)
  • Delay 3.2ms
  • Provide a separate pulse (3rd output)
  • Delay to the end of the 60..210Hz sample period

This means changing the divisor to provide 60Hz to 210Hz, preferably with synchronous update:  when changing frequencies, we need:

  1. The current cycle to complete, THEN
  2. Update divisors and compare values, THEN
  3. Begin the next cycle using the new values.  

Currently, the API only supports stopping asynchronously, at an indeterminate point in the cycle.

Is there a way to support a synchronous update?  This would require either:

  1. Latching the new divisor and compare values, and clocking them in when the current cycle ends / new cycle begins, OR
  2. Support synchronous stop:
    1. Allow setting a Synchronous Stop flag,
    2. Fire an interrupt when the PWM stops (the ISR would then modify register values and restart the PWM),

Is there a better component to use?

Thanks!

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

Attached is example using DDS24 and a Timer. Frequency and number of pulses are updated on interrupt (isr_Reload). Both parameters will take effect simultaneously (hardware timing) upon Timer overflow. In this example frequency jumps between two values 50 Hz (5 pulses) <-> 100 Hz (10 pulses), while keeping period the same 100 msec. DDS output accuracy 0.015 Hz, UDB resources consumption ~20%.

The DDS component can be downloaded here:

DDS24: 24-bit DDS arbitrary frequency generator component

/odissey1

DDS_NumPulse_01a.png

DDS_NumPulse_01b.png

View solution in original post

0 Likes
6 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

What parameter is actually variable? Is it a number of MUXes? Some time diagram or drawing would be helpful.

/odissey1

0 Likes

The number of MUX inputs is changed, and the sampling frequency needs to be updated to <number of inputs> x <30Hz per input>.

The desired timing diagram is quite simple:  switch from one frequency to another at the end of a full cycle of the first frequency, without any 'runt' pulses.  Follow a full cycle of one sampling frequency (e.g. 210Hz) with full cycles of whatever the new sampling frequency is (e.g. 180Hz, 150Hz, etc.).

Using ASCII art, '_' for a low, '-' for a high.  Unfortunately the font here is variable spacing and a '-' is narrower than '_'.  This is intended to show 50% duty cycle.

Desired behavior:  Full Cycles

<---- 210Hz ------><------- 120Hz -------->

\_____/-----\_____/----------\__________/----------

OR transition on a falling edge:

<-- 210Hz -----><------ 120Hz --------->

/-----\_____/-----\__________/----------\__________

The goal is to simply transition from one frequency to another at a transition, rather than:

Current (Problem) Behavior, Asynchronous Switching:

It currently completes some portion of a cycle of the current frequency, then is reset.  Not actual waveforms, I am showing the concept of it cutting off the previous frequency at an arbitrary time and then starting output of the new frequency.

\_____/-----\__/----------\__________/----------

                   ^ runt pulse

or:

\_____/-----\/----------\__________/----------

                   ^ runt pulse

or:

\_____/\/----------\__________/----------

            ^ runt pulse

or:

\___/----------\__________/----------

     ^ runt pulse

or:

\_/----------\__________/----------

^ runt pulse

0 Likes

Another possibility is to use DDS24 custom component using its "hardware load" option.

DDS24: 24-bit DDS arbitrary frequency generator component

Please refer to the supplied Application Note and associated demo project: 'Sweep generator with hardware load' (DDS24_hw.proj). The DDS generates frequency, which is written to the internal buffer by API in interrupt, but load of the new value occurs instantly on the 'load' pulse (hardware timing). The only job left is to add a Timer/Counter to count number of pulses requires (120, 150, 180,... ). To get better resolution at low frequency, DDS clock must be set to low value (e.g. 1.6 MHz gives 0.1 Hz accuracy).

DDS24_hw_01.png

0 Likes
lock attach
Attachments are accessible only for community members.

Attached is example using DDS24 and a Timer. Frequency and number of pulses are updated on interrupt (isr_Reload). Both parameters will take effect simultaneously (hardware timing) upon Timer overflow. In this example frequency jumps between two values 50 Hz (5 pulses) <-> 100 Hz (10 pulses), while keeping period the same 100 msec. DDS output accuracy 0.015 Hz, UDB resources consumption ~20%.

The DDS component can be downloaded here:

DDS24: 24-bit DDS arbitrary frequency generator component

/odissey1

DDS_NumPulse_01a.png

DDS_NumPulse_01b.png

0 Likes
ScWi_1017771
Level 2
Level 2
First like given

Looks like I'll be learning how to create a custom component.

0 Likes

I believe that can be done using standard PWM and interrupt.

Please take a look at this PSoC4 Sequential PWM demo (#8)

Re: Using a single PWM block to drive multiple pins using DEMUX

and associated YouTube video: https://youtu.be/qQQ731Kddq8

Same project updated for PSoC5

Bug in PWM or am I missing something really obvious? 

The gist of it that PWM parameters can be updated on-the-fly with hardware timing at ~1 kHz range. The way it works, PWM parameter (in this example, a duty cycle) is updated inside ISR with a new value every time the counter rolls-over. Because the compare value is double-buffered, the software (isr) timing is not important, actual value is being copied from the buffer (hardware timing), which has been updated during previous cycle. I believe that the same principle can be applied here with additional counter in ISR to count number of pulses (150, 180, 210...).

/odissey1

0 Likes