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.
why do I always get the strange problems.
I am converting voltage from 4 potentiometers into values as inputs on my board as a sequence of channels single conversion. and am getting not what I expect on 1 of the 4 channels. I verified the voltage on the pin was at 3.27V (vcc is 3.3 which is the reference) and 3 of the 4 channels are giving 1024, but channel 2 is spitting back 709.
Now as a test I downloaded my ADC test program to verify the hardware. and it converts properly and all 4 channels come back 0-1024 like I expect. so I know that the hardware is working correctly
so my next thought was a software issue however this is where it gets weird. I have 2 boards built up ready to go. on one running my final program, channel 2 comes back 709 even though i know the voltage at the pin is 3.27. so i initially starting trying to find out what was wrong with the code for that channel. but on a whim I loaded the EXACT same program into the second board and its channel 2 is converting just fine, however its channel 3, and channel 4 are not converting correctly.
channel 2 is reporting 709 - 192 when the voltage on the pin is 3.27v - 0v and 476 when its roughly centered so it looks linear
I verified the hardware was working on both boards using the ADC test program so i know the hardware is good. and I know it is not a channel specific thing in the software, because channel 3 and 4 convert correctly on one board. and channel 2 converts correctly on the other board running the exact same software.
the only thing i can think of is the channels are not "next to each other" is is P1.0, P1.1, P1.3, and P1.6. so I am having it convert all 8 channels and just reading the values I want from the array.
I verified the register settings between the ADC test program and my code and the registers are setup corectly on both Port 1, and the ADC10 registers
#include <msp430.h> /* * main.c */ unsigned int ADCOut[8] = {0,0,0,0,0,0,0,0}; unsigned int ADCOutF[4] = {0,0,0,0}; float ADCFinal = 0; void main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; // DCOCTL = CALDCO_1MHZ; // set main internal oscillator for 1 MHz BCSCTL2 = DIVM_3+DIVS_3; // set system clock to 1 MHz / 8 = 125 kHz BCSCTL3 = LFXT1S_2; // start Low speed clock TA0CCTL0 = CCIE; // enable interrupt from the timer TA0CTL = TASSEL_2 + ID_3 + MC_1; // set timer to run from the system clock 125 kHz / 8 = 15.6 kHz TA0CCR0 = 2000; // set timer time to 65535 counts / 15.6 kHz = 4.2 seconds. ADC10CTL1=INCH_6 + CONSEQ_1 + ADC10SSEL_2; // set ADC to read A0 (P1.0) and time off of the main system clock ADC10AE0=BIT0+BIT1+BIT3+BIT6; // enable Analog on A0 (P1.0) ADC10DTC1 = 7; // set ADC for single block transfer ADC10DTC0 = ADC10CT; // set ADC for continuous data tranfer ADC10SA = (unsigned int)ADCOut; // target data transfer to first address of "ADCOut" array ADC10CTL0=SREF_0+ADC10ON+MSC+ENC+ADC10SC; // set ADC voltage reference to Gnd, and VCC, turn on the ADC, sample automatically, enable conversion, start the ADC __enable_interrupt(); // enable global interrupts while (1){ _BIS_SR(LPM1_bits + GIE); // MAIN CYCLE, when not performing an interrupt, put processor to sleep } } #pragma vector=TIMER0_A0_VECTOR __interrupt void timerA0_isr(void) //Timer interrupt { P1OUT ^= BIT6; // Toggle pin 6 to track cycles on oscilloscope ADC10CTL0 |= ENC+ADC10SC; // trigger a new ADC cycle while(ADC10CTL1&BUSY); // wait for ADC to complete. ADCOutF[0] = ADCOut[0]; ADCOutF[1] = ADCOut[3]; ADCOutF[2] = ADCOut[5]; ADCOutF[3] = ADCOut[6]; }
and here is the final software that I loaded I
the ADC function is near the top ADCCheck(int);
//*********************************************************** // runfast.c - Using 12MHZ external square wave clock as LFXTCLK // source MCLK/SMCLK from 12MHZ wave and blink led // at 60Hz // // Use an external clock ( I'm using an attiny running at 12.00 MHZ // with the CLKOUT fuse enabled ) as the MCLK/SMCLK for the MSP430. // I've been told you could also use an external oscillator like an // ECS-100A-160. I ordered some of these to verify. // // LFXT1 oscillator logic level square wave input frequency, LF mode // // XIN - external clock in from attiny CLKOUT pin ( set avr fuse to get clock ) // XOUT - NC // P1.0 - led on until OSCFault cleared // P1.4 - SMCLK frequency, measuer with multimeter/oscope // P1.6 - 60Hz led flash, measure with multimeter/oscope // //*********************************************************** #include <msp430g2553.h> //#include <math.h> //int tmp = 0; #define dataClock BIT4; #define dataOut BIT5; #define outputClock BIT7; int ledsetnum = 0; //int offset = 0; unsigned int index = 0; int subSec = 0; long secondsCH1 = 0; long secondsCH2 = 0; long secondsCH3 = 0; long secondsCH4 = 0; long secondsCH1tmp = 0; long secondsCH2tmp = 0; long secondsCH3tmp = 0; long secondsCH4tmp = 0; long secondsConvert = 0; int startupDelay = 5; int relayBitMask = 0; int RelayState = 0; int RelayQue = 0; int RelayServiced = 0; int RelayZeroed = 0; unsigned int ADCOut[8] = {0,0,0,0,0,0,0,0}; unsigned int ADCOutF[4] = {0,0,0,0}; int TMPOut = 0; int TMPRen = 0; int TMPDir = 0; float SecondsMath = 0; int InputTimer = 0; int ledset[16] = { 0,0,0, 0,0,0, 0,0,0, 0,0,0 }; void LEDWrite(void); void setLED(int, int, int, int); void ledUpdate(void); void Timer_ISR(void); void init_Timer1_A0(void); void relaySet(int); void RelayCheck(void); void RelayService(void); void relayClear (void); void ADCCheck(int); int ledTarget[16] = { 32,32,32, 0,0,0, 0,0,0, 0,0,0 }; void ADCCheck(int num){ if (num == 0){ ADC10CTL0 |= ENC+ADC10SC; // trigger a new ADC cycle while(ADC10CTL1&BUSY); // wait for ADC to complete. secondsConvert = 1024-ADCOut[0]; SecondsMath = 300 + (secondsConvert * 3.25); secondsCH1 = SecondsMath; //(ADC6 * 3.25) + 5 minutes } if (num == 1){ ADC10CTL0 |= ENC+ADC10SC; // trigger a new ADC cycle while(ADC10CTL1&BUSY); // wait for ADC to complete. secondsConvert = 1024-ADCOut[3]; SecondsMath = 300 + (secondsConvert * 3.25); secondsCH2 = SecondsMath; //(ADC3 * 3.25) + 5 minutes } if (num == 2){ ADC10CTL0 |= ENC+ADC10SC; // trigger a new ADC cycle while(ADC10CTL1&BUSY); // wait for ADC to complete. secondsConvert = 1024-ADCOut[5]; SecondsMath = 300 + (secondsConvert * 3.25); secondsCH3 = SecondsMath; //(ADC1 * 3.25) + 5 minutes } if (num == 3){ ADC10CTL0 |= ENC+ADC10SC; // trigger a new ADC cycle while(ADC10CTL1&BUSY); // wait for ADC to complete. secondsConvert = 1024-ADCOut[6]; SecondsMath = 300 + (secondsConvert * 3.25); secondsCH4 = SecondsMath; //(ADC0 * 3.25) + 5 minutes } } void RelayService(void){ RelayServiced = 0; if ((RelayQue == 0x00)){ relayClear(); } if ((RelayQue & BIT0)){ RelayQue &= ~BIT0; RelayServiced = 1; relaySet(0); } if ((RelayQue & BIT1) && (RelayServiced == 0)){ RelayQue &= ~BIT1; RelayServiced = 1; relaySet(1); } if ((RelayQue & BIT2) && (RelayServiced == 0)){ RelayQue &= ~BIT2; RelayServiced = 1; relaySet(2); } if ((RelayQue & BIT3) && (RelayServiced == 0)){ RelayQue &= ~BIT3; RelayServiced = 1; relaySet(3); } if ((RelayQue & BIT4) && (RelayServiced == 0)){ RelayQue &= ~BIT4; RelayServiced = 1; relaySet(4); } if ((RelayQue & BIT5) && (RelayServiced == 0)){ RelayQue &= ~BIT5; RelayServiced = 1; relaySet(5); } if ((RelayQue & BIT6) && (RelayServiced == 0)){ RelayQue &= ~BIT6; RelayServiced = 1; relaySet(6); } if ((RelayQue & BIT7) && (RelayServiced == 0)){ RelayQue &= ~BIT7; RelayServiced = 1; relaySet(7); } } void RelayCheck(void){ int i = 0; int j = 0; RelayState = 0; P2SEL &= ~BIT7; P2OUT |= BIT4; P2OUT &= ~(BIT5+BIT7); P2DIR |= BIT4; P2DIR &= ~(BIT5+BIT7); P2REN &= ~BIT4; P2REN |= BIT5+BIT7; i = 1000; j = 0; while (i>0){ i-= 1; if (P2IN & BIT5){ j += 1; } } if (j > 500){ RelayState |= BIT2; } i = 1000; j = 0; while (i>0){ i-= 1; if (P2IN & BIT7){ j += 1; } } if (j > 500){ RelayState |= BIT1; } P2OUT &= ~(BIT4+BIT7); P2OUT |= BIT5; P2DIR &= ~(BIT4+BIT7); P2DIR |= BIT5; P2REN |= BIT4; P2REN &= ~(BIT5+BIT7); i = 1000; j = 0; while (i>0){ i-= 1; if (P2IN & BIT4){ j += 1; } } if (j > 500){ RelayState |= BIT3; } P2OUT &= ~(BIT4+BIT5); P2OUT |= BIT7; P2DIR &= ~(BIT4+BIT5); P2DIR |= BIT7; P2REN |= BIT4; P2REN &= ~(BIT5+BIT7); i = 1000; j = 0; while (i>0){ i-= 1; if (P2IN & BIT4){ j += 1; } } if (j > 500){ RelayState |= BIT0; } } void relayClear (void){ P1OUT &= ~dataOut; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= outputClock; P1OUT &= ~outputClock; } void relaySet(int relayReq){ // relay coil 0-7 relayReq &= 0x07; relayBitMask = 1; relayBitMask = relayBitMask << relayReq; if (relayBitMask & BIT0){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT1){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT2){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT3){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT4){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT5){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT6){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; if (relayBitMask & BIT7){P1OUT |= dataOut;} else {P1OUT &= ~dataOut;} P1OUT |= dataClock; P1OUT &= ~dataClock; P1OUT |= outputClock; P1OUT &= ~outputClock; } void setLED(int setR, int setG, int setB, int setNum) { setR &= 0xff; //clip red to 0-255 setG &= 0xff; //clip green to 0-255 setB &= 0xff; //clip blue to 0-255 setNum &= 0x03; //clip led num to 0-3 unsigned int setIndex = setNum + setNum + setNum; ledTarget[setIndex]=setR; ledTarget[setIndex+1]=setG; ledTarget[setIndex+2]=setB; } void ledUpdate(void) { unsigned int i =0; int change = 0; while (i < 16){ if (ledset[i] < ledTarget[i]){ ledset[i] += 1; change = 1; } if (ledset[i] > ledTarget[i]){ ledset[i] -= 1; change = 1; } i+= 1; } if (change){ LEDWrite(); } } void LEDWrite(void) { int i = 0; int ledTemp; P1SEL |= BIT2; P1SEL2 |= BIT2; ledsetnum = 0; index = 0; while (ledsetnum<4){ i=0; index = ledsetnum + ledsetnum + ledsetnum; ledTemp = ledset[index+1]; while (i<8){ while ((IFG2 & UCA0TXIFG)==0); if (ledTemp & BIT7){ UCA0TXBUF = 63; } else { UCA0TXBUF = 3; } ledTemp = ledTemp << 1; i++; } ledTemp = ledset[index]; i=0; while (i<8){ while ((IFG2 & UCA0TXIFG)==0); if (ledTemp & BIT7){ UCA0TXBUF = 63; } else { UCA0TXBUF = 3; } ledTemp = ledTemp << 1; i++; } ledTemp = ledset[index+2]; i=0; while (i<8){ while ((IFG2 & UCA0TXIFG)==0); if (ledTemp & BIT7){ UCA0TXBUF = 63; } else { UCA0TXBUF = 3; } ledTemp = ledTemp << 1; i++; } ledsetnum += 1; } } #pragma vector=TIMER1_A0_VECTOR __interrupt void Timer_ISR(void){ //P3OUT |= BIT0; ledUpdate(); subSec += 1; if ((subSec & BIT0) && (startupDelay == 0)){ RelayService(); } if (subSec >= 100) { subSec = 0; RelayCheck(); if (startupDelay > 0){ startupDelay -= 1; } else { int i = 0; int j= 0; i = 1000; j = 0; while (i > 0){ i -= 1; if (!(P3IN & BIT0) || !(P3IN & BIT1)){ j += 1; } } if (j > 500){ ADCCheck(0); } i = 1000; j = 0; while (i > 0){ i -= 1; if (!(P3IN & BIT2) || !(P3IN & BIT3)){ j += 1; } } if (j > 500){ ADCCheck(1); } i = 1000; j = 0; while (i > 0){ i -= 1; if (!(P3IN & BIT4) || !(P3IN & BIT5)){ j += 1; } } if (j > 500){ ADCCheck(2); } i = 1000; j = 0; while (i > 0){ i -= 1; if (!(P3IN & BIT6) || !(P3IN & BIT7)){ j += 1; } } if (j > 500){ ADCCheck(3); } if (secondsCH1 > 0){ if ((P3IN & BIT1) && (P3IN & BIT0)){ secondsCH1 -= 1; if (secondsCH1 > 180){ setLED(0, 32, 0, 0); } else if (secondsCH1 < 180 && secondsCH1 > 120 ) { if (secondsCH1 & BIT0){ setLED(32, 32, 0, 0); if ((secondsCH1 & 0x0f) == 15){ P2OUT |= BIT1; } } else { setLED(0, 32, 0, 0); P2OUT &= ~BIT1; } } else if (secondsCH1 < 120 && secondsCH1 > 60 ) { if (!(secondsCH1 & BIT0)){ setLED(32, 32, 0, 0); if ((secondsCH1 & 0x0f) == 14){ P2OUT |= BIT1; } } else { setLED(0, 0, 0, 0); P2OUT &= ~BIT1; } } else { setLED(32, 32, 0, 0); P2OUT |= BIT1; } } else { setLED(0, 32, 32, 0); P2OUT &= ~BIT1; } if (!(RelayState & BIT0)){ RelayQue |= BIT0; } } else { setLED(32, 0, 0, 0); P2OUT &= ~BIT1; if (RelayState & BIT0){ RelayQue |= BIT1; } } if (secondsCH2 > 0){ if ((P3IN & BIT3) && (P3IN & BIT2)){ secondsCH2 -= 1; if (secondsCH2 > 180){ setLED(0, 32, 0, 1); } else if (secondsCH2 < 180 && secondsCH2 > 120 ) { if (secondsCH2 & BIT0){ setLED(32, 32, 0, 1); if ((secondsCH2 & 0x0f) == 15){ P2OUT |= BIT0; } } else { setLED(0, 32, 0, 1); P2OUT &= ~BIT0; } } else if (secondsCH2 < 120 && secondsCH2 > 60 ) { if (!(secondsCH2 & BIT0)){ setLED(32, 32, 0, 1); if ((secondsCH2 & 0x0f) == 14){ P2OUT |= BIT0; } } else { setLED(0, 0, 0, 1); P2OUT &= ~BIT0; } } else { setLED(32, 32, 0, 1); P2OUT |= BIT0; } } else { setLED(0,32,32, 1); P2OUT &= ~BIT0; } if (!(RelayState & BIT0)){ RelayQue |= BIT2; } } else { setLED(32, 0, 0, 1); P2OUT &= ~BIT0; if (RelayState & BIT1){ RelayQue |= BIT3; } } if (secondsCH3 > 0){ if ((P3IN & BIT5) && (P3IN & BIT4)){ secondsCH3 -= 1; if (secondsCH3 > 180){ setLED(0, 32, 0, 2); } else if (secondsCH3 < 180 && secondsCH3 > 120 ) { if (secondsCH3 & BIT0){ setLED(32, 32, 0, 2); if ((secondsCH3 & 0x0f) == 15){ P2OUT |= BIT3; } } else { setLED(0, 32, 0, 2); P2OUT &= ~BIT3; } } else if (secondsCH3 < 120 && secondsCH3 > 60 ) { if (!(secondsCH3 & BIT0)){ setLED(32, 32, 0, 2); if ((secondsCH3 & 0x0f) == 14){ P2OUT |= BIT3; } } else { setLED(0, 0, 0, 2); P2OUT &= ~BIT3; } } else { setLED(32, 32, 0, 2); P2OUT |= BIT3; } } else { setLED(0,32,32, 2); P2OUT &= ~BIT3; } if (!(RelayState & BIT2)){ RelayQue |= BIT4; } } else { setLED(32, 0, 0, 2); P2OUT &= ~BIT3; if (RelayState & BIT2){ RelayQue |= BIT5; } } if (secondsCH4 > 0){ if ((P3IN & BIT7) && (P3IN & BIT6)){ secondsCH4 -= 1; if (secondsCH4 > 180){ setLED(0, 32, 0, 3); } else if (secondsCH4 < 180 && secondsCH4 > 120 ) { if (secondsCH4 & BIT0){ setLED(32, 32, 0, 3); if ((secondsCH4 & 0x0f) == 15){ P2OUT |= BIT2; } } else { setLED(0, 32, 0, 3); P2OUT &= ~BIT2; } } else if (secondsCH4 < 120 && secondsCH4 > 60 ) { if (!(secondsCH4 & BIT0)){ setLED(32, 32, 0, 3); if ((secondsCH4 & 0x0f) == 14){ P2OUT |= BIT2; } } else { setLED(0, 0, 0, 3); P2OUT &= ~BIT2; } } else { setLED(32, 32, 0, 3); P2OUT |= BIT2; } } else { setLED(0,32,32, 3); P2OUT &= ~BIT2; } if (!(RelayState & BIT3)){ RelayQue |= BIT6; } } else { setLED(32, 0, 0, 3); P2OUT &= ~BIT2; if (RelayState & BIT3){ RelayQue |= BIT7; } } } } } void init_Timer1_A0(void) { TA1CCR0 = 2499; // PWM Period TA1CCTL0 = CCIE;//CCIE; TA1CCTL1 = OUTMOD_1; // CCR1 reset/set TA1CTL = TASSEL_1 + ID_3 + MC_1; // ACLK/8 = TA1CCR1=100; P1DIR |= BIT4; //P1SEL |= BIT4; } void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer DCOCTL = CALDCO_16MHZ; // Set DCOCLK to 16MHz BCSCTL1 = CALBC1_16MHZ; BCSCTL2 = SELM_3 + DIVM_0 + SELS + DIVS_0; // external clock, no dividers on clocks BCSCTL1 = XTS + DIVA_3; // XTS, ACLK @ 2mHZ BCSCTL3 = LFXT1S_3 | XCAP_0; // LFXT1 = 16MHZ source, No Capacitor UCA0CTL0 |= UCSYNC + UCMST; UCA0CTL1 |= UCSSEL_2; // Have USCI use System Master Clock: AKA core clk 1MHz UCA0BR0 = 3; // 1MHz 9600, see user manual UCA0BR1 = 0; // UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // Start USCI state machine P2DIR = 0x00; P3DIR = 0x00; P3REN = 0xFF; P3OUT = 0xFF; P1SEL = BIT2; P1SEL2 = BIT2; P1OUT &= ~(BIT4 + BIT5 + BIT7); P1DIR |= BIT4 + BIT5 + BIT7; P2DIR |= 0x0f; P2OUT &= ~0x0f; ADC10CTL1=INCH_6 + CONSEQ_1 + ADC10SSEL_2; // set ADC to read A0 (P1.0) and time off of the main system clock ADC10AE0=BIT0+BIT1+BIT3+BIT6; // enable Analog on A0 (P1.0) ADC10DTC1 = 7; // set ADC for single block transfer ADC10DTC0 = ADC10CT; // set ADC for continuous data tranfer ADC10SA = (unsigned int)ADCOut; // target data transfer to first address of "ADCOut" array ADC10CTL0=SREF_0+ADC10ON+MSC+ENC+ADC10SC; // not sure if this is needed while(IFG1 & OFIFG) { IFG1 &= ~OFIFG; // Clear OSCFault flag _delay_cycles(10000); // delay for flag and visibility } //__bis_SR_register(SCG0); // Stop DCO, we just use the LFXT1 which is // actually running at 16MHZ init_Timer1_A0(); _BIS_SR(GIE); RelayCheck(); if (RelayState & BIT0){ ADCCheck(0); RelayQue |= BIT0; } else { RelayQue |= BIT1; } if (RelayState & BIT1){ ADCCheck(1); RelayQue |= BIT2; } else { RelayQue |= BIT3; } if (RelayState & BIT2){ ADCCheck(2); RelayQue |= BIT4; } else { RelayQue |= BIT5; } if (RelayState & BIT3){ ADCCheck(3); RelayQue |= BIT6; } else { RelayQue |= BIT7; } while(1) { _BIS_SR(LPM1 + GIE); } }
i don't even know what to check at this point the hardware is good, the software i think is good but I don't understand the failure I am getting right now
**Attention** This is a public forum