• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

READING A PUSHBUTTON & display on LCD

Status
Not open for further replies.
I recently got a pikit 2, its the 1st time that im using push button switches.
im using 4 pushbuttons. when i power the circuit The LCD displays "infrared liquid level detector" permanently, so the lcd code and initialising is working.

All i want for now is:

when i press ENTER/Settings button....i want "enter/settings" to display on the LCD. And that is not happening when i press the button. Please help me solve this problem....i attached a picture of how i connect the switch to the pic.


Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>


char input_sw;
#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4    	//ENTERSETTINGS switch

void init(void)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
        TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

 void read_input_sw(void)
{
 char input_sw2; 
 input_sw = ((HOME_SW*8)+(INCREASE_SW*4)+(DECREASE_SW*2)+(ENTERSETTINGS_SW*1)); //create a binary combination of the input switches
 if (input_sw != 0) //check if any of the switches are pressed
	{
	 DelayMs(20); //switch debouncing
	 input_sw2 = ((HOME_SW*8)+(INCREASE_SW*4)+(DECREASE_SW*2)+(ENTERSETTINGS_SW*1));
	 while (input_sw2 != 0) //if a switch is pressed wait for release
			{
			 input_sw2 = ((HOME_SW*8)+(INCREASE_SW*4)+(DECREASE_SW*2)+(ENTERSETTINGS_SW*1));
			 DelayMs(20); //switch debouncing
  			}
	 }
}
 
   
[COLOR="Red"]void home_screen(void)[/COLOR]
{
	lcd_clear();
	lcd_goto_L1();
	[COLOR="Red"]lcd_puts("INFRARED LIQUID"); //home screen message (line 1)[/COLOR]
	lcd_goto_L2();
[COLOR="Red"]	lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)[/COLOR]

	read_input_sw();
	while(input_sw == 0)

		read_input_sw();
		switch(input_sw)
	{
		case 8: break;	
		//	ENTER/SETTINGS	button pressed	
		case 1: {	lcd_clear();
		            lcd_goto_L1();
		[COLOR="Red"]            lcd_puts(" ENTER/SETTINGS ");[/COLOR]
		            DelayS(1);
		            lcd_clear();
 					
					break;
				}
                   default : break; //should any abnormalties occur
    } 
	return;
}


void main(void)
{
	init();	// initialise I/O ports, LCD
	while (1)
	{
	home_screen();
   
	} 
	 
}
 

Attachments

Last edited:

AtomSoft

Well-Known Member
If thats how the buttons are wired then you have to check for a LOW signal.

like ..

Code:
char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(20);    //debounce
    return temp;
}
and do this for calling in your main code:

Code:
if(WaitForInput = 1){
    //This is where you put code if the user pressed ENTER
}

if(WaitForInput = 2){
    //This is where you put code if the user pressed Home
}

if(WaitForInput = 3){
    //This is where you put code if the user pressed Increase
}

if(WaitForInput = 4){
    //This is where you put code if the user pressed Decrease
}
or
Code:
switch(WaitForInput){
    case 1:
        //User Pressed ENTER do something
        break;
    case 2:
        //User Pressed HOME do something
        break;
    case 3:
        //User Pressed INCREASE do something
        break;
    case 4:
        //User Pressed DECREASE do something
        break;
}
 
Last edited:
Thanks ALOT AtomSoft...Im going to try that out now....
 

AtomSoft

Well-Known Member
heh no problem.

This would be the same but smoother:
Code:
char WaitForInput(void){
  char temp;

  while(1){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        break;
    }

    if(!HOME_SW){
        temp = 2;
        break;
    }

    if(!INCREASE_SW){
        temp = 3;
        break;
    }

    if(!DECREASE_SW){
        temp = 4;
        break;
    }
  }//end of while
    DelayMs(20);    //debounce
    return temp;
}
 
Last edited:
Uhmm its giving an error

illegal type for switch expression
illegal conversion of integer to pointer

Code:
[COLOR="Red"]switch(WaitForInput){[/COLOR]
[COLOR="DarkOrchid"]    case 1:[/COLOR]
        //User Pressed ENTER do something
        break;
[COLOR="DarkOrchid"]    case 2:[/COLOR]
        //User Pressed HOME do something
        break;
[COLOR="DarkOrchid"]    case 3:[/COLOR]
        //User Pressed INCREASE do something
        break;
[COLOR="DarkOrchid"]    case 4:[/COLOR]
        //User Pressed DECREASE do something
        break;
}
 
Last edited:

AtomSoft

Well-Known Member
oops try this:

Code:
switch(WaitForInput()){
    case 1:
        //User Pressed ENTER do something
        break;
    case 2:
        //User Pressed HOME do something
        break;
    case 3:
        //User Pressed INCREASE do something
        break;
    case 4:
        //User Pressed DECREASE do something
        break;
}
if that fails then simply:

Code:
input_sw = WaitForInput();

switch(input_sw){
    case 1:
        //User Pressed ENTER do something
        break;
    case 2:
        //User Pressed HOME do something
        break;
    case 3:
        //User Pressed INCREASE do something
        break;
    case 4:
        //User Pressed DECREASE do something
        break;
}
 
Last edited:
hehe, the 1st 1 worked, now for the lol testing it on the circuit;)
 

AtomSoft

Well-Known Member
heh good luck. I leave in about 1 hours for errands then come home then wait about 1 hours till i have to goto work. so enjoy and have fun. and if you need help ill try to post .
 
yay lol getting somewhere:). i tested it now.

when i power up without pressing switches it displays:

infrared liquid level detector
clears then
enter/settings
clears then
infrared liquid level detector
clears then
enter/settings

and keeps doing this.......


when i press the home button down continuously :
it displays
"infrared liquid level detector" continuously

thats correct because the home button takes you to the home screen

when i release the home button then:

infrared liquid level detector
clears then
enter/settings
clears then
infrared liquid level detector
clears then
enter/settings

and keeps doing this.......


uhmm im going to play around to see if i can get it to stay at enter/settings screen
 
Thanks again n again n again:). Im very happy now....that im seeing some progress.
Going to continue to make all the buttons work now. ill b back:)for sure
 
Last edited:

AtomSoft

Well-Known Member
heh was bored and about to leave but i have a gift

Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>

char input_sw;
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;

#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4    	//ENTERSETTINGS switch

void init(void);
char WaitForInput(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);

void init(void)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
        TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
  char temp;

  while(1){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        break;
    }

    if(!HOME_SW){
        temp = 2;
        break;
    }

    if(!INCREASE_SW){
        temp = 3;
        break;
    }

    if(!DECREASE_SW){
        temp = 4;
        break;
    }
  }//end of while
    DelayMs(20);    //debounce
    return temp;
}
   
void home_screen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
	lcd_goto_L2();
	lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	DelayS(1);
	lcd_clear();
}

void ShowDigits(unsigned char val){

    MyValLCD[0] = val /10;    //returns the quotient (if temp = 35 the result is 3)
    MyValLCD[1] = val % 10; 	//Returns remainder   (if temp = 35 the result is 5)

	MyValLCD[0] += 0x30;	//to ASCII
	MyValLCD[1] += 0x30;	//to ASCII

	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	lcd_goto_L2();
	lcd_data(MyValLCD[0]);	//to LCD
	lcd_data(MyValLCD[1]);  //to LCD
}

void main(void)
{
	init();	// initialise I/O ports, LCD
	home_screen();

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

while(1){
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
   		input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}

	 
}
 
Hehe, that was a nice surprise:) when i logged in again. Thanks lol i hope you not counting how many times i said that :rolleyes: I tried the code. i commented home screen() in the main code otherwise it only displays infra red liquid level detector and ignores the button presses.

Code:
void main(void)
{
	init();	// initialise I/O ports, LCD
	//home_screen();

ALSO
it works when i replace:


Code:
char WaitForInput(void){
  char temp;

  while(1){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        break;
    }

    if(!HOME_SW){
        temp = 2;
        break;
    }

    if(!INCREASE_SW){
        temp = 3;
        break;
    }

    if(!DECREASE_SW){
        temp = 4;
        break;
    }
  }//end of while
    DelayMs(20);    //debounce
    return temp;
}

with:

Code:
char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(20);    //debounce
    return temp;
}
if i dont replace it then pressing the buttons has no affect...it keeps displaying "enter/settings"



when i replace it and power on:


"enter/settings" is displayed continuously

when i press home button: infra red liquid level detect is displayed.
it does not display the full word "detector"

when i release home button: "enter/settings" is displayed continuously


when i press increase button: the screen remains blank
when i release increase button:"enter/settings" is displayed continuously
uhmmm it does not show the number of times the button is pressed on the LCD

when i press decrease button: the screen remains blank
when i release decrease button:"enter/settings" is displayed continuously
it does not show the number of times the button is pressed on the LCD

when i press home/settings button:"enter/settings" is displayed continuously
when i release home/settings button:"enter/settings" is displayed continuously
 
Last edited:
im thinking maybe this:

Code:
lcd_data(MyValLCD[0]);	//to LCD
lcd_data(MyValLCD[1]);  //to LCD
is affecting the "detect" word from being "detector".

i was bread boarding a switch mode power supply-boost regulator
3.2V to 5V, im waiting for the batteries to charge so i can test it...hehe.
 

AtomSoft

Well-Known Member
that should not affect the other text.
Can you post full code?
Try this:
Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>

char input_sw;
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;

#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4    	//ENTERSETTINGS switch

void init(void);
char WaitForInput(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);

void init(void)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
        TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(150);    //debounce
    return temp;
}

   
void home_screen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts("INFRARED LIQUID "); //home screen message (line 1)
	lcd_goto_L2();
	lcd_puts("LEVEL DETECTOR  "); //home screen message (line 2)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	DelayS(1);
	lcd_clear();
}

void ShowDigits(unsigned char val){

    MyValLCD[0] = val /10;    //returns the quotient (if temp = 35 the result is 3)
    MyValLCD[1] = val % 10; 	//Returns remainder   (if temp = 35 the result is 5)

	MyValLCD[0] += 0x30;	//to ASCII
	MyValLCD[1] += 0x30;	//to ASCII

	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	lcd_goto_L2();
	lcd_data(MyValLCD[0]);	//to LCD
	lcd_data(MyValLCD[1]);  //to LCD
}

void main(void)
{
	init();			// initialise I/O ports, LCD
    DelayMs(20);    // init delay
	home_screen();	//display home screen

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

	mnuPOS = 2;
while(1){
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
   		input_sw = WaitForInput();
    	DelayMs(50);    //debounce #2 for a total of 200ms (user can press button 5 times in 1 second)
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}

	 
}
 
Heres the code i used and remarked on

Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>
  
void FloatToStr(float , char[]); 
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char); 
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);

void init(void);
char WaitForInput(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);



void calc_distance(void);

      

#define LCD_RS RC0		//LCD RS pin
#define LCD_EN RC1		//LCD EN pin
#define LCD_STROBE()	LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0

unsigned char cm10;		//
unsigned char cm;		//
unsigned int math;		// used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
   
unsigned char i,j,k;
char temp[8];
int height=50, SensorPos=10;
char input_sw;

 
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;



#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4	//ENTERSETTINGS switch








[COLOR="Purple"]///////////////////////CONVERT FLOAT TO STRING///////////////////[/COLOR]
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
	  {
      scale=floor(0.5+scale/10.0);
      d=(unsigned char) (n/scale);
      str[f]=d+'0';
      n=n-scale*d;
	  f++;
      };

str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
      {
      n=n*10.0;
      d=(unsigned char) n;
      str[f]=d+'0';
      n=n-d;
	  f++;
	  };
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////

/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if	XTAL_FREQ <= 2MHZ
	do {
		DelayUs(996);
	} while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ	
	unsigned char	p;
	do {
		p = 4;
		do { 
			DelayUs(250);
		} while(--p);
	} while(--cnt);
#endif
}

void DelayS(unsigned char cnt)
{
	for (j=0; j<(cnt*10); j++)
		DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////

//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
	DelayMs(20); //wait for LCD to be ready
	LCD_RS = 0;	 //write instruction
	PORTB = (c & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD
	PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD   	
}

/* send data to the LCD */
void lcd_data(unsigned char c)
{
	DelayMs(20); //wait for LCD to be ready
	PORTB = 0x00;
	LCD_RS = 1; //write data
    PORTB |= (c & 0xF0); //load upper nibble on LCD data lines     
	LCD_STROBE(); //send instruction to LCD
	PORTB &= 0x00; //load upper nibble on LCD data lines
	PORTB |= ( (c << 4) & 0xF0); 
	LCD_STROBE(); //send instruction to LCD
}

/*Clear the LCD*/
void lcd_clear(void)
{
	lcd_cmd(0x01); //command to clear LCD
}

/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
	j = -1;
	while(s[++j]!=('\0')) // send characters until null character reached
		lcd_data(s[j]);
}

/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
	lcd_cmd(0b10000000); // command to go to line 1
}

/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
	lcd_cmd(0b11000000); // command to go to line 2
}

/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
	lcd_cmd(((x)&0x7F)|0x80); 
}

/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
	LCD_RS = 0;	
	LCD_EN = 0;
	DelayMs(20); //wait for LCD startup
	lcd_cmd(0x28);	// 4-bit mode
	lcd_cmd(0x08);	// display off
	lcd_cmd(0x01);	// clear display
	lcd_cmd(0x0C);	// disp. on, cursor off, cursor blink off
	lcd_cmd(0x06);	// entry mode
	lcd_cmd(0x80);  // initialise DDRAM address to zero
}
[COLOR="Purple"]//////////////////////////LCD SETUP END//////////////////////////[/COLOR]


 
  

void init(void)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
    TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(20);    //debounce
    return temp;
}

void home_screen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
	lcd_goto_L2();
	lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	DelayS(1);
	lcd_clear();
}

void ShowDigits(unsigned char val){

    MyValLCD[0] = val /10;    //returns the quotient (if temp = 35 the result is 3)
    MyValLCD[1] = val % 10; 	//Returns remainder   (if temp = 35 the result is 5)

	MyValLCD[0] += 0x30;	//to ASCII
	MyValLCD[1] += 0x30;	//to ASCII

	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
	lcd_goto_L2();
	lcd_data(MyValLCD[0]);	//to LCD
	lcd_data(MyValLCD[1]);  //to LCD
}

  
void calc_distance(void)
{
	// from the transeiver datasheet the analog voltage is
	// the inverse of distance, so distance can be calculated
	// d = (1 / volts) then just scaled to suit the transeiver

	// load ADC value in 16bit math var
	math = ADRESH;
	math = (math * 256);
	math += ADRESL;

	// now invert it; (1 / volts) use (6050 / volts) for scaling
	math = (6050 / math);
	if(math >= 2) math -=2;		// fix linear error (-2)
	if(math > 99) math = 99;	// max limit at 99cm

	// convert from 0-99 to 2 decimal digits, 0-99cm
	cm10=0;
	while(math >= 10)
	{
		cm10++;
		math -= 10;
	}
	cm = math;
}
 
void main(void)
{
	init();	// initialise I/O ports, LCD
  [COLOR="Red"]  //home_screen();[/COLOR]

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

while(1){
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
   		input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}
 
	 
}
 

AtomSoft

Well-Known Member
try this and tell me what happens:
Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>
  
void FloatToStr(float , char[]); 
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char); 
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);

void init(void);
char WaitForInput(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);



void calc_distance(void);

      

#define LCD_RS RC0		//LCD RS pin
#define LCD_EN RC1		//LCD EN pin
#define LCD_STROBE()	LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0

unsigned char cm10;		//
unsigned char cm;		//
unsigned int math;		// used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
   
unsigned char i,j,k;
char temp[8];
int height=50, SensorPos=10;
char input_sw;

 
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;



#define HOME_SW RC2				//HOME switch	
#define INCREASE_SW RC3			//INCREASE switch
#define DECREASE_SW RC4			//DECREASE switch
#define ENTERSETTINGS_SW RA4	//ENTERSETTINGS switch



///////////////////////CONVERT FLOAT TO STRING///////////////////
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
	  {
      scale=floor(0.5+scale/10.0);
      d=(unsigned char) (n/scale);
      str[f]=d+'0';
      n=n-scale*d;
	  f++;
      };

str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
      {
      n=n*10.0;
      d=(unsigned char) n;
      str[f]=d+'0';
      n=n-d;
	  f++;
	  };
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////

/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if	XTAL_FREQ <= 2MHZ
	do {
		DelayUs(996);
	} while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ	
	unsigned char	p;
	do {
		p = 4;
		do { 
			DelayUs(250);
		} while(--p);
	} while(--cnt);
#endif
}

void DelayS(unsigned char cnt)
{
	for (j=0; j<(cnt*10); j++)
		DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////

//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
	DelayMs(20); //wait for LCD to be ready
	LCD_RS = 0;	 //write instruction
	PORTB = (c & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD
	PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
	LCD_STROBE(); //send instruction to LCD   	
}

/* send data to the LCD */
void lcd_data(unsigned char c)
{
	DelayMs(20); //wait for LCD to be ready
	PORTB = 0x00;
	LCD_RS = 1; //write data
    PORTB |= (c & 0xF0); //load upper nibble on LCD data lines     
	LCD_STROBE(); //send instruction to LCD
	PORTB &= 0x00; //load upper nibble on LCD data lines
	PORTB |= ( (c << 4) & 0xF0); 
	LCD_STROBE(); //send instruction to LCD
}

/*Clear the LCD*/
void lcd_clear(void)
{
	lcd_cmd(0x01); //command to clear LCD
}

/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
	j = -1;
	while(s[++j]!=('\0')) // send characters until null character reached
		lcd_data(s[j]);
}

/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
	lcd_cmd(0b10000000); // command to go to line 1
}

/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
	lcd_cmd(0b11000000); // command to go to line 2
}

/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
	lcd_cmd(((x)&0x7F)|0x80); 
}

/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
	LCD_RS = 0;	
	LCD_EN = 0;
	DelayMs(20); //wait for LCD startup
	lcd_cmd(0x28);	// 4-bit mode
	lcd_cmd(0x08);	// display off
	lcd_cmd(0x01);	// clear display
	lcd_cmd(0x0C);	// disp. on, cursor off, cursor blink off
	lcd_cmd(0x06);	// entry mode
	lcd_cmd(0x80);  // initialise DDRAM address to zero
}
//////////////////////////LCD SETUP END//////////////////////////


 
  

void init(void)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
    TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(150);    //debounce
    return temp;
}

void home_screen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
	lcd_goto_L2();
	lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
}

void ShowDigits(unsigned char val){

    MyValLCD[0] = val /10;    //returns the quotient (if temp = 35 the result is 3)
    MyValLCD[1] = val % 10; 	//Returns remainder   (if temp = 35 the result is 5)

	MyValLCD[0] += 0x30;	//to ASCII
	MyValLCD[1] += 0x30;	//to ASCII

	EnterScreen();
	lcd_goto_L2();
	lcd_data(MyValLCD[0]);	//to LCD
	lcd_data(MyValLCD[1]);  //to LCD
}

  
void calc_distance(void)
{
	// from the transeiver datasheet the analog voltage is
	// the inverse of distance, so distance can be calculated
	// d = (1 / volts) then just scaled to suit the transeiver

	// load ADC value in 16bit math var
	math = ADRESH;
	math = (math * 256);
	math += ADRESL;

	// now invert it; (1 / volts) use (6050 / volts) for scaling
	math = (6050 / math);
	if(math >= 2) math -=2;		// fix linear error (-2)
	if(math > 99) math = 99;	// max limit at 99cm

	// convert from 0-99 to 2 decimal digits, 0-99cm
	cm10=0;
	while(math >= 10)
	{
		cm10++;
		math -= 10;
	}
	cm = math;
}
 
void main(void)
{
	init();	// initialise I/O ports, LCD
    //home_screen();

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

while(1){
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
		DelayMS(50);
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
   		input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}
 
	 
}
 
Im using the new code you suggested and now

when i power on:


"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.


when i press home button: infra red liquid level detector is displayed continuously

when i release home button:

"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.
Code:
when i [B]press increase button[/B]: it displays enter/settings on 1st line
                                         then 01                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 02                        on 2nd line
and continues increasing...
but i need the 1st digit to increase fro 0 to 9 and rollover to 0.

when i release increase button:"enter/settings" is displayed continuously

Code:
when i [B]press decrease button[/B]: it displays enter/settings on 1st line
                                         then 02                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 01                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 00                       on 2nd line

                                         it displays enter/settings on 1st line
                                         then 00                        on 2nd line
and 00 is the lowest it decreases to
But i need the 2nd digit to decrease from 9 to 0 and rollover to 9.

when i release decrease button:"enter/settings" is displayed continuously


when i press home/settings button:
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.

when i release home/settings button:
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.
 
Last edited:

AtomSoft

Well-Known Member
i think you might have a hardware issue. Are all the buttons pulled high?

As soon as it goes on it should not say anything. It should be blank and you have to press the home button for it to show that "infrared liquid level detector"

Hence why i suggest you uncomment the :

Code:
void main(void)
{
	init();	// initialise I/O ports, LCD
        [b]home_screen();[/b]
 
Last edited:
Maybe the configuration bits in MPLAB are not set corrrectly???that would affect the micro right. im using momentary push button switches....
 
im going to uncomment home and c what happens. When i tried your new code....home is uncommented and the same remarks apply.
 
Last edited:
Status
Not open for further replies.

EE World Online Articles

Loading
Top