Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
#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 = 0b10010010; // 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;
temp = 0;
while(!done){
if(!ENTERSETTINGS_SW){
while(!ENTERSETTINGS_SW);
temp = 1;
done = 0xff;
}
if(!HOME_SW){
while(!HOME_SW);
temp = 2;
done = 0xff;
}
if(!INCREASE_SW){
while(!INCREASE_SW);
temp = 3;
done = 0xff;
}
if(!DECREASE_SW){
while(!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){
mnuPOS = 0;
input_sw = 0;
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 = 0;
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 = 0;
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.
}
}
#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 = 0b10010010; // RA7 high imp, RA3 is serial out,
ANSEL=0x02; //set RA1 as analog input for GP2 sensor
ANSELH=0x00;
CM1CON0 = 0;
CM2CON0 = 0;
lcd_init(); //call LCD initialisation
}
char WaitForInput(void){
char done;
char temp;
done = 0;
temp = 0;
while(!done){
if(!ENTERSETTINGS_SW){
while(!ENTERSETTINGS_SW);
temp = 1;
done = 0xff;
}
if(!HOME_SW){
while(!HOME_SW);
temp = 2;
done = 0xff;
}
if(!INCREASE_SW){
while(!INCREASE_SW);
temp = 3;
done = 0xff;
}
if(!DECREASE_SW){
while(!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){
mnuPOS = 0;
input_sw = 0;
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 = 0;
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 = 0;
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.
}
}
Do you think its possible to use Proteus to simulate?
Proteus VSM for PIC16 contains everything you need to develop, test and virtually prototype your embedded system designs based around the Microchip Technologies™ PIC16 series of microcontrollers. The unique nature of schematic based microcontroller simulation with Proteus facilitates rapid, flexible and parallel development of both the system hardware and the system firmware. This design synergy allows engineers to evolve their projects more quickly, empowering them with the flexibility to make hardware or firmware changes at will and reducing the time to market. Proteus VSM is discussed in more detail here.