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.
Part Number: MSP430-ADC10
Hi everyone !
This is my first issue on the forum. I am facing a problem on my robotic project with MSP430. So, i want to read ADC values from multiple pins on MSP. When i chose PIN0 for starting pin with PIN1, PIN2, PIN3, everything is okay, reading is okay, values are okay. Besides that i want to transfer these data with bluetooth module so i cannot use PIN1 and PIN2(PIN1 and PIN2 is reserved for UART communication). So, i modified the pin configurations and necessary register change and chose PIN0, PIN3, PIN4, PIN5 to read the ADC values but the code which is working before, didn't work. I am sharing the code below, if you faced this type of problem, please contact me. Thank you for your attention.
Best Regards
Hi Caleb,
Sorry for carelessness. I am using MSP430 G2553 and I solve this problem by using single channel, single conversion mode for each PIN but nevertheless i am sharing first code which is not working and actually i want to know why it is not working or why msp430g2553 cannot measure the voltage from any PIN interval. Thank you for your attention Caleb !
"The First Code That Does Not Work Properly"
#include <msp430g2553.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
unsigned int Voltage[4];
void PIN_Config(void);
void ADC_Config(void);
void ADC_Reading(void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
PIN_Config();
ADC_Config();
while(1){
ADC_Reading();
_enable_interrupts();
}
}
void PIN_Config(void){
P1SEL = BIT1 | BIT2;
P1SEL2 = BIT1 | BIT2;
P1DIR = 0xF0;
P1OUT &= ~0x00;
P1IE |= 0x0F;
P1IES |= 0x0F;
P1IFG = 0x00;
P2DIR = 0xFF;
P2OUT &= ~0x00;
}
void ADC_Config(void){
ADC10CTL1 = INCH_5+ CONSEQ_3;
ADC10CTL0 = SREF_0 + ADC10ON + ADC10IE + MSC;
ADC10DTC0 = ADC10CT;
ADC10DTC1 = 0x4;
ADC10AE0 |= 0x39;
}
void ADC_Reading(void){
ADC10CTL0 &= ~ENC;
while(ADC10CTL1 & BUSY);
ADC10SA = (unsigned int)Voltage;
ADC10CTL0 |= ENC + ADC10SC;
}
"The Second Code That Works Perfectly"
#include <msp430g2553.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
unsigned int X_Axis;
unsigned int Y_Axis;
unsigned int Z_Axis;
unsigned int Gripper;
void PIN_Config(void);
void ADC_Config(void);
void ADC_Reading_X_Axis(void);
void ADC_Reading_Y_Axis(void);
void ADC_Reading_Z_Axis(void);
void ADC_Reading_Gripper(void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
PIN_Config();
ADC_Config();
while(1){
ADC_Reading_X_Axis();
ADC_Reading_Y_Axis();
ADC_Reading_Z_Axis();
ADC_Reading_Gripper();
_enable_interrupts();
}
}
void PIN_Config(void){
P1SEL = BIT1 | BIT2;
P1SEL2 = BIT1 | BIT2;
P2DIR = 0xFF;
P2OUT &= ~0x00;
}
void ADC_Config(void){
ADC10CTL0 = SREF_0 + ADC10ON + ADC10IE;
}
void ADC_Reading_X_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_0 + CONSEQ_0;
ADC10AE0 |= BIT0;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
X_Axis = ADC10MEM;
}
void ADC_Reading_Y_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_3 + CONSEQ_0;
ADC10AE0 |= BIT3;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Y_Axis = ADC10MEM;
}
void ADC_Reading_Z_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_4 + CONSEQ_0;
ADC10AE0 |= BIT4;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Z_Axis = ADC10MEM;
}
void ADC_Reading_Gripper(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_5 + CONSEQ_0;
ADC10AE0 |= BIT5;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Gripper = ADC10MEM;
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
}
Hi Can,
Can you be more specific about the issue the incorrect code is causing? Are you seeing bad values, no values, etc? Also, have you looked at the MSP430Ware examples for the MSP430G2553? Example msp430g2x33_adc10_14.c shows how to use repeat sequence of channels mode in a way that is very similar to what you are trying to accomplish.
Best regards,
Caleb Overbay
Hi Can,
A few comments on the code that is not working properly:
Best regards,
Caleb Overbay
Thank you for your attention again Caleb but i accomplished the problem using second code that i share above. Nevertheless the situation, that you mention your last comment which is related to incorrect reading, happened to me. In the below code i reading correct values from Y, Z and Gripper but X is not correct. I guess ADC has not enough time to measure the correct value but this is only happen for X (which is measured first). How can i fix it? I have "while(ADC10CTL1 & BUSY);" line before every conversion. Is not it enough? Besides i am receiving "Isr16.asm" warning while code is running sometimes. What does it mean and how can i fix it? As a last thing, what did you mean with "I see you've enabled interrupts for the ADC but are not using them." ? Thank you for your response again.
#include <msp430g2553.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
int X_Axis;
int Y_Axis;
int Z_Axis;
int Gripper;
void PIN_Config(void);
void Time_Config(void);
void UART_Config(void);
void ADC_Config(void);
void ADC_Reading_X_Axis(void);
void ADC_Reading_Y_Axis(void);
void ADC_Reading_Z_Axis(void);
void ADC_Reading_Gripper(void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
PIN_Config();
Time_Config();
UART_Config();
ADC_Config();
while(1){
ADC_Reading_X_Axis();
ADC_Reading_Y_Axis();
ADC_Reading_Z_Axis();
ADC_Reading_Gripper();
_enable_interrupts();
}
}
void PIN_Config(void){
P1SEL = BIT1 | BIT2;
P1SEL2 = BIT1 | BIT2;
P2DIR = 0xFF;
P2OUT &= ~0x00;
}
void Time_Config(void){
DCOCTL = 0;
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
}
void UART_Config(void){
UCA0CTL1 |= UCSSEL_2;
UCA0BR0 = 104;
UCA0BR1 = 0;
UCA0MCTL = UCBRS_1;
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0TXIE;
}
void ADC_Config(void){
ADC10CTL0 = SREF_0 + ADC10ON + ADC10IE;
}
void ADC_Reading_X_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_0 + CONSEQ_0;
ADC10AE0 |= BIT0;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
X_Axis = ADC10MEM;
UCA0TXBUF = X_Axis;
}
void ADC_Reading_Y_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_3 + CONSEQ_0;
ADC10AE0 |= BIT3;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Y_Axis = ADC10MEM;
UCA0TXBUF = Y_Axis;
}
void ADC_Reading_Z_Axis(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_4 + CONSEQ_0;
ADC10AE0 |= BIT4;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Z_Axis = ADC10MEM;
UCA0TXBUF = Z_Axis;
}
void ADC_Reading_Gripper(void){
ADC10CTL0 &= ~ENC;
ADC10CTL1 = INCH_5 + CONSEQ_0;
ADC10AE0 |= BIT5;
ADC10CTL0 |= ENC + ADC10SC;
while(ADC10CTL1 & BUSY);
Gripper = ADC10MEM;
UCA0TXBUF = Gripper;
}
#pragma vector = ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
ADC10MEM = (ADC10MEM >> 7);
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
IE2 &= ~UCA0TXIE;
}
Hi Can,
All of my previous comments were to answer your question of why your first "non-working" set of code was failing. I still recommend trying to accomplish this task with a sequence of conversions instead of the single channel approach you've created. The single channel approach will take a much longer time to execute.
Now to answer your question as to why the X reading on the single channel approach is not working. Why are you shifting the ADC10MEM register in the ADC ISR? I suspect this is the cause of your issue. It seems to serve no purpose in the code and if the ISR executes before ADC_Reading_XXXX() it will corrupt your results. The approach you're using with "while(ADC10CTL1 & BUSY);" is a polling implementation and does not require the use of interrupts. If you don't intend to use ADC interrupts, you should disable them in the AADC10CTL0 register. Also, try increasing the sample and hold time to 8 ADC clock cycles from the 4 that you currently have it set to.
Finally, please take a look at the ADC code examples provided in MSP430Ware. They show the proper use of interrupts for an application just like this one.
Best regards,
Caleb Overbay
Hi Can,
Using the following code I am not seeing the issue you're describing. When experiencing the issue are you looking at the X_Axis, Y_Axis, etc variables in the debugger of CCS or are you trying to view them via the terminal? I haven't debugged your UART code but from a quick glance I see there could be possible issues there as well.
#include <msp430.h> #include <stdlib.h> #include <stdio.h> #include <signal.h> int X_Axis; int Y_Axis; int Z_Axis; int Gripper; void PIN_Config(void); void Time_Config(void); void UART_Config(void); void ADC_Config(void); void ADC_Reading_X_Axis(void); void ADC_Reading_Y_Axis(void); void ADC_Reading_Z_Axis(void); void ADC_Reading_Gripper(void); void main(void) { WDTCTL = WDTPW + WDTHOLD; PIN_Config(); Time_Config(); UART_Config(); ADC_Config(); while(1) { ADC_Reading_X_Axis(); ADC_Reading_Y_Axis(); ADC_Reading_Z_Axis(); ADC_Reading_Gripper(); _enable_interrupts(); } } void PIN_Config(void){ P1SEL = BIT1 | BIT2; P1SEL2 = BIT1 | BIT2; P2DIR = 0xFF; P2OUT &= ~0x00; } void Time_Config(void){ DCOCTL = 0; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; } void UART_Config(void){ UCA0CTL1 |= UCSSEL_2; UCA0BR0 = 104; UCA0BR1 = 0; UCA0MCTL = UCBRS_1; UCA0CTL1 &= ~UCSWRST; IE2 |= UCA0TXIE; } void ADC_Config(void){ ADC10CTL0 = SREF_0 + ADC10ON + ADC10SHT_1; } void ADC_Reading_X_Axis(void){ ADC10CTL0 &= ~ENC; ADC10CTL1 = INCH_0 + CONSEQ_0; ADC10AE0 |= BIT0; ADC10CTL0 |= ENC + ADC10SC; while(ADC10CTL1 & BUSY); X_Axis = ADC10MEM; UCA0TXBUF = X_Axis; } void ADC_Reading_Y_Axis(void){ ADC10CTL0 &= ~ENC; ADC10CTL1 = INCH_3 + CONSEQ_0; ADC10AE0 |= BIT3; ADC10CTL0 |= ENC + ADC10SC; while(ADC10CTL1 & BUSY); Y_Axis = ADC10MEM; UCA0TXBUF = Y_Axis; } void ADC_Reading_Z_Axis(void){ ADC10CTL0 &= ~ENC; ADC10CTL1 = INCH_4 + CONSEQ_0; ADC10AE0 |= BIT4; ADC10CTL0 |= ENC + ADC10SC; while(ADC10CTL1 & BUSY); Z_Axis = ADC10MEM; UCA0TXBUF = Z_Axis; } void ADC_Reading_Gripper(void){ ADC10CTL0 &= ~ENC; ADC10CTL1 = INCH_5 + CONSEQ_0; ADC10AE0 |= BIT5; ADC10CTL0 |= ENC + ADC10SC; while(ADC10CTL1 & BUSY); Gripper = ADC10MEM; UCA0TXBUF = Gripper; } #pragma vector=USCIAB0TX_VECTOR __interrupt void USCI0TX_ISR(void) { IE2 &= ~UCA0TXIE; }
Best regards,
Caleb Overbay
Hi Caleb,
Of course, i am checking them in the debugger, Expressions window. If i summarize my project, i have 2 axis 2 joy stick module which have 0V to 3.3V output with feeding MSP430 Vcc and i made some calibrations to easily control the motors which MSP432 will drive, so this is why i used bit shifting. This gives me a value from 0 to 7 for each axis. If it is 0, it means that the axis output is 0V or ADC10MEM value is 0; if it is 7, it means that the axis output is 3.3v or ADC10MEM is 1023. Unfortunately, although all axis except X_Axis gives 7 or 1023 or 3.3V when bring them to the their maximum positions, X_Axis cannot reach the its maximum value. I am sharing screenshot of debugger window and the values. Besides, the UART section is working i guess, and i am checking UCA0TXBUF in the registers window but if you are thinking something is wrong, please share to me.
Best Regards
Above figure's values on the right are related to central position joy stick module. While three axis are giving 4, the X_Axis is 3. Below figure's values are related to maximum position of joy sticks and as it can be seen, X_Axis is 6 and the others are 7.
Hi Can,
I apologize for the delayed response as I've been out a few days. Now that you've described why the shift is present, I think I'm understanding your issue a little better. Let's first tackle the UART code.
When you take an ADC measurement, you immediately put the result into TXBUF. I recommend checking the TX interrupt flag before writing anything to this buffer. By checking this first, you are ensuring that you're not overwriting something that is in the buffer that hasn't been sent yet. Adding while(IFG2 & UCA0TXIFG); before writing to the buffer should do the trick. Also, I see you've enabled TX interrupts in UART_Config() with the line IE2 |= UCA0TXIE; but then disable them when you get into the ISR with the line IE2 &= ~UCA0TXIE;. The approach you've taken here doesn't require interrupts so you could simply disable UART interrupts and remove the ISR from your code. Again here, I have to refer you to MSP430Ware with UART examples that show best practices.
Finally, I'm still not seeing the ADC results you are. With the same code and applying VCC to X_Axis, I am consistently getting the expected result of 7 after shifting ADC10MEM right by 7. There could be several factors that are causing this difference in measurement. Section 22.2.5.1 of the user's guide for the MSP430G2553 provides a formula to calculate the minimum sampling time. Please review it and see if you are meeting this specification for the X_Axis input.
Best regards,
Caleb Overbay
**Attention** This is a public forum