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.
Hi,
I am working on MSP430F5438A board. I am sending 500Hz sine wave signal from function generator and passing through ADC12 of MSP430 and plotting the sine wave on pc using python.
ADC clock - SMCLK (1,048,576 Hz frequency)
ADC sampling frequency - 7436.7Hz (ADC12SHT06 -128clock cycles)
UART baud rate - 115200bps
My problem is that I am not able to correctly set TA1CCR0. I get different plots if I use different values and if I change the input signal frequency the plot gets distorted so I then have to make some changes in the code and use different value of TA1CCR0.
Please tell me how to correctly set TA1CCR0 values so that I am able to plot for all frequencies
Thanks
Yuvraj
Your post doesn't really say what you are using TA1 for. Are we to assume that it is used for triggering an ADC conversion cycle?
If so, then the larger the number you use for TA1CCR0, the longer time between samples, and the better the chance of aliasing occurring.
I would recommend looking at the User's Guide (SLAU208) and making sure you understand how many clock cycles a single ADC conversion takes with all of your settings. Once you know that, then you can determine what rate you can actually sample at and compute the value for TA1CCR0 accordingly.
BTW.... to clarify for you, setting the ADC sample/hold time and other parameters determine the conversion time, not the sampling rate. The sampling rate is the inverse time between conversion starts.
Regarding sampling rate, can you please tell in bit more detail how to calculate sampling rate and on what all factors is it dependent on?
Also in the link below , a query was put up regarding sampling rate and I am doing same calculation as this guy did for his case
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/41263.aspx
I am attaching the code I am using. Please if you could have a look at it and tell me where am I wrong.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char buffer[100];
static uint8_t SavedADC12MEM1; //To store ADC outputs
int16_t x_new,y_new;
float values;
float factor=0.000714285714; int volt;
/*************************************************************************************/
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
P1OUT ^= 0x01; // Toggle P1.0
ADC12CTL0 |= ADC12ENC; // Enable conversions
ADC12CTL0 |= ADC12SC; // Start conversion
}
/*---------------------------------------------------------------------------*/
#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
ADC12CTL0 &= ~ADC12ENC; // Disable ADC12 conversions
REFCTL0 &= ~REFON; // Disable reference (if enabled)
SavedADC12MEM1 = ADC12MEM1; // Store the sampled data
__bic_SR_register_on_exit(LPM0_bits);
}
/*---------------------------------------------------------------------------*/
void accelerometerInit(void)
{
P7SEL |= BIT5; // Pin 7.6 and 7.7 are inputs from the accelerometer to the ADC => they are configured as inputs to the ADC
P7DIR &= ~BIT5;
UCSCTL8 |= MODOSCREQEN; // ADC is clocked by the ACLK in the UCS module
ADC12CTL0 &= ~ADC12ENC; // Disable conversion
ADC12CTL0 = ADC12ON + ADC12SHT0_6 + ADC12MSC; // Turn on ADC, Sample once every 1024 cycles, Multisample conversion
ADC12CTL1 = ADC12CSTARTADD_1 + ADC12SHP + ADC12CONSEQ_2 + ADC12SSEL_3;
ADC12CTL2 = ADC12RES_2; // Resolution=12 bits, 13 clock cycle conversion time
ADC12MCTL1 = ADC12INCH_13; //select channel 13(pin 7.5)
ADC12IE = 0x00;
__delay_cycles(200000); // Allowing reference voltage to stabilize
}
/*---------------------------------------------------------------------------*/
void accelerometerReadWithOffset(uint8_t *x)
{
*x = SavedADC12MEM1;
}
/*---------------------------------------------------------------------------*/
void adcStartRead(void)
{
ADC12IFG = 0x00;
ADC12IE = BIT1;
ADC12CTL0 |= ADC12ENC | ADC12SC;
// Enable conversion and Start conversion
}
/**********************************************************************************/
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// initialize Timer_A module
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 =(52000);
TA1CTL = TASSEL__SMCLK + MC__UP + TACLR; // ACLK, up mode, clear TAR
//float voltages;
while(1)
{
accelerometerInit();
adcStartRead();
//accelerometerReadWithOffset(&x_new); // ADC output (digital data
//voltages=x_new*factor;
// initialize USCI module
P5SEL |= BIT6 + BIT7; // P5.6,7 = USCI_A1 TXD/RXD
UCA1CTL1 |= UCSWRST; // **Put state machine in reset**
UCA1CTL1 |= UCSSEL__SMCLK;
UCA1BR0 =9; //
UCA1BR1 = 0; //
UCA1MCTL = UCBRS_1;
UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
int k=0;
sprintf(buffer,"%d",SavedADC12MEM1);
while(buffer[k])
{
while(!(UCA1IFG&UCTXIFG)); // USART0 TX buffer ready?
UCA1TXBUF = buffer[k++];
}
__bis_SR_register(LPM0_bits+GIE); // Enter LPM0, enable interrupts
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
DCO, while convenient, has no precision frequency. The ADC runs in free-running mode, so its conversion cycle length is unknown (and btw it is 128+13 MODOSC cycles). With 1MiHz, as you wrote, it would indeed be 7436Hz maximum sampling frequency, if the timer would trigger exactly when the ADC is ready. However, default is 1.0MHz. Which gives a maximum sampling rate of 7092sps.
But let’s assume 7436hz sampling rate, this means you have 7436 results per second. You convert them into decimals with printf. So it can be 4 bytes you transfer for each result (4 digits, no delimiter). Means 40 bit per result. Or 297440Bd minimum UART baudrate or you’ll start skipping results. Your 115200bps aren’t by far not fast enough to transfer all samples. Between two sent samples, you always skip one or two. And depending on input signal waveform, this gives distortion or aliasing effects.
Now you’re running the ADC in repeated single conversion mode with SHP and MSC set. Normally, the ADC would begin the next conversion once the previous is done. Which it tries. But then in your ADC ISR, you interrupt it by clearing ADC12ENC. Then in the next timer interrupt you start it again.
BTW you’re sending the first ADC result without waiting for the first (manually started in adcStartRead) conversion to complete. Also, your main while loop and the timer ISR both start a conversion. And you init the accelerometer and the USCU on each loop. (but the USCI might not be done with sending the last byte).
Also, you disable the reference in the ADC ISR. Which makes no sense because you never enable it and you don’t use it.
All this looks like what has been named “Frankenstein code” in this forum: code patched together from snippets ripped out of different demo codes and somehow combined without really knowing how they work and how they should work together. As a result you got Frankenstein’s monster, rampaging through its virtual world. (Actually, it is an insult to Dr. Frankenstein. At least he knew where head and feet belong :) )
I did some changes as you told me to do, I sent a sine wave of frequency 10Hz from function generator and I was able to plot the wave on pc after passing it through msp430f5438a. I am even able to see the changes in plot as I change the frequency. My settings are:
ADC sampling rate: 40Hz
UART baud rate: 115200
My query is I am not able to obtain the plot for higher frequencies like for 100Hz , I changed the sampling frequency upto 1.1KHz but still no luck.What can be possible error?
Thanks
hello jeans,
can you please explain what do u mean by
But let’s assume 7436hz sampling rate, this means you have 7436 results per second. You convert them into decimals with printf. So it can be 4 bytes you transfer for each result (4 digits, no delimiter). Means 40 bit per result. Or 297440Bd minimum UART baudrate or you’ll start skipping results. Your 115200bps aren’t by far not fast enough to transfer all samples. Between two sent samples, you always skip one or two. And depending on input signal waveform, this gives distortion or aliasing effects
thank u
It means what I wrote. You get a 12 bit binary value form the ADC. Then you convert it into a human-readable chain of digits with sprintf. Which takes up to four digits per value. This means, you’ll have send 4*10 bit through UART. So the UART baudrate needs to be at least 40 times higher than the sampling frequency – which you specified with 7436Hz. 7436*40 is 297440, which is your minimum UART baudrate then.
Now if you sample slower, of course you need a lower baudrate.
If you send binary data, you only need two bytes per sample. If you pack the data, you only need three bytes per two samples. Which will reduce the required baudrate to 1/2 or even 3/8 of this value. But then the data is not human-readable anymore.
Well, since your sprintf conversion does not contain a space or lien feed to separate two values, all you’ll see in a terminal program would be an endless chain of digits. You should change your format string to “%d “ or even “%04d “ (note the space). Of course this will mean you’ll have to send 50 bits per sample, further rising the required baudrate. But at lease you’ll see separated numbers on the terminal.
**Attention** This is a public forum