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.

MSP430G2231 code exceeding available memory

Other Parts Discussed in Thread: MSP430G2231

Hi,

i am using MSP430G2231 and i am making an ohm meter and hence want to display resistance values on LCD(4-bit mode). I want to check its value and then display it on LCD but using numerous comparisons and float variables has made my program to exceed the 2KB flash of the MCU.

The Error while compiling is:

the part of the code which i am using to check the range of Resistance and displaying on LCD is:

void string(char *p)                     // to display the string
{
while(*p) data(*p++); // send data Alphabet by Alphabet
}

void switch_case(int x)                // to display numerical values
{
switch(x)
{
case 0: string("0");
break;
case 1: string("1");
break;
case 2: string("2");
break;
case 3: string("3");
break;
case 4: string("4");
break;
case 5: string("5");
break;
case 6: string("6");
break;
case 7: string("7");
break;
case 8: string("8");
break;
case 9: string("9");
break;
}
}

void res(float ad, int p)            // to break the number for displaying on LCD
{
unsigned int a[10]={0},m,y;
for(m=9;m<=0;m++)
{
a[m]=(int)ad % 10;
ad=ad/10;
}
for(m=p-3;m>=p;m--)
{
if(m==p-2)
string(".");
y=a[m];
switch_case(y);
}
}

void range(float x)          // to find range of Resistance
{
if(x>=1 && x <=9.999)
{
x=x*1000;
res(x,1);
string(" Ohm");
}
else if (x>=10 && x <=99.999)
{
x=x*100;
res(x,2);
string(" x10 Ohm");
}
else if (x>=100 && x<=999.999)
{
x=x*10;
res(x,3);
string(" x100 Ohm");
}
else if (x>=1000 && x<=9999.999)
{
res(x,4);
string(" kOhm");
}
else if (x>=10000 && x<=99999.999)
{
res(x,5);
string(" x10 kOhm");
}
else if (x>=100000 && x<=999999.999)
{
res(x,6);
string(" x100 kOhm");
}
else if (x>=1000000 && x<=9999999.999)
{
res(x,7);
string(" MOhm");
}
else
{
res(x,0);
string(" Ohm");
}
}

please help me optimize the code.

  • Udit,

    Why not do things in terms of integer math? Scale the value up by 1000, and then all of your compares will become whole numbers.

    Example:

    If the value is 100.123, the compare value becomes 100123.

    As a quick test, I did this:

    /*
    	float test;
    
    	for(;;) {
    		test = WDTCTL;
    
    		test *= 0.01;
    		test += test;
    
    		if (test < 0.123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 1.123)
    		{
    			P1OUT = 0;
    		}else if(test < 10.123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 100.123)
    		{
    			P1OUT =0;
    		}
    	}
    	*/
    	//return 0;
    //      name            origin    length      used     unused   attr    fill
    //----------------------  --------  ---------  --------  --------  ----  --------
    	//  FLASH                 00004400   0000bb80  00000b2c  0000b054  RWIX //this used 2860 bytes
     
    
    	long test;
    
    	for(;;) {
    		test = WDTCTL;
    
    		test *= 1000;
    
    		if (test < 123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 1123)
    		{
    			P1OUT = 0;
    		}else if(test < 10123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 100123)
    		{
    			P1OUT =0;
    		}
    	}
    	//      name            origin    length      used     unused   attr    fill
    	//----------------------  --------  ---------  --------  --------  ----  --------
    
        //  FLASH                 00004400   0000bb80  0000011e  0000ba62  RWIX  //using long for compares instead of
    // uses only 286 bytes.

    This is just a suggestion, if you google doing floating point math with integers, you will probably find some routines to use.

    -Jason

  • void switch_case(int x)                // to display numerical values
    {
      if ((x >= 0) && (x<= 9))
        data('0'+x);
    }

    And yes, don't use float but 16-bit integers.

    Before we even consider to optimize very ineffective coding of range() - please tell how do you measure Ohms and MegaOhms using 10-bit ADC?

  • Ilmars said:

    void switch_case(int x)                // to display numerical values
    {
      if ((x >= 0) && (x<= 9))
        data('0'+x);
    }

    And yes, don't use float but 16-bit integers.

    Before we even consider to optimize very ineffective coding of range() - please tell how do you measure Ohms and MegaOhms using 10-bit ADC?

    Thank you for your reply, it is working well.

    and about measuring resistance then i am measuring voltage across the resistance using 10-bit ADC and the using voltage divider i am calculating the resistance

    the circuit diagram is:

    then i have to display the resistance calculated[depending upon the range(from Ohms to MOhms) of it]

  • Jason Kriek said:

    Udit,

    Why not do things in terms of integer math? Scale the value up by 1000, and then all of your compares will become whole numbers.

    Example:

    If the value is 100.123, the compare value becomes 100123.

    As a quick test, I did this:

    /*
    	float test;
    
    	for(;;) {
    		test = WDTCTL;
    
    		test *= 0.01;
    		test += test;
    
    		if (test < 0.123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 1.123)
    		{
    			P1OUT = 0;
    		}else if(test < 10.123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 100.123)
    		{
    			P1OUT =0;
    		}
    	}
    	*/
    	//return 0;
    //      name            origin    length      used     unused   attr    fill
    //----------------------  --------  ---------  --------  --------  ----  --------
    	//  FLASH                 00004400   0000bb80  00000b2c  0000b054  RWIX //this used 2860 bytes
     
    
    	long test;
    
    	for(;;) {
    		test = WDTCTL;
    
    		test *= 1000;
    
    		if (test < 123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 1123)
    		{
    			P1OUT = 0;
    		}else if(test < 10123)
    		{
    			P1OUT =1;
    		}
    		else if(test < 100123)
    		{
    			P1OUT =0;
    		}
    	}
    	//      name            origin    length      used     unused   attr    fill
    	//----------------------  --------  ---------  --------  --------  ----  --------
    
        //  FLASH                 00004400   0000bb80  0000011e  0000ba62  RWIX  //using long for compares instead of
    // uses only 286 bytes.

    This is just a suggestion, if you google doing floating point math with integers, you will probably find some routines to use.

    -Jason

    Jason,

    thanks for your reply.

    but if i make the resistance to int datatype then for displaying MOhm(7 + 3(after multiplying by 1000)) range the value will exceed the digit range of int.

    and if i do not multiply high range Resistance by 1000 then how can i distinguish between small values after multiplying them by 1000 and values in range kOhms

    eg:- 1.234ohm *1000 = 1234

             & 1234 ohms

    Please suggest if there is another datatype or method other than int which can be used for this or method by which i can reduce the digits when considering high Ohm values.

  • Udit Khanna said:
    and about measuring resistance then i am measuring voltage across the resistance using 10-bit ADC

    This is it? 10-bit ADC can give measurements in 0...1023 range. If you measure resistance up-to 10 MOhm then single count of ADC, meaning accuracy of measurement in this case is +/- 10000000/1023 = 9775.2 Ohms. How do you plan to measure Ohms with planned display range 0...9.999 meaning +/- 0.01 Ohm accuracy in case of 10-bit ADC?

  • Ilmars said:

    This is it? 10-bit ADC can give measurements in 0...1023 range. If you measure resistance up-to 10 MOhm then single count of ADC, meaning accuracy of measurement in this case is +/- 10000000/1023 = 9775.2 Ohms. How do you plan to measure Ohms with planned display range 0...9.999 meaning +/- 0.01 Ohm accuracy in case of 10-bit ADC?

    llmars,

    i am using internal reference of MSP430 of 2.5V to measure the voltage across the resistance.

    Eg; voltage applied = 5.03V

    standard R = 100k

    Variable R=47k(46480 ohms)

    then using ADC i am measuring voltage across 47k(variable)

    V=1.572581 V (should be 1.582V according to multimeter reading) error = +/- 0.59%

    then using this voltage i measure the corresponding R value using voltage divider

    R(variable)=(V / applied voltage-V) * 100k(standard R) = 45484.2471 ohms

    this is giving accuracy of +/- 2%(approx)

    and i have to display this value on LCD like 4.548 (x10k) Ohms

    please suggest if there is a better way to display the Resistance readings

    Thanks,

    Udit

  • Udit Khanna said:
    standard R = 100k

    What standard R will be used for other measurement ranges? For 10Ohms and for 10MOhms?

  • Ilmars said:

    standard R = 100k

    What standard R will be used for other measurement ranges? For 10Ohms and for 10MOhms?

    [/quote]

    Standard range of R
    100 0 to 100
    1000 100 to 1k
    10000 1k to 10k
    100000 10 k to 100k
    1000000 100k to 1 M

             

  • Good. Then CPU anyway shall know which exactly of "standard" resistors are connected, so you can use this information in your code, in result display function knowing R_standard identifier (0...4) and ADC measurement (integer in range 0...1023) can display result. No floating point variables or math needed, only your brain - to think how to do it using integer variables and fixed point math :)

  • Ilmars said:

    Good. Then CPU anyway shall know which exactly of "standard" resistors are connected, so you can use this information in your code, in result display function knowing R_standard identifier (0...4) and ADC measurement (integer in range 0...1023) can display result. No floating point variables or math needed, only your brain - to think how to do it using integer variables and fixed point math :)

    Thank you llmars for your help.

    now i am able to reduce my code size and i'll try to execute it within memory constraints using your suggestions.

    regards,

    udit

  • Udit,

    Use a long variable type, and not an int. This will give you the range that you need.

    In an signed long you can do 2,147,483,647.

    -Jason

     

  • Jason Kriek said:
    Use a long variable type, and not an int.

    Long is type specifier - you can't use long w/o using int :D Well.. you can - using long double which is what we are trying to avoid, right? Better say: don't use 16-bit short int but use 32-bit long int instead.

    And yes, sure - 16-bit integers could be not enough for fixed point math of particular application. 

  • Jason Kriek said:
    In an signed long you can do 2,147,483,647.

    With an unsigned long int, you can do even twice as much. It is rather unlikely that you will have to show negative resistances (unless you have a voltage-dependent current amplifier and not a resistor)

    However..

    for(m=9;m<=0;m++)

    The end condition in this loop is nonsense, since m is an unsigned int and therefore cannot be <0. Also, m starts with 9, which is >0 and therefore the loop immediately ends, as if it were "i=9;while(0){...}".
    The compiler gives a warning here.

**Attention** This is a public forum