Update Duty-cycle in Channel Interrupts?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Update Duty-cycle in Channel Interrupts?

Jump to solution
25,228 Views
abicash
Contributor III

Hi

 

Till now i would update TPMCnV with duty values in overflow interrupt ISR.

I want to use 2 channels of the same timer w/ different pulse widths.

For this i need to update values in channel interrupt (rather than overflow interrupt).

I am using Edge aligned PWM mode for the timer.

 

Can someone share a snippet or at least guide with some top level advice?

 

Thanks and Regards

Labels (1)
0 Kudos
1 Solution
1,151 Views
bigmac
Specialist III

Hello,

For 9S08 devices, the update of the PWM pulse width is automatically buffered, so that the new TPMCnV setting will update the duty just prior to the next overflow.  It is therefore unnecessariy to update the value within an ISR - simply write the new duty values to each register.

However, this will not guarantee that each PWM channel will change within the same cycle.  If this is a requirement, you should change both channel settings within the overflow ISR.  The change of duty for both channels will then be delayed by nearly one PWM cycle from this point.

Updating the register setting within each channel interrupt would not achieve any advantage over the direct update process, that I can see.

Regards,

Mac

View solution in original post

0 Kudos
5 Replies
1,152 Views
bigmac
Specialist III

Hello,

For 9S08 devices, the update of the PWM pulse width is automatically buffered, so that the new TPMCnV setting will update the duty just prior to the next overflow.  It is therefore unnecessariy to update the value within an ISR - simply write the new duty values to each register.

However, this will not guarantee that each PWM channel will change within the same cycle.  If this is a requirement, you should change both channel settings within the overflow ISR.  The change of duty for both channels will then be delayed by nearly one PWM cycle from this point.

Updating the register setting within each channel interrupt would not achieve any advantage over the direct update process, that I can see.

Regards,

Mac

0 Kudos
1,151 Views
abicash
Contributor III

Hello Mac

thanks for the reply

It seems right now.

A related problem :

I have been trying a code for quite some time now and am having troubles anyhow which i cannot resolve.

I am generating a Sine-wave out of a Look up table (3200 8-bit values) and then trying to synchronize with an input frequency (close to 50 Hz)

I am using an SH8 device but lately i have found that the debugger window just freezes (some variables update though).I assumed it to be a stack problem and have changed various values in prm to no avail.

If i attach this project, can you take a look and point out a mistake?

0 Kudos
1,151 Views
bigmac
Specialist III

Hello,

I assume that you are attempting to generate a sine wave of the same frequency as the input signal.  I also assume that the input frequency will be close to, but not exactly 50Hz, and would be variable over narrow limits.

I have a problem understanding how you actually intend to vary the generated frequency to achieve synchronisation, and the size of the minimum frequency increment that you require.  Additionally, the sine look-up table would seem to be far too large to be practical.  With 256 states in each PWM cycle, and assuming a fixed output frequency of 50 Hz, the bus frequency would need to exceed 256 * 3200 * 50 = 40.96 MHz - clearly outside the bus limit for the device you are using.  A table size of 256, or maybe 512 entries would seem far more appropriate, especially as the table contains 8-bit amplitude values.

I wonder if your ISR code currently requires more than the available 250 cycles to complete, or perhaps another interrupt is causing a problem.

One method that can provide a good variable frequency resolution, with more moderate clock rate, is the Direct Digital Synthesis (DDS) method.  The DDS method achieves the improved frequency resolution due to the fact that there may be small variations of step duration over each output cycle.  Since these adjustments are spread over the whole cycle, there is little distortion to the output signal.  Another characteristic of DDS is that, as the output frequency increases, the number of steps per cycle will gradually reduce, thus again moderating the clock frequency requirement.  yet a further advantage of DDS is that the frequency adjustment parameter setting is directly proportional frequency, rather than output period, as for other synthesis methods.  The MCU code for the phase update will probably need to be written in tight assembly code, and the highest bus frequency available used.


Let's set some parameters for DDS operation.


I will assume that the main DDS accumulation register is 24 bits in length, but uses only 20 active bits, and that the bus frequency is 8 MHz.  Dividing this by the PWM period cycles (256) will give a maximum DDS clock of 31.25 kHz. However, the choice of a lower DDS clock frequency would allow more bus cycles for each phase update to occur. To output a constant frequency, a fixed value N needs to be added to the main register at every DDS clock interval.  With this arrangement, the frequency resolution would be Fclk / (2^20)  ~ 0.03 Hz.  The output frequency will be given by the expression N * Fclk / (2^20).  Note that the waveform at the MS bit of the main register will be a square wave at the set frequency.  The upper bits of the main register would form the address for the sine look-up table, and the value from the look-up table would be applied to the PWM.


I would suggest that the PWM overflow interrupt be used to trigger each update of the PWM register.  The new PWM value should then come into effect on the next overflow.


Because of the symmetry of a sinusoid, it may be possible to reduce the size of the look-up table to one-half or one-quarter of the output cycle.  But this will involve further manipulations of the data, and may push over the processing cycle limit.

Regards,

Mac

0 Kudos
1,151 Views
abicash
Contributor III

Hello Mac

The problem got solved !

As i had mentioned earlier the code was attempting to use uninitialized memory, i realized that this location was Timer overflow interrupt vector.

So i wrote an ISR clearing the TOF bit and now everything seems to run fine.

Regarding your doubt about 3200 Look up table variables , i want to clarify that the lookup table is of 32 variables for one half cycle.I have 100 such tables to adjust for feedback voltages.I index this table to compensate for any changes in the output.

In each input capture ISR, the first thing i do is reset this index so that it starts at 0th position so sync would be automatically achieved (?).

Also i derive the frequency where i call each of the 32 variable for n times to make up say 10ms so that for twice the frequency , i call each variable n/2 times.

This seems to work for now.

Can you point out an inconspicuous mistake here? i may be missing something

Thanks and regards

0 Kudos
1,151 Views
abicash
Contributor III

Hello and thanks for the much awaited reply Mac :smileyhappy:

I have shared my project with you yesterday

Can you take a look?

Right now i am checking this on Full chip simulation and i see this

Error: At location FFE2 -
Error: Attempt to use invalid or uninitialized memory

Error: Interrupt processing failed.
HALTED

Here is my prm file

/* This is a linker parameter file for the mc9s08sh8 */

NAMES END /* CodeWarrior will pass all the needed files to the linker by command line. But here you may add your own files too. */

SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */
    Z_RAM                    =  READ_WRITE   0x0080 TO 0x00FF;
    RAM                      =  READ_WRITE   0x0100 TO 0x027F;
    ROM                      =  READ_ONLY    0xE000 TO 0xFFAD;
  INTVECTS                 =  READ_ONLY    0xFFC0 TO 0xFFFF; /*Reserved for Interrupt Vectors */
END

PLACEMENT /* Here all predefined and user segments are placed into the SEGMENTS defined above. */
    DEFAULT_RAM,                        /* non-zero page variables */
                                        INTO  RAM;

    _PRESTART,                          /* startup code */
    STARTUP,                            /* startup data structures */
    ROM_VAR,                            /* constant variables */
    STRINGS,                            /* string literals */
    VIRTUAL_TABLE_SEGMENT,              /* C++ virtual table segment */
    DEFAULT_ROM,
    COPY                                /* copy down information: how to initialize variables */
                                        INTO  ROM;

    _DATA_ZEROPAGE,                     /* zero page variables */
    MY_ZEROPAGE                         INTO  Z_RAM;
END

STACKSIZE 0x40

VECTOR 0 _Startup /* Reset vector: this is the default entry point for an application. */

What is happening?

0 Kudos