Hi everyone,
I am attempting to setup a continuous data acquisition routine with the MSP430, it will transmit the integers over UART to be read and interpreted by MATLAB. I intend to operate at a sample rate of above 10Khz. I have read a few previous articles on this website and was able to set up continuous data transmission, however I observed some irregularities and I am not sure of the cause. I am not sure I have gone about this in the best way also my knowledge of operating the ADC on the MSP430 is not extensive, but I am aware of the functions of the majority of registers.
// Main Routine #include "msp430G2553.h" #include "Config.h" #include "Initialise.h" #include "UARTSend.h" void ConfigureTimerAPWM(void); void ConfigureADCBlock(void); void ConfigureUART(void); void InitialisePorts(void); void UARTSendArray(unsigned char *TxString, unsigned int ArrayLength); void UARTSendIntArray(unsigned int *TxArray, unsigned int ArrayLength); void UARTSendTerminator(void); volatile unsigned int data[SAMPLES]; // define data array void main(void) { InitialisePorts(); ConfigureUART(); ConfigureTimerAPWM(); //ConfigureADCBlock(); __enable_interrupt(); // Enable interrupts. __bis_SR_register(LPM0_bits + GIE); // Enter LPM0, interrupts enabled } // Echo back RXed character, confirm TX buffer is ready first #pragma vector=USCIAB0RX_VECTOR __interrupt void USCI0RX_ISR(void) { if (UCA0RXBUF == 'D') // If it recieves char D it will start { UARTSendArray("Sending data\n\r", 14); P1OUT |= BIT0; // Turn on RED to indicate start of conversion ADC10CTL0 &= ~ENC; ADC10CTL0 = ADC10ON; ADC10CTL1 = INCH_5 + SHS_0 + ADC10DIV_3 + ADC10SSEL_3 +CONSEQ_2 ; // Select input channel 5. Sample and hold source (0: ADCSCbit). ADC10CLK Divider (0: /1). ADC Clock source (0: internal 5MHz oscillator). Repeat single channel ADC10AE0 |= BIT5; // Enable P1.5 as ADC input while(ADC10CTL1 & ADC10BUSY); P1OUT ^= BIT0; ADC10DTC0 = ADC10CT; // Continuous Transfer mode ADC10DTC1 = 255; ADC10SA = data; ADC10CTL0 = SREF_0 + ADC10SHT_1 + MSC + ADC10ON + ADC10IE; // Reference Voltage (0: Vcc & Vss). Sample and hold time (0: 4 ADC clk cycles). Enable continous sampling. Turn ADC on. Enable ADC interrupt ADC10CTL0 |= ENC + ADC10SC; // ADC Sampling and conversion start } // end of if Statement } // ADC10 interrupt service routine #pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR (void) { //ADC10CTL0 &= ~ENC; // Switch off conversion UARTSendArray(data,2*SAMPLES); // sends the data it has recorded P1OUT &= ~BIT0; // Turn off LED1 to indicate transmission complete //volatile unsigned int data[SAMPLES]; // define data array }
// Initialising Clock on MSP
void InitialisePorts(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_16MHZ; // Set DCO to 16MHz DCOCTL = CALDCO_16MHZ; P1DIR |= BIT0; // Set the LED on P1.0 outputs P1OUT &= ~BIT0; // Turn on LED1 to indicate start of conversion }
One potential change I could make is to allow the MSP430 to receive the number of acquisitions the user would like to make over UART, so it does not have to continuously cycle, this will allow both devices to know what to send and expect. This may also speed up interpretation in MATLAB.
// MATLAB Code, the number of data acquisitions to occur is defined by the input parameter x,
Nstring = 14;
Nintdata = 248*x; obj=serial('COM8','BaudRate', 9600,'Terminator', 'LF/CR','InputBufferSize',2*Nintdata+Nstring); fopen(obj); finishup = onCleanup(@() fclose(obj)); command = 'D'; fprintf(obj,command); % Send D down the UART string = fscanf(obj,'%c',14); disp(['Response: ' string(1:end-2)]) disp(' '); if strcmp(string(1:end-2),'Sending data'), %pause(0.2); % watch out data = fread(obj,Nintdata,'uint16'); N=length(data); disp([num2str(N) ' integers received']); Fs = 10e3/0.044; time = (0:N-1)./Fs; figure(1); plot(time,data); xlabel('Time (s)'); ylabel('Amplitude'); grid on; y = data; end
The irregularities I observe is that my sample rate is significantly slower, about 500Hz down by a factor of 100, I have tried playing around with the clock divider but it doesnt make a difference even though when I had my code to do a single acquisition it worked just fine. Additionally in MATLAB it takes a while to process the information I suspect it is due to not receiving the data on time or the data sent over UART is not cleaned correctly. When the data is obtained the plot comes out a bit strange the first 248 samples (first acquisition) is just fine in terms of magnitude and accuracy. However when the next acquisition is made the magnitude is completely incorrect (10^4). It will then return to the correct magnitude and accuracy on the next 248 bits. This occurs on an odd even basis. Again I know the problem is either in the memory of the ADC not been cleared correctly after it has sent, I tried re declaring the data array but it doesn't make a difference. Or in the reading of the integers sent over UART in MATLAB.