Jump to content
Sign in to follow this  
watergius

PWM from 2 Analog input in MSP430G2231 ?

Recommended Posts

Hello guys..

 

I am a newbie to this MSP430. So, please tell me when I go wrong.

 

I have a final project making MPPT (Maximum Power Point Tracker) using MSP430G2231. The basic idea is to measure to Analog input (voltage and current), then multiply it (power) and compare to the previous result. That's why, before going further to the algorithm of the MPPT itself, I am trying to use this MSP430G2231 to read 2 analog input and create PWM using it.

 

I use two pins as an input, P1.0 and P1.1. Then, I use P1.2 to produce the PWM.

The coding that I made goes like this:

#include 
#include "msp430g2231.h"

//Global Variable
unsigned int AdcData[2] ;                 // Store results A1,A0
unsigned int Current ;			// store value from P1.0 
unsigned int Voltage ;			// store value from P1.1

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

 BCSCTL1 = CALBC1_1MHZ;	// Set range
 DCOCTL = CALDCO_1MHZ;		// SMCLK = DCO = 1MHz  

 ADC10CTL1 = INCH_1 + CONSEQ_1;            // A1/A0, single sequence
 ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE;
 ADC10DTC1 = 0x02;                         // 2 conversions
 ADC10AE0 |= 0x03;                         // P1.1,0 ADC10 option select

 P1DIR |= BIT2;                            // P1.2 = output
 P1SEL |= BIT2;                            // P1.2 = TA1 output
 TACCR0 = 1024-1;                             // PWM Period
 TACCTL1 = OUTMOD_7;                       // TACCR1 reset/set
 AdcData[0]=32;
 AdcData[1]=16;
 Voltage = AdcData[0];
 Current = AdcData[1];				  
 TACCR1 = (Voltage*0.04)*(Current*0.05);         // TACCR1 PWM Duty Cycle
 TACTL = TASSEL_2 + MC_1;                  // SMCLK, upmode


 while (1)
 {
 __bis_SR_register(LPM0_bits + GIE);     // LPM0, ADC10_ISR will force exit
  ADC10SA = (unsigned int)AdcData;        // Data transfer location 
  ADC10CTL0 |= ENC + ADC10SC;             // Start sampling
 }
}


// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
 __bic_SR_register_on_exit(LPM0_bits);     // Exit LPM0
}

 

And it doesn't goes well.. :(

 

I try to trace it using "step into" in debugging mode. Everything seems goes well until it reach this line :

 ADC10SA = (unsigned int)AdcData;        // Data transfer location 

 

When the pointer reach that line, the "step into" button is not active anymore which means there's something wrong..

 

Do I write the algorithm right, especially when assign the values from ADC to the AdcData?

Any helps are greatly appreciate.

Thank you.

Share this post


Link to post
Share on other sites

//******************************************************************************

//  MSP430F20x2 Demo - ADC10, DTC Sample A1 32x, 1.5V, Repeat Single, DCO

//

//  Description: Use DTC to sample A1 32 times with reference to internal 1.5v.

//  Vref Software writes to ADC10SC to trigger sample burst. In Mainloop MSP430

//  waits in LPM0 to save power until ADC10 conversion complete, ADC10_ISR(DTC)

//  will force exit from any LPMx in Mainloop on reti. ADC10 internal

//  oscillator times sample period (16x) and conversion (13x). DTC transfers

//  conversion code to RAM 200h - 240h. P1.0 set at start of conversion burst,

//  reset on completion.

//

//                MSP430F20x2

//             -----------------

//         /|\|              XIN|-

//          | |                 |

//          --|RST          XOUT|-

//            |                 |

//        >---|P1.1/A1      P1.0|-->LED

//

//  L. Westlund

//  Texas Instruments Inc.

//  May 2006

//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A

//******************************************************************************

#include  "msp430x20x2.h"



void main(void)

{

 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

 ADC10CTL1 = CONSEQ_2+INCH_1;              // Repeat single channel

 ADC10CTL0 = SREF_1 + ADC10SHT_2 + MSC + REFON + ADC10ON + ADC10IE;

 __enable_interrupt();                     // Enable interrupts.

 TACCR0 = 30;                              // Delay to allow Ref to settle

 TACCTL0 |= CCIE;                          // Compare-mode interrupt.

 TACTL = TASSEL_2 + MC_1;                  // TACLK = SMCLK, Up mode.

 LPM0;                                     // Wait for delay.

 TACCTL0 &= ~CCIE;                         // Disable timer Interrupt

 __disable_interrupt();

 ADC10DTC1 = 0x20;                         // 32 conversions

 ADC10AE0 |= 0x02;                         // P1.1 ADC option select

 P1DIR |= 0x01;                            // Set P1.0 output



 for (;

 {

   ADC10CTL0 &= ~ENC;

   while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active

   ADC10SA = 0x200;                        // Data buffer start

   P1OUT |= 0x01;                          // Set P1.0 LED on

   ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start

   __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit

   P1OUT &= ~0x01;                         // Clear P1.0 LED off

 }

}



// ADC10 interrupt service routine

#pragma vector=ADC10_VECTOR

__interrupt void ADC10_ISR(void)

{

 __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)

}



#pragma vector=TIMERA0_VECTOR

__interrupt void ta0_isr(void)

{

 TACTL = 0;

 LPM0_EXIT;                                // Exit LPM0 on return

}

straight from the code examples

 

you have to wait for the conversion to finish before sending it to the buffer

Share this post


Link to post
Share on other sites

thank you all for giving me feedback..

 

Actually I've been writing the algorithm like you mention and it goes like these and it still not working

 for (;
{
  ADC10CTL0 &= ~ENC;
  while (ADC10CTL1 & BUSY);               // Wait if ADC10 core is active
  ADC10SA = (unsigned int)&AdcData;        // Data transfer location 
  ADC10CTL0 |= ENC + ADC10SC;             // Start sampling
  __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exit  
 }

// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
 //code from reading from res and sending it to AP
 __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}

 

the only difference is, now the "step into" button not working when it reaches the line after

__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit

 

I don't use this code : P1OUT |= 0x01; because I use that Pin for ADC input. And this line,

 

ADC10SA = 0x200; // Data buffer start

 

ADC10SA means ADC10 Start Address right, where you want to transfer the ADC conversion value? So, when I want to transfer it to my AdcData array, is it okay to write it like it did?

 

thanks

Share this post


Link to post
Share on other sites

lol well the step button wont work when the CPU is off

so go ahead and remove it

 

 

i haven't used it in that fashion, but i would try and transfer write into the array crap dont try that what am i thinking lol

 

 

to me the pointer that your using just doesn't look write to me, I would have to read up some more C text books to see but alas i have already worked 10 hours today and am ready to go to bed. ill keep looking into it later if you havent found a solution.

 

Good luck

Share this post


Link to post
Share on other sites

actually the step button is not a real button (not physical).. It is a button in debugging mode to check whether the value in a specific register correct or not (I got it from this tutorial : http://mspsci.blogspot.com/2010/07/tutorial-06-getting-bugs-out.html)

 

I try to track it because when I run the codes/algorithm, the PWM is not working and the value in all registers are unable to read..

 

And about the pointer itself, I don't really know whether it's wrong or not. I copied it from this code example (msp430g2x31_adc10_16.c) and it working right there. And I also try it with and without the pointer (&) for the AdcData :|

 

thanks.

Share this post


Link to post
Share on other sites
...And about the pointer itself, I don't really know whether it's wrong or not. I copied it from this code example (msp430g2x31_adc10_16.c) and it working right there. And I also try it with and without the pointer (&) for the AdcData :|

The code example is

 ADC10SA = (unsigned int)&TACCR1;        // Data transfer location

If you don't use address of, you simply setting ADC10SA to the values that is currently stored in TACCR1.

ADC10SA needs memory address. In your case it is working with or without because address of the first element is returned with or without &.

Share this post


Link to post
Share on other sites

@RobG : what do you mean with "address of" ? Is it the address of the AdcData?

with the code example that you provide, that means that I should write something like this, right:

 ADC10SA = (unsigned int)&AdcData;        // Data transfer location

 

My AdcData is an array which consist of AdcData[0] (for storing converted ADC value from P1.0) and AdcData[1] (storing converted ADC value from P1.1). Or, do I need to assign the ADC10SA like this : ADC10SA = (unsigned int)&AdcData[0]; to indicate the address started at AdcData[0] ?

thanks

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...