This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LCD display : NaN

Hi,



I have a problem of displaying the output data on LCD. it will display "NaN", which i have read that this is not a data. This problem arises when i start to acquire data from the sensors (meaning when there is reading). But if the sensors circuit are off and the reading is zero, there is output data. i think it could be due to integer to floating point conversion of the aquired data. i have tried several times by changing the data types but the output is still display :NaN. But if i do normalize the data in (1 to -1)there will be an output reading. If i dont normalize the data, the output reading will be in around 1000 to 8000 . The problem arises when i am not normalizing the data.



Here is the code.



 #include <stdio.h>
#include <math.h>
#include <reg51.h>
//#include <AT89X52.h>
#include <stdlib.h>
//#include <intrins.h>

.......
/*Main Program*/
main()
{
	int pmax=10,i,n=8,j;
	int data_LSB,data_MSB,CH[10];
    int CHn[10],min=2,max=1;
    ppi_set();
    serial_init();


 for (i=0;i<=pmax;i++)						//for number of pulse <=10
    {
	 if (PULSE==1)							//Check whether PULSE =1
	 {
	    for (j=0;j<8;j++)					//If yes do DAQ of 8 Ch (0-7)
		   {
			 P1=j;							//Write Add to Port 1 (0-7)
			 data_LSB=PA;					//Read LSB data from Port A
			 data_MSB=PB;					//Read MSB data from Port B
			 CH[j]=(data_MSB<<8)|data_LSB;  //Shift Left MSB data 8 times ("|"is bitwise 'or' to sum both bit)
			 printf("%d\t",CH[j]);
            // min=(min<CH[j])? min:CH[j];	//Scan for Min data
			// max=(max>CH[j])? max:CH[j];	//Scan for Max data
			 }
	    printf("\n");
        for (j=0;j<n;j++)
		   {
		//	CHn[j]=2*((CH[j]-min)/(max-min))-1; //Data Normalization formula make data in range (-1,1)
		    CHn[j]=(float) CH[j];    //Raw data (in range 1000-8000)

           }

		ANN(n,CHn);		//Call ANN process function

		 }
        wait(1);
       }


}

/*ANN PROCESS*/

#include <stdio.h>
#include <math.h>
#include <intrins.h>
/* External LCD output function*/
extern void LCD(float O[]);

/*ANN Function Definitioan*/
void ANN(int n,float CHn[])

{	int j,h,hmax=6,o,omax=4;  //Hidden Neuron (hmax)=6, Output Neuron(omax)=4
    float xdata O[5],H[8];
	float xdata WHI[6][8]= {//WHI=Weight value of connection between Input=8 and Hidden=6

		/*Weight with logsig and logsig transfunction*/
		{2.7294,4.5239,-0.0103,-0.6089,4.8868,-5.7313,-2.6335,0.4967},
		{-4.7325,-3.8315,-0.1689,-1.6844,8.3110,4.7062,0.1422,-1.3525},
		{3.1464,2.3160,0.6550,0.6286,3.3174,0.9235,8.5057,0.6745},
		{2.6970,-3.2395,-0.7225,-4.6076,5.4900,-7.1220,0.5794,2.2767},
		{4.4916,1.7946,0.4944,0.5825,0.7911,-9.6612,-4.7229,-0.1789},
		{1.6326,-4.5621,-4.2867,-0.9461,-2.9762,-3.0127,-0.6397,-1.7811}

	};

	float xdata WOH[4][6]= {//WOH=Weight value of connection between Hidden=6 and Output=4

		/*Weight with logsig and logsig transfunction*/
		{10.2251,3.9513,2.6186,8.5117,3.7212,-7.4772},
		{-5.0325,-9.1396,-1.4935,13.1217,-0.5011,5.5292},
		{4.3388,-13.4855,3.0468,-10.0947,6.0913,-8.8211},
		{-9.7137,9.8602,-1.9421,-2.2828,-8.7116,1.1900}

	};

	float xdata BH[6]={//BH=Bias of Hidden Neuron=6

		/* Bias with logsig and logsig transfunction*/
		{-6.4229},{10.9651},{-3.3755},{-2.2552},{-6.6035},{-2.6723}};

	float xdata BO[4]={//BO=Bias of Output Neuron=4

		/* Bias with logsig and logsig transfunction*/
    	{-15.1368},{-8.9549},{3.7160},{-0.3211}};

	for (h=0;h<hmax;h++)//Multiply and Accumulate Input*Weight(WHI)
	{
	  H[h]=0;
		for(j=0;j<n;j++)
		{
			H[h]=H[h]+(CHn[j]*WHI[h][j]);  // do the Multiply for hidden first

		}

			H[h]=H[h]+BH[h];	    		//Accumulate with Bias of each Hidden
			H[h]=1.0/(1.0+exp(-1.0*(H[h])));//Logsig Transfer Function
	}


	for (o=0;o<omax;o++)//Multiply and Accumulate Hidden Output*Weight(WOH)
	{
		O[o]=0;
		for(h=0;h<hmax;h++)
		{
			O[o]=O[o]+(H[h]*WOH[o][h]);	//Multiply for output neuron

		}
            O[o]=O[o]+BO[o];		   // Accumulate with Bias of each Output neuron
		    O[o]=1.0/(1.0+exp(-1.0*(O[o])));//Transfer function logsig

	  }

	LCD(O); // Call LCD Gas output display function


}
/* LCD output display of detected gas*/
/* Display Result of Neuron Output using sprintf()*/
/**************************************************************************************/
....
/* Main Program Function : LCD DISPLAY*/

void LCD(float O[])
{  //data int i;
   char buf[40];
   ppi_set();//Configures the PPI :PA & PB as input, PC as Output
   LCD_init ();



  /* Check on each neuron Output value, if>0.9 display the detected GAS*/

          sprintf(buf,"O[0]:%f",O[0]);
          LCD_StringCentered (1,buf);
	     // sprintf(buf,"O[1]:%f",O[1]);
         // LCD_StringCentered (2,buf1);
          wait(30000);





}

Please help to find out why it keep displaying NaN. Your help is much appreciated.

Thanks

  • NaN (Not A Number) means you you preformed a math operation that produce an overflow or a divide by Zero.
    Test for bad data before doing calculations

  • "NaN (Not A Number) means you you preformed a math operation that produce an overflow or a divide by Zero."

    Or you're simply trying to perform some floating point operation on an invalid float. There are lots of ways of obtaining an invalid float - reading past the end of an array is one of my old favourites.

    I'm afraid you're going to have to methodically step through all those loops until you find out where it's going wrong.

    Incidentally, your variable naming convention is quite horrible:

    O[o]=0;

    just isn't good for my mental health.

  • Hi all,

    Thank-you for the response. I have found the solution. I need to modify the input of exponent formula so that there wont be any infinity answer which leads to NaN display.

    p/s- sorry if my variable naming makes u headache.hehe.

    bye.

  • sorry if my variable naming makes u headache
    so does your inability to spell you

    Erik

  • Nore,

    Here is a suggestion for your line:

    	    O[o]=1.0/(1.0+exp(-1.0*(O[o])));//Transfer function logsig
    

    Use an inline macro instead:

    #define LOGSIG(x) (1.0/(1.0+exp(-1.0*(x[0]))))
    :
    :
    :
    LOGSIG(O);
    

    You really should take some time and define a coding standard for yourself. It is amazing how much easier it is to debug code that is easier to read. Use spaces for white space instead of tabs. I myself like to attach the units at the end of a variable name and the type at the beginning:

    void CC9_viIsrTmr1(void) interrupt T1INT using T1_REG_BANK
    /*******************************************************************************
    Description:  This interrupt routine services the T1 counter roll over.  The
                  timer counts from the reload value (RELOAD_TICS) up to the
                  rollover value (0xFFFF) and then fires an interrupt.  A tic occurs
                  every 400 nS (assuming a prescaler of 8).  Given the above reload
                  value and prescaler, this interrupt fires every 26 mS. (See page
                  14-6 of the C167 Derivatives Users Manual).
    
                  This interrupt is used to generate the globally accessible speed
                  readings for CAPCOM input 8 (transmission input) and
                  CAPCOM input 9 (transmission output).
    Inputs:  NONE
    Outputs: NONE
    Globals: m_ulCC08Ave400nsTics - 0x00-0xFFFFFFF 400 nS tics
             m_ulCC09Ave400nsTics - 0x00-0xFFFFFFF 400 nS tics
             m_uTranInRpm - 0-65,535 RPM  (tied to CC08)
             m_uTranOutRpm - 0-65,535 RPM (tied to CC09)
    *******************************************************************************/
    {
       BYTE bCaptures;
       static ULONG sdata ulCC08SinceLastCapture400nsTics;
       static ULONG sdata ulCC09SinceLastCapture400nsTics;
    
       /* Mask interrupts.  The IRET at the end of the routine will pop the PSW
          and reenable the interrupts.*/
       IEN = 0;
    
       /* See if at least two captures were made for CC08.  PECC2 holds the count
          which is decremented each time a PEC transfer is made.*/
       bCaptures = PEC_ARRAY_SIZE - (PECC2 & PEC_COUNT_MASK);
       if (bCaptures >= 2)
       {
          /* Two or more captures occurred, compute average number of 400 nS tics
             between each capture.  Update the number of 400 nS tics since last
             capture. */
          m_ulCC08Ave400nsTics =
                      (m_auCC08Pec400nsTics[bCaptures-1] - m_auCC08Pec400nsTics[0])
                      /
                      (bCaptures-1);
          ulCC08SinceLastCapture400nsTics =
                              (ULONG)(MAX_TICS - m_auCC08Pec400nsTics[bCaptures-1]);
       }
       else if (bCaptures == 1)
       {
          /* One capture occured, compute 400 nS tics factoring in rollovers. Update
             the number of 400 nS tics since last capture. */
          m_ulCC08Ave400nsTics = ulCC08SinceLastCapture400nsTics +
                                 m_auCC08Pec400nsTics[0];
          ulCC08SinceLastCapture400nsTics =
                                        (ULONG)(MAX_TICS - m_auCC08Pec400nsTics[0]);
       }
       else
       {
          /* No capture occured, add rollover to number of 400 nS tics since last
             capture. */
          ulCC08SinceLastCapture400nsTics += ROLLOVER_TICS;
    
          /* Zero out global reading if no signal */
          if (m_ulCC08Ave400nsTics > ZERO_SPEED_400_NS_TICS)
          {
             m_ulCC08Ave400nsTics = ZERO_SPEED_400_NS_TICS;
          }
       }
       /* Update transmission input RPM reading */
       m_uTranInRpm = TICS_TO_RPM(m_ulCC08Ave400nsTics, m_uTranInPpr);