This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to generate 4 SPWM using MSP430g2553?

Other Parts Discussed in Thread: MSP430G2553

Hi,

I am trying to generate 4 SPWM signals (reference signal 50Hz, Triangular wave 2.5kHz) for my h-bridge inverter like the following:

However, its not giving appropriate output for the complementary signals. Below is my code. I will be grateful if someone can help. Thanks in advance.

#include  <msp430g2553.h>

#define pwmPeriod 400				// carrier of 2.5kHz and reference of 50Hz. PWM period is 0.4 ms.

const unsigned int phalfcycle[25] = {200, 223, 245, 266, 287, 306, 323, 339, 352, 363, 371, 377, 380, 380, 377, 371, 363, 352, 339, 323, 306, 287, 266, 245, 223};

unsigned int pulsecounterA0 = 0;
unsigned int pulsecounterA1 = 0;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  //Calibrate DCO for 1MHz operation
  BCSCTL1 = CALBC1_1MHZ;
  DCOCTL = CALDCO_1MHZ;

  P1OUT &= 0x00;								// Setting all pins as low
  P2OUT &= 0x00;

  P1DIR |= BIT2 + BIT6;							// PWM Outputs
  P2DIR |= BIT1 + BIT2;

  P1SEL |= BIT2;
  P2SEL |= BIT1;

  TACCR0 = pwmPeriod - 1;						// setting PWM period to 0.4 ms, 400-1 clock ticks of SMCLK
  TA1CCR0 = pwmPeriod - 1;

  TACCTL0 = CCIE;								// Enable Timer A0 Interrupt for CCR0
  TA1CCTL0 = CCIE;

  TACCTL1 = OUTMOD_2;							// RESET/SET for Timer A0 CCR1
  TA1CCTL1 = OUTMOD_6;


  TACTL = TASSEL_2 +  MC_1 + TACLR;          	// Timer_A0 control register with SMCLK = 1 MHz, Upmode. Starting the timer
  TA1CTL = TASSEL_2 + MC_1 + TACLR;

  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

// Timer A0 interrupt service routine
// #pragma is a catch-all preprocessor directive that is used to extend the functionality of the compiler that is not already covered by predefined directives.
//In this code, the compiler (and the linker) is being told that we are going to create an ISR for TIMER0_A0_VECTOR.
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
	//TACCTL1 = OUTMOD_7;

	if (pulsecounterA0 < 25)
	{

		TACCR1 = phalfcycle[pulsecounterA0];
		pulsecounterA0 = pulsecounterA0 + 1;
	}
	else
	{
		P1SEL ^= (BIT2 + BIT6);
		pulsecounterA0 = 0;
	}

}


// Timer A1 interrupt service routine
// #pragma is a catch-all preprocessor directive that is used to extend the functionality of the compiler that is not already covered by predefined directives.
//In this code, the compiler (and the linker) is being told that we are going to create an ISR for TIMER1_A0_VECTOR.
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer_A1 (void)
{

	if (pulsecounterA1 < 25)
	{

		TA1CCR1 = phalfcycle[pulsecounterA1];
		pulsecounterA1 = pulsecounterA1 + 1;
	}
	else
	{
		P2SEL ^= (BIT1 + BIT2);
		pulsecounterA1 = 0;
	}

}

  • Hi,

    For synchronized PWMs, I assume you mean you want each PWM pulse to be centered with each other, and not have rising (or falling) edges synchronized, correct?  The easiest way to do this is with up-down mode in the timer module.  Please reference section 12.2.5.4 in the MSPx2xx User's Guide for up-down mode in TimerA.  Also, see code example msp430g2xx3_ta_19 (from the Resource Explorer in CCS).  However, this only applies to PWMs generated out of the same timer module.  Since the G2553 has two TimerA3s, each timer module can generate two PWMs.  This means your 4 PWMs can be synchronized in pairs, but not all 4 together.

    Mike

  • What H-bridge driver are you using?
    Most allows to PWM just one gate a time and you alternate between each side
    And therefor you only need one pwm that you toggle between two TA0.1 outputs

    Micrel have a new one out and I'm sure TI have a few too
    MIC4606-2 : 2 PMW inputs
    www.mouser.com/.../MIC4606-461413.pdf

    You are going old-school with something like this, don't punish yourself get above IC.
    so-which-pwm-technique-best-part-5

  • Thanks a lot Mike. Seems like I need sometime to go through the user guide and the code example to understand what you are saying. In case of 4 synchronized PWMs, isn't it possible that I calibrate both the timers for the same frequency like I did in my code example? I need 4 synchronized PWM signals as I am trying to implement Unipolar Sinusoidal PWM. Any observation on this?
  • Thanks for the reply Tony. I am using FOD3184 as the driver. And you are right that I need to generate only 2 signals. If you see my code, I am generating same signal for P1.2 and P1.6 and toggling between them to have signals c and e in the sample picture. Again, I am using P2.1 and P2.2 to generate another signal and toggling between them to generate d and f signals in the sample picture. However, as you can see c and d are complementary signals and e and f are complementary signals. To get complementary signals I am using OUTMOD_2 and OUTMOD_6 but then the generated signals are not completely complementary. Instead, I am getting one/two extra pulses and also the pulse widths are not matching. I can see pulse width difference at microseconds level although the pulse width should be the same for complementary signals. Please help if you can think of any solution.

    Tahsina
  • How are you going to control dead time and thru shoot protection?
    MIC4606 have all the bells and whistles.
    Apply up to a 50KHz pwm and it will handle it all for you.
    So unless this is a school project and they want to teach you old-school stuff first

  • I am using very low loss IGBT IRG4BC20UD for the full bridge. I am not sure if I can use MIC4606 as the driver of the IGBT. Rather I wanted to use MSP430 code to configure dead time.

    Tahsina
  • I assume you don't need it to withstand 600v as this is the low voltage side of the inverter.
    N-Mosfets are now down to 0.01 Ohm Rds (=low loss and low heat)
    www.mouser.com/.../N-ax1sfZscv7;Ns=Pricing%7c0

    As MIC4606 have a boot strap circuit so you can use n-mosfet for the high side too, improving efficiency.

    IGBT or MOSFET: Choose Wisely
    www.irf.com/.../choosewisely.pdf

  • It is possible to synchronize two timers. There are two methods: one is complicated and the other requires hardware.
    In the first case, you need to exactly count the CPU clock cycles between starting timer 1 and timer 2, and adjust their initial counts accordingly. Depending on the actual application, this can be simple or complex.
    The other way is to output the timer clock on a pin and route it to the two timer's clock inputs. This way you can start both timers synchronously by simply switching the clock on after you have configured and started the timers. This also allows for a synchronized stop, if required.
  • Dear sir,
    I am facing problems with programming for sine wave PWM though I have been trying it few months ago.I am having c2000 F28027 and also control suite installed on my pc. Please will you lead me a perfect way.

    Thanks
  • I know there is a language barrier involved here, but what about your basic engineering skills?

    Do you know C? Do you understand how a single core mcu has to deal with IRQ's to handle things?

    Have you made LED blink in software, then moved on by blinking the LED by msp430-timer.
    Then moved on by fading the LED using pwm., now apply a sineway lookup table to the pwm and you are close.

  • Yes I accept that I lag in language but have basics cleared for c. I have even tried all led program as you specified here. But the problem arises in advance programming needed for sine wave interruption by triangular wave to develop modulation. Prior to that how should a sine wave be generated in mcu,I don't want to use a external sine generator to compare with timer.plz help me program it.
  • Siddhesh, there is a seperate thread for your problem here. Tashina, maybe this document has some useful information for you, too.

    Dennis

  • Hi I am a beginner in MSP430G2553.I too want to generate an SPWM

    I have studied your code, but I am unable to figure out where have you assigned the amplitude to the carrier wave ? Also if I want to shift the sine wave such that it's negative cycle can also contribute in the PWM generation what changes should I make in the sine sample points.

    Thanks in advance !

  • There is no simple way to configure the amplitude in the code.

    PWM is a digital output, which switches between logical low and high. Physically, this is between 0V and VCC. So the amplitude of the signal is defined by VCC and (to a lesser extent) by the ratio between PWM frequency and sine frequency and the applied filter.

    you can influence (attenuate) the aplitude by limiting the pulse density of the PWM duty cycle maximum (the duty cycle for sine maximum). Or you simply use an external voltage divider :)

  • How can I vary the sampling time in this code? to adjust the number of samples in my sine wave.
  • The 'Sampling time' is configured by the timer cycle length and hte timer tick frequency.

    In the above code, the timer tick frequency is 1MHz (which is the convigured DCO frequency), the cycle length is 400 ticks, which means the timer runs from 0 to 399 for each PWM cycle. This results in 2500 PWM pulse per second (a PWM rate of 2,5kHz).

    With 25 samples per half-wave this gives 50Hz output frequency.

    Whenyou want more samples per (half) wave with same sine frequency, you'll have to either reduce the number of timer ticks per PWM cycle (which in turn reduces the range value for the duty-cycle, so you need to scale the samples) or you can increase the timer tick frequency.

    In any case, you'll have to adjust the external analog low-pass filter which turns the digital rectangular PWM pulse output into an analog value or your output signal will attenuate.

    Depending on the external filter, increasing the samples per sine wave does not really increase the quality of the signal.
    If you use an analog filter with a cutting frequency of 50Hz, you can run 1 PWM cycle per wace with 50% duty cycle and get a sine-like output too (well, it's more a sawtooth). Increasing the number of samples (to 50 in this case) increases the shaping (to 50 tiny sawtooth shapes arranged on a sine curve and smoothed) and reduces the requirements for the filter (towards higher filter cutting frequency and therefore smaller, cheaper parts) but the effect lessens with increasing sample count.
    I've not done the math, but I guess, to halve the distortion, you'll have to double the samples. Which means for an exponentially increasing number of samples, the resulting quality increase is only logarithmically.
     And you'll never get a 100% distortion-free sine wave.

  • BTW: increasing the number of samples also means calling the ISR more often. It also tightens the constraints for the ISR timing, so you don't miss the moment where the PWM cycle has to be updated. The processor requires some time to call and execute the ISR. If you increase the DCO clock, then of course the processor speed scales with the PWM speed. But then power consumption increases even more (over-proportionally), if that's an issue. And with higher PWM frequency, crosstalk increases too. So some thoughts are required to find the optimum configuration.
  • According to the sine array if  25 samples correspond to 10ms cycle, why does my scope image show 20ms cycle at each pin.

    Also It appears that my pulses are missing at two intervals,I have run the aforementioned code on my system.Is the reason for that a bit overflow situation? (I am not very certain)

    Also how can I calculate the modulation index.What relation does duty cycle(which is the input of the sine array) has with the amplitude of sine wave?

  • The 25 values in the original correspond to a half cycle, full cycle is 50 values. In the original code, every 25 values, the port pins are inverted, so the output is inverted too for the second half-wave.

    The output of a PWN is limited to 0V to VCC. If the duty cycle is constantly 0% 0r 100%, the output voltage will be 0V or VCC, no matter what analog filter you apply. It's DC and not attenuated by any filter. However, if the duty cycle is between 0% and 100%, the steepness of the filter determines how much the digital output signal is averaged and attenuated to an analog value. Nevertheless, it is still between 0V and VCC. This is why the samples never reach 0 or 399. The filtered analog wave will have a DC offset part. For a sine output with negative value, it must be level-shifted by its average DC value. This can be done by a series capacitor (similar to the AC coupling of an oscilloscope) or a more complex high-pass filter.

    Regarding the 'missing' pulses: the code requires the CCR to be updated on each cycle. The update must happen after the last output trigger but before the next. Depending on the actual values, it may be that your ISR isn't fast enough to do so, resulting in one cycle being not X but 100+X%. This is why the original code comes not even near 0 or 399 but limits to 200..380. This gives the ISR 200 clock cycles for the update (worst case). But of course it also limits the AC amplitude, as it adds another 50% of the theoretical maximum to the DC offset.

    Using TimerB, which is available in many MSPs, offers a workaround. Here you can load the new CCR value into a latch register and update the CCR value at the next timer overflow in hardware (the very moment the timer ocunts to 0). So you always have a full cycle to prepare the nex value, no matter what the last value was.
  • Thanks , I think I may have a better understanding to approach it now.

**Attention** This is a public forum