|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
Lowest Current Consumption with ADC RunningHi~
I am doing some testing with the MSP430FG461x processor right now in an attempt to get the current consumption under 100 microamperes. The program uses the ADC to obtain temperature, then display it onto the LCD. Whenever I measure the current on the board, it shows up as lower 500 to upper 600 microamps. This is sounding an alarm in my head because 1) while not interrupting, the current should be MUCH lower than that (I measured it at 9 microamps before adding the ADC part) 2)I was told by someone else who's worked with this microprocessor before that for a program like this, the current consumption should stay under 100 microamps. I've pasted the code below. #include <Board.h> #include <LCD.h> #include "msp430xG46x.h" #include <stdlib.h> #include "string.h" #include <stdio.h> volatile unsigned int i,k; volatile unsigned int ADCresult; volatile unsigned long int DegC, DegF; int stringLength; char displayBuffer[10]; void ReverseArray(char*orig,unsigned short int b); //-------------------------------------------------------------------- --------- void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR = (0xff & ~(BIT0+BIT1)); // P1.0, P1.1 input, others output P1OUT = 0; P2DIR = (0xff & ~BIT5); // P2.5 must be input P2OUT = 0; P3DIR = (0xff & ~BIT5); // P3.5 must be high P3OUT = (BIT1 + BIT2); // '2013 could possibly tied these high P4DIR = 0xff; P4OUT = 0; P5DIR = 0xff; P5OUT = 0; P6DIR = 0xff; P6OUT = 0; P7DIR = 0xff; P7OUT = 0; P8DIR = 0xff; P8OUT = 0; P9DIR = 0xff; P9OUT = 0; P10DIR = 0xff; P10OUT = 0; FLL_CTL0 |= XCAP14PF; // Configure load caps TACTL = TASSEL_1 + TACLR; // Clock = ACLK (32768), clear TACCTL0 = CCIE; // CCR0 interrupt enabled TACCR0 = 32768-1; // #counts for 1s TACTL |= MC_1; // Setting mode bits starts timer while(1) {_BIS_SR(LPM3_bits + GIE);} // Enter LPM3 } //-------------------------------------------------------------------- --------- // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { initLCD_A(); dispChar(15,0); ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_7; // Turn ADC,ref on. Ref = 2.5V, sampling time ADC12CTL1 = SHP; // Use sampling timer ADC12MCTL0 = INCH_10 + SREF_1; // Select channel A10, Vref+ ADC12IE = 0x01; // Enable ADC12IFG.0 for (i = 0; i < 0x3600; i++); // Delay for reference start-up ADC12CTL0 |= ENC; // Enable conversions __enable_interrupt(); // Enable interrupts ADC12CTL0 |= ADC12SC; // Start conversion __bis_SR_register(LPM0_bits); // Enter LPM0 // DegC = (Vsensor - 986mV)/3.55mV // Vsensor = (Vref)(ADCresult)/4095) // DegC -> ((ADCresult - 1615)*704)/4095 __no_operation(); // SET BREAKPOINT sprintf(displayBuffer,"%ld",DegF); stringLength = strlen(displayBuffer); ReverseArray(displayBuffer,stringLength); for(i=0;i<stringLength;i++) {dispChar(displayBuffer[i]-0x30, i+1);} } //-------------------------------------------------------------------- --------- #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR(void) { ADCresult = ADC12MEM0; // Move results, IFG is cleared DegC = ((((long)ADCresult-1615)*704)/4095); DegF = ((DegC * 9/5)+32); // Calculate DegF __no_operation(); // SET BREAKPOINT __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 } //-------------------------------------------------------------------- --------- void ReverseArray(char*orig,unsigned short int b) { unsigned short int a; int swap; for(a=0;a<--b;a++) //increment a and decrement b until they meet eachother { swap=orig[a]; //put what's in a into swap space orig[a]=orig[b]; //put what's in b into a orig[b]=swap; //put what's in the swap (a) into b } } |
|
|
Re: Lowest Current Consumption with ADC RunningI think your TimerA0 isr is faulty. You should have moved most of that
to the while(1) loop in main after "_BIS_SR(LPM3_bits + GIE);". "for (i = 0; i < 0x3600; i++);" wasts energy. "__bis_SR_register(LPM0_bits);" will not make your TimerA0 isr enter LPM0. Nesting the ADC12 interrupt inside TimerA0 interrupt is unnecessary and incorrectly done. Calling library routines inside isr may cause problems too. --- In msp430@..., "emil.marinov" <emil.marinov@...> wrote: > > Hi~ > > I am doing some testing with the MSP430FG461x processor right now in > an attempt to get the current consumption under 100 microamperes. > The program uses the ADC to obtain temperature, then display it onto > the LCD. Whenever I measure the current on the board, it shows up as > lower 500 to upper 600 microamps. This is sounding an alarm in my > head because 1) while not interrupting, the current should be MUCH > lower than that (I measured it at 9 microamps before adding the ADC > part) 2)I was told by someone else who's worked with this > microprocessor before that for a program like this, the current > consumption should stay under 100 microamps. I've pasted the code > below. > > > > > > > #include <Board.h> > #include <LCD.h> > #include "msp430xG46x.h" > #include <stdlib.h> > #include "string.h" > #include <stdio.h> > > > volatile unsigned int i,k; > volatile unsigned int ADCresult; > volatile unsigned long int DegC, DegF; > int stringLength; > char displayBuffer[10]; > > void ReverseArray(char*orig,unsigned short int b); > //-------------------------------------------------------------------- > --------- > void main(void) > { > WDTCTL = WDTPW + WDTHOLD; // Stop WDT > > > P1DIR = (0xff & ~(BIT0+BIT1)); // P1.0, P1.1 input, others output > P1OUT = 0; > P2DIR = (0xff & ~BIT5); // P2.5 must be input > P2OUT = 0; > P3DIR = (0xff & ~BIT5); // P3.5 must be high > P3OUT = (BIT1 + BIT2); // '2013 could possibly tied these high > P4DIR = 0xff; > P4OUT = 0; > P5DIR = 0xff; > P5OUT = 0; > P6DIR = 0xff; > P6OUT = 0; > P7DIR = 0xff; > P7OUT = 0; > P8DIR = 0xff; > P8OUT = 0; > P9DIR = 0xff; > P9OUT = 0; > P10DIR = 0xff; > P10OUT = 0; > > > FLL_CTL0 |= XCAP14PF; // Configure load caps > TACTL = TASSEL_1 + TACLR; // Clock = ACLK (32768), > clear > TACCTL0 = CCIE; // CCR0 interrupt enabled > TACCR0 = 32768-1; // #counts for 1s > TACTL |= MC_1; // Setting mode bits > starts timer > while(1) > {_BIS_SR(LPM3_bits + GIE);} // Enter LPM3 > } > //-------------------------------------------------------------------- > --------- > // Timer A0 interrupt service routine > #pragma vector=TIMERA0_VECTOR > __interrupt void Timer_A (void) > { > initLCD_A(); > dispChar(15,0); > > ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_7; > // Turn ADC,ref on. Ref = 2.5V, > sampling time > ADC12CTL1 = SHP; // Use sampling timer > ADC12MCTL0 = INCH_10 + SREF_1; // Select channel A10, > Vref+ > ADC12IE = 0x01; // Enable ADC12IFG.0 > for (i = 0; i < 0x3600; i++); // Delay for reference > start-up > ADC12CTL0 |= ENC; // Enable conversions > __enable_interrupt(); // Enable interrupts > > > ADC12CTL0 |= ADC12SC; // Start conversion > __bis_SR_register(LPM0_bits); // Enter LPM0 > > // DegC = (Vsensor - 986mV)/3.55mV > // Vsensor = (Vref)(ADCresult)/4095) > // DegC -> ((ADCresult - 1615)*704)/4095 > __no_operation(); // SET BREAKPOINT > > sprintf(displayBuffer,"%ld",DegF); > stringLength = strlen(displayBuffer); > ReverseArray(displayBuffer,stringLength); > for(i=0;i<stringLength;i++) > {dispChar(displayBuffer[i]-0x30, i+1);} > > > } > //-------------------------------------------------------------------- > --------- > #pragma vector=ADC12_VECTOR > __interrupt void ADC12ISR(void) > { > ADCresult = ADC12MEM0; // Move results, IFG is > cleared > DegC = ((((long)ADCresult-1615)*704)/4095); > DegF = ((DegC * 9/5)+32); // Calculate DegF > __no_operation(); // SET BREAKPOINT > > > __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 > } > //-------------------------------------------------------------------- > --------- > void ReverseArray(char*orig,unsigned short int b) > { > unsigned short int a; > int swap; > > for(a=0;a<--b;a++) //increment a and decrement b until they meet > eachother > { > swap=orig[a]; //put what's in a into swap space > orig[a]=orig[b]; //put what's in b into a > orig[b]=swap; //put what's in the swap (a) into b > } > > } > |
|
|
Re: Lowest Current Consumption with ADC RunningAlso, you are doing some monster math with all those multiplies and
divides: >> DegC = ((((long)ADCresult-1615)*704)/4095); >> DegF = ((DegC * 9/5)+32); I don't know if your selected MSP430 device has a hardware multiplier or not, but if not, that is a lot of code execution to complete those temperature conversions (more runtime = less low power mode). If you have lots of free flash space, you may want to consider using a look-up table for the most common temperature ranges and saving the hard math for temperatures outside of your expected range. Or just build everything into a table, but that would be 4K for a 12-bit ADC value range. <...short pause for some quick math...> Okay, it looks like for every incremental increase in the ADC12 reading (for example, reading 2000d versus 2001d), the temperature resolution would be 0.1719 degrees C (66.1880C vs. 66.3599C). Since the decimal values get lopped off anyway, you could easily shift your 12-bit readings down to, say, 10 bit by throwing away the lowest two bits and still maintain a Celcius resolution of 0.687 degrees C. That makes your entire Celius lookup table only 1KBytes in size. Create a Fahrenheit table of like size (1KBytes) and you have a decreased your execution time by several factors. You just need to use a spreadsheet or simple C/Basic/Perl/your-favorite-language program to pre-generate the values from your equations and load them as a header file into your source code at compile time. Just my $0.02 worth; Hope it helps. --- In msp430@..., "old_cow_yellow" <old_cow_yellow@...> wrote: > > I think your TimerA0 isr is faulty. You should have moved most of that > to the while(1) loop in main after "_BIS_SR(LPM3_bits + GIE);". > > "for (i = 0; i < 0x3600; i++);" wasts energy. > > "__bis_SR_register(LPM0_bits);" will not make your TimerA0 isr enter LPM0. > > Nesting the ADC12 interrupt inside TimerA0 interrupt is unnecessary > and incorrectly done. > > Calling library routines inside isr may cause problems too. > > --- In msp430@..., "emil.marinov" <emil.marinov@> wrote: > > > > Hi~ > > > > I am doing some testing with the MSP430FG461x processor right now > > an attempt to get the current consumption under 100 microamperes. > > The program uses the ADC to obtain temperature, then display it onto > > the LCD. Whenever I measure the current on the board, it shows up as > > lower 500 to upper 600 microamps. This is sounding an alarm in my > > head because 1) while not interrupting, the current should be MUCH > > lower than that (I measured it at 9 microamps before adding the ADC > > part) 2)I was told by someone else who's worked with this > > microprocessor before that for a program like this, the current > > consumption should stay under 100 microamps. I've pasted the code > > below. > > > > > > > > > > > > > > #include <Board.h> > > #include <LCD.h> > > #include "msp430xG46x.h" > > #include <stdlib.h> > > #include "string.h" > > #include <stdio.h> > > > > > > volatile unsigned int i,k; > > volatile unsigned int ADCresult; > > volatile unsigned long int DegC, DegF; > > int stringLength; > > char displayBuffer[10]; > > > > void ReverseArray(char*orig,unsigned short int b); > > //---------------------------------------------------------------- > > --------- > > void main(void) > > { > > WDTCTL = WDTPW + WDTHOLD; // Stop WDT > > > > > > P1DIR = (0xff & ~(BIT0+BIT1)); // P1.0, P1.1 input, others output > > P1OUT = 0; > > P2DIR = (0xff & ~BIT5); // P2.5 must be input > > P2OUT = 0; > > P3DIR = (0xff & ~BIT5); // P3.5 must be high > > P3OUT = (BIT1 + BIT2); // '2013 could possibly tied these high > > P4DIR = 0xff; > > P4OUT = 0; > > P5DIR = 0xff; > > P5OUT = 0; > > P6DIR = 0xff; > > P6OUT = 0; > > P7DIR = 0xff; > > P7OUT = 0; > > P8DIR = 0xff; > > P8OUT = 0; > > P9DIR = 0xff; > > P9OUT = 0; > > P10DIR = 0xff; > > P10OUT = 0; > > > > > > FLL_CTL0 |= XCAP14PF; // Configure load caps > > TACTL = TASSEL_1 + TACLR; // Clock = ACLK > > clear > > TACCTL0 = CCIE; // CCR0 interrupt enabled > > TACCR0 = 32768-1; // #counts for 1s > > TACTL |= MC_1; // Setting mode bits > > starts timer > > while(1) > > {_BIS_SR(LPM3_bits + GIE);} // Enter LPM3 > > } > > //---------------------------------------------------------------- ---- > > --------- > > // Timer A0 interrupt service routine > > #pragma vector=TIMERA0_VECTOR > > __interrupt void Timer_A (void) > > { > > initLCD_A(); > > dispChar(15,0); > > > > ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_7; > > // Turn ADC,ref on. Ref = 2.5V, > > sampling time > > ADC12CTL1 = SHP; // Use sampling timer > > ADC12MCTL0 = INCH_10 + SREF_1; // Select channel > > Vref+ > > ADC12IE = 0x01; // Enable ADC12IFG.0 > > for (i = 0; i < 0x3600; i++); // Delay for reference > > start-up > > ADC12CTL0 |= ENC; // Enable conversions > > __enable_interrupt(); // Enable interrupts > > > > > > ADC12CTL0 |= ADC12SC; // Start conversion > > __bis_SR_register(LPM0_bits); // Enter LPM0 > > > > // DegC = (Vsensor - 986mV)/3.55mV > > // Vsensor = (Vref)(ADCresult)/4095) > > // DegC -> ((ADCresult - 1615)*704)/4095 > > __no_operation(); // SET BREAKPOINT > > > > sprintf(displayBuffer,"%ld",DegF); > > stringLength = strlen(displayBuffer); > > ReverseArray(displayBuffer,stringLength); > > for(i=0;i<stringLength;i++) > > {dispChar(displayBuffer[i]-0x30, i+1);} > > > > > > } > > //---------------------------------------------------------------- > > --------- > > #pragma vector=ADC12_VECTOR > > __interrupt void ADC12ISR(void) > > { > > ADCresult = ADC12MEM0; // Move results, IFG is > > cleared > > DegC = ((((long)ADCresult-1615)*704)/4095); > > DegF = ((DegC * 9/5)+32); // Calculate DegF > > __no_operation(); // SET BREAKPOINT > > > > > > __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 > > } > > //---------------------------------------------------------------- ---- > > --------- > > void ReverseArray(char*orig,unsigned short int b) > > { > > unsigned short int a; > > int swap; > > > > for(a=0;a<--b;a++) //increment a and decrement b until they meet > > eachother > > { > > swap=orig[a]; //put what's in a into swap space > > orig[a]=orig[b]; //put what's in b into a > > orig[b]=swap; //put what's in the swap (a) into b > > } > > > > } > > > |
| Free Forum Powered by Nabble | Forum Help |