1. 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.
    Dismiss Notice

READING A PUSHBUTTON & display on LCD

Discussion in 'Microcontrollers' started by fantabulous68, Sep 9, 2009.

  1. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Try this as your usermenu stuff. The slow speed might be because of that 2 second delay you have in the menu using timer1:
    Code (text):

    void userMenu(char pos){
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= 2000000)     // if reached 2 seconds!
                    {
                        bres -= 2000000;    // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(cm10 + '0');
                        lcd_data(cm + '0');
                        lcd_puts(" [cm] ");         //comment this out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts("      OK      ");
            lcd_goto_L2();
            lcd_puts("              ");
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }
     
    Holding Home down will take you home.

    EDIT: If you can read this try the code again. I edited it/
     
    Last edited: Sep 18, 2009
  2. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Ok ok i forgot a few things. try this full code:
    Code (text):

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

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char cmHigh, cmLow;

         

    #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 int LiquidLevel;
    unsigned char NumDec;
    unsigned char NumSep[2];
       
    unsigned char i,j,k;
    //char temp[8];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= 2000000)     // if reached 2 seconds!
                    {
                        bres -= 2000000;    // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(cm10 + '0');
                        lcd_data(cm + '0');
                        lcd_puts(" [cm] ");         //comment this out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts("      OK      ");
            lcd_goto_L2();
            lcd_puts("              ");
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }
    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // [b]used for voltage calculations backup[/b]
        // 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

        //[b]Create a copy of math for more use[/b]
        mathKeep = math;
        //LiquidLevel=height-; 

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //[b]Now our original data is back and can be used.[/b]
    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen
    /*
    "enter height"
    call enter/settings (which is now user input function in new code)
    height=MyVal

    "enter range"
    call user_input
    range=MyVal

    "enter surface area"
    call user_input
    area=MyVal
    */
    }
     
    //*********************************************************
    /*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

        uses "zero error 1 second timer"
        system to generate a 2 second interval, then every
        2 seconds it reads an analog voltage from a
        Sharp GP2 distance sensor and converts it to decimal
        distance, then sends that data to a LCD

        Code for MikroC, config handled by MikroC compiler;
        _INTI02_OSC_1H
        _WDT_OFF_2H
        -MCLRE_ON_3H
        _LVP_OFF_4L
        _PWRT_ON_2L
    */
    //*********************************************************

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

     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }

     
     
  3. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    This code checks 4 times a second
    Code (text):

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

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char cmHigh, cmLow;

         

    #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 int LiquidLevel;
    unsigned char NumDec;
    unsigned char NumSep[2];
       
    unsigned char i,j,k;
    //char temp[8];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= 250000)      // if reached 2 seconds!
                    {
                        bres -= 250000; // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(cm10 + '0');
                        lcd_data(cm + '0');
                        lcd_puts(" [cm] ");         //comment this out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }
    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // [b]used for voltage calculations backup[/b]
        // 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

        //[b]Create a copy of math for more use[/b]
        mathKeep = math;
        //LiquidLevel=height-; 

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //[b]Now our original data is back and can be used.[/b]
    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen
    /*
    "enter height"
    call enter/settings (which is now user input function in new code)
    height=MyVal

    "enter range"
    call user_input
    range=MyVal

    "enter surface area"
    call user_input
    area=MyVal
    */
    }
     
    //*********************************************************
    /*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

        uses "zero error 1 second timer"
        system to generate a 2 second interval, then every
        2 seconds it reads an analog voltage from a
        Sharp GP2 distance sensor and converts it to decimal
        distance, then sends that data to a LCD

        Code for MikroC, config handled by MikroC compiler;
        _INTI02_OSC_1H
        _WDT_OFF_2H
        -MCLRE_ON_3H
        _LVP_OFF_4L
        _PWRT_ON_2L
    */
    //*********************************************************

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

     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }

     
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0

    lol OK Super Cool:) That fixes the get to home screen problem hehehe but it comes with a price.....

    the sensors reading slow.....
     
    Last edited: Sep 18, 2009
  6. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Loading Home:)

    It got a bit faster.....R u changing the oscillator frequency???
     
  7. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    It needs to be pretty fast to detect the changes in the level of the liquid

    MATHKEEP:rolleyes: Ok thats a better solution by far...lol dont know why my thinking is so complicated hehehe maybe coz im a gal :D
     
    Last edited: Sep 18, 2009
  8. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Thanks AtomSoft....You helped solve alot of problems
     
  9. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Code (text):
    unsigned char LLHigh, LLLow;
    unsigned int LiquidLevel;

    Code (text):

    void calc_distance(void)
    {
    unsigned int mathKeep;      // used for voltage calculations backup
        // 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

        //Create a copy of math for more use
        mathKeep = math;
       

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //Now our original data is back and can be used.
        [COLOR="Plum"]do i need to say height=user_input???[/COLOR]
          [COLOR="Red"]LiquidLevel=height-math;
          //LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
          LLHigh = ( LiquidLevel / 10 ) + '0'; //
          LLLow = ( LiquidLevel % 10 ) + '0';  // [/COLOR]
         





    }
     
  10. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    LOL it workzzzzzzzzzzzzzzzzzzzzzzzz!!!!!!

    it displays the height-liquid level
     
  11. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    I only made the changes in RED highlight..................
    I entered the height as 70cm
    i put a paper 10cm away from the sensor...

    & it says measured 60cm

    :):):):):):):):):D:D:D:D:D:D

    Code (text):
    #include <pic.h>
    #include "pic.h"
    #include "delay.h"
    #include "math.h"
    #include <stdio.h>
    #include <stdlib.h> //

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char LLHigh, LLLow;

         

    #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 int LiquidLevel;
    unsigned char NumDec;
    unsigned char NumSep[2];
       
    unsigned char i,j,k;
    //char temp[8];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= 250000)      // if reached 2 seconds!
                    {
                        bres -= 250000; // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance
    [COLOR="Red"][B]
                        lcd_goto_L2();              //Only change line 2
                        lcd_data(LLHigh + '0');
                        lcd_data(LLLow + '0');
                        lcd_puts(" [cm] ");         //comment this out if you want[/B][/COLOR]
                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }
    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // used for voltage calculations backup
        // 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

        //Create a copy of math for more use
        mathKeep = math;
       

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //Now our original data is back and can be used.
       
        [B][COLOR="Red"]LiquidLevel=height-math;   
        //LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
          LLHigh = ( LiquidLevel / 10 ) + '0'; //
          LLLow = ( LiquidLevel % 10 ) + '0';  // [/COLOR][/B]
         





    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen

    }

     

    void main(void)
    {  
        init(); // initialise I/O ports, LCD
        while(1){
        home_screen();
       
     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }
     

    Hehe...just applying YOUR tricks there AtomSoft......................................:)
    Fast learner lol i hope i am...........THANX THANX THANX AtomSoft 4 President!!!


    Uhmmmmm but i still got to work on speeding it up.....(i am goin to do that now)
     
    Last edited: Sep 18, 2009
  12. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    OMG!!!! i dont know what happened now.....i reloaded the exact code from above(the one i made changes to...the one that was working) but!!!


    the measured "values" are ALPHABETS!!!!:eek: now
     
    Last edited: Sep 18, 2009
  13. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Ok there it is..... Shew!!!!working again BUT i noticed that.....it does still display measurements as ALPHABETS but this happens in acertain case.....:

    CASE 1[negative case]
    Eg if height=30
    distance away from sensor=40
    liquid level will thus be=-10 BUT we dont have negative distances....
    *(uhmmmm i declared LiquidLevel as unsigned int)

    AND thats when it displays all funny kind alien like wingding symbols hehehe...:eek:





    CASE 2 [positive case]
    But if height=30
    distance away from sensor=10
    lcd displays measuerd distance=20cm:)

    So basically the negative case(liquid level is higher than the container-maybe an overflow) is like an impossible situation in which case it would be appropriate to display a suitable message if the distance is negative???

    Uhmmm but also i should consider displaying a message if the container is full
    ie. container height=liquid level

    Well i want to know what can i do to prevent those funny symbols from appearing????

    & how can i speed up the sensor....i tried in vein hehe

    ADCON2 = 0b10100010; // right justify, 8Tad, 32Tosc would increasing the32Tosc help?
    O the speed all deals with the timer?

    Code (text):
    #include <pic.h>
    #include "pic.h"
    #include "delay.h"
    #include "math.h"
    #include <stdio.h>
    #include <stdlib.h> //

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char LLHigh, LLLow;
    unsigned int LiquidLevel;


         

    #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];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= 250000)      // if reached 2 seconds!
                    {
                        bres -= 250000; // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(LLHigh);
                        lcd_data(LLLow);
                        lcd_puts(" [cm] ");         //comment this out if you want

                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }
    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // used for voltage calculations backup
        // 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

        //Create a copy of math for more use
        mathKeep = math;
        //LiquidLevel=height-; 

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //Now our original data is back and can be used.
        LiquidLevel=height-math;   

          //LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
          LLHigh = ( LiquidLevel / 10 ) + '0'; //
          LLLow = ( LiquidLevel % 10 ) + '0';  //
         


    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen
    /*
    "enter height"
    call enter/settings (which is now user input function in new code)
    height=MyVal

    "enter range"
    call user_input
    range=MyVal

    "enter surface area"
    call user_input
    area=MyVal
    */
    }
     
    //*********************************************************
    /*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

        uses "zero error 1 second timer"
        system to generate a 2 second interval, then every
        2 seconds it reads an analog voltage from a
        Sharp GP2 distance sensor and converts it to decimal
        distance, then sends that data to a LCD

        Code for MikroC, config handled by MikroC compiler;
        _INTI02_OSC_1H
        _WDT_OFF_2H
        -MCLRE_ON_3H
        _LVP_OFF_4L
        _PWRT_ON_2L
    */
    //*********************************************************

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

     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }
     
     
  14. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    no :D if you take out that delay or make it less then its faster:
    Code (text):


    void userMenu(char pos){
        unsigned int delaytime = 100000; // 100ms [COLOR=RED][b]CHANGE THIS FOR YOUR BELOW DELAY[/b] [/COLOR]
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value[b][COLOR="Red"]
                    if(bres >= delaytime )      // if reached 2 seconds!
                    {
                        bres -= delaytime ; // subtract 2 seconds, keep error [/COLOR][/b]
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(cm10 + '0');
                        lcd_data(cm + '0');
                        lcd_puts(" [cm] ");         //comment this out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

     
     
    Last edited: Sep 18, 2009
  15. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    sorry im not a negative number person :( not sure how to allow it... just got back from work. Ill take a look in a minute
     
  16. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Yeah thats cool

    Maybe i should say something like :

    1)if liquid level<0 [ie. negative]
    [this would happen for an over flow ie .when the level of the liquid is > height of container]
    then--> lcd display "ERROR"

    in this way it would prevent funny symbols from being displayed...........
    AND all negative distances will be represented by "error"



    2)if liquid level=height then--> lcd display "FULL"

    3)if liqud level level=00 then--> lcd display "EMPTY"


    so these 3 cases cater for all 3 scenarios that can take place.....
    sounds good???
     
  17. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    The speed is much much better now-:)only changed the part in RED.....hope im displaying it correctly to LCD. The alien wingdings appear when the level is negative otherwise it displays positive values correctly

    Code (text):
    [COLOR="Red"][B]    lcd_goto_L2();              //Only change line 2
                        lcd_data(LLHigh);
                        lcd_data(LLLow);
                        lcd_puts(" [cm] ");         //comment this [/B][/COLOR]out if you want

    here the code with the red highlight included:

    Code (text):
    #include <pic.h>
    #include "pic.h"
    #include "delay.h"
    #include "math.h"
    #include <stdio.h>
    #include <stdlib.h> //

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char LLHigh, LLLow;
    unsigned int LiquidLevel;


         

    #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];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        unsigned int delaytime = 100000; // 100ms CHANGE THIS FOR YOUR BELOW DELAY
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= delaytime )      // if reached 2 seconds!
                    {
                        bres -= delaytime ; // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                    [COLOR="Red"][B]    lcd_goto_L2();              //Only change line 2
                        lcd_data(LLHigh);
                        lcd_data(LLLow);
                        lcd_puts(" [cm] ");         //comment this [/B][/COLOR]out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // used for voltage calculations backup
        // 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

        //Create a copy of math for more use
        mathKeep = math;
        //LiquidLevel=height-; 

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //Now our original data is back and can be used.
        LiquidLevel=height-math;   

          //LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
          LLHigh = ( LiquidLevel / 10 ) + '0'; //
          LLLow = ( LiquidLevel % 10 ) + '0';  //
         


    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen
    /*
    "enter height"
    call enter/settings (which is now user input function in new code)
    height=MyVal

    "enter range"
    call user_input
    range=MyVal

    "enter surface area"
    call user_input
    area=MyVal
    */
    }
     
    //*********************************************************
    /*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

        uses "zero error 1 second timer"
        system to generate a 2 second interval, then every
        2 seconds it reads an analog voltage from a
        Sharp GP2 distance sensor and converts it to decimal
        distance, then sends that data to a LCD

        Code for MikroC, config handled by MikroC compiler;
        _INTI02_OSC_1H
        _WDT_OFF_2H
        -MCLRE_ON_3H
        _LVP_OFF_4L
        _PWRT_ON_2L
    */
    //*********************************************************

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

     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }
     



    I didnt use this below to display
    Code (text):

    lcd_data(LLHigh + '0');
        //  lcd_data(LLLow + '0');
    because the LCD displays ALPHABET measurements

    EG

    Measured

    ae
     
    Last edited: Sep 18, 2009
  18. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Try this it will show 00cm if its a Negative:

    Code (text):

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

    void userMenu(char pos); //  
    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(char expire);  
    unsigned char user_input(void);
    void home_screen(void);
    void EnterHeight(void);
    void EnterScreen(void);
    void ShowDigits(unsigned char val);
    void calc_distance(void);
    void main(void);


    unsigned char cm2LCD;

    unsigned char LLHigh, LLLow;
    unsigned int LiquidLevel;


         

    #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];
    //[/b]
    unsigned char height=50;
    unsigned char range;
    unsigned char area;
    unsigned char SensorPos=10;
    //[/b] New Vars
    char input_sw;

     
    char mnuPOS;

    unsigned char MyVal;
    unsigned char MyValLCD[2];
    unsigned char MyMaxVal;
    unsigned char MyMinVal;
    unsigned long bres;     // for bresenham 2-second timer system

    unsigned char ;

    #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(2); //wait for LCD to be ready shorter delay
        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(2); //wait for LCD to be ready shorter delay
        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(0x02);
     
        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)
    {  
       
        // setup the PIC 16f690
        OSCCON = 0x72;          // internal osc, 8MHz


        PORTA = 0;
        TRISA = 0b10010010;     // RA7 high imp, RA3 is serial out, RA4 button input


       
        PORTB = 0;              // PORTB not used
        WPUB = 1;               // PORTB pullups ON    
        RABPU = 0;


        /* Init ADC */
        ADCON0 = 0b10000101;    // bit 7 right justify,analogue channel select bits bits5-2  0001=AN1,ADC ON, RA1 is ADC input
        ADCON1 = 0b00100000;    //bits6-4  fosc/32
        ADON=1;                 // turn on the A2D conversion module

       
        ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
        ANSELH=0x00;

        T1CON = 0b00010001;     // TMR1 is ON, 1:2 prescale, =1MHz
        T2CON = 0b00000101;     // TMR2 is ON, 1:4 prescale, =1MHz



        MyVal = 0; //initializn these variables here
        MyMinVal = 0;
        MyMaxVal = 99;
     
        TRISB=0x00;
        TRISC=0xFC;
       
        lcd_init(); //call LCD initialisation

    }
    //EDITED this a bit. now if expire input is set it will leave loop with a 0
    //instead of rechecking this will be useful for display your measured data and
    //waiting for user to exit.
    char WaitForInput(char expire){
    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;
        }
        if(expire == 1) break;
    }//end of while
        DelayMs(150);    //debounce
        return temp;
    }//
    void userMenu(char pos){
        unsigned int delaytime = 100000; // 100ms CHANGE THIS FOR YOUR BELOW DELAY
        lcd_clear();
        lcd_goto_L1();

        switch(pos){
            case 0:
                lcd_puts("    HEIGHT    ");
                break;     
            case 1:
                lcd_puts("    RANGE     ");
                break;     
            case 2:
                lcd_puts(" SURFACE AREA ");
                break;                          //
            case 3:
                lcd_puts("   MEASURED   ");
                 while(WaitForInput(1) != 2){       //Wait for user to press enter to leave loop

                    // wait for 2 seconds, uses TMR1 free running at 1Mhz
                    while(!TMR1IF)          // wait for TMR1 overflow
                    TMR1IF = 0;             // clear overflow flag

                    bres += 65536;          // add 65536uS to bres value
                    if(bres >= delaytime )      // if reached 2 seconds!
                    {
                        bres -= delaytime ; // subtract 2 seconds, keep error
               
                        // read the ADC voltage RA1 (Sharp GP2 sensor)
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
                        lcd_data(LLHigh);
                        lcd_data(LLLow);
                        lcd_puts(" [cm] ");         //comment this out if you want
                   }
            }
            lcd_goto_L1();
            lcd_puts(" Loading Home ");
            lcd_goto_L2();
            lcd_puts("              ");
            DelayS(1);
            break;
        }

        if(pos == 3) return;
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    // New Menu System
    void EnterHeight(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" ENTER HEIGHT ");
        lcd_goto_L2();
        lcd_puts("Press Up/Down"); //home screen message (line 2)
    }

    void EnterScreen(void){
        lcd_clear();
        lcd_goto_L1();
        lcd_puts(" [cm] ");
    }

    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)
    {
    unsigned int mathKeep;      // used for voltage calculations backup
        // 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

        //Create a copy of math for more use
        mathKeep = math;
        //LiquidLevel=height-; 

        // convert from 0-99 to 2 decimal digits, 0-99cm
        cm10=0;
        while(math >= 10)
        {
            cm10++;
            math -= 10;
        }
        cm = math;

        math = mathKeep;    //Now our original data is back and can be used.
        [b][color=red]//This will check if negative
        LiquidLevel=height-math;   
            if((LiquidLevel < 0) || (LiquidLevel > 0xFFB0))
            LiquidLevel = 0;
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D[/color][/b]
          //LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
          LLHigh = ( LiquidLevel / 10 ) + '0'; //
          LLLow = ( LiquidLevel % 10 ) + '0';  //
         


    }
     //
    unsigned char user_input(void)      //This will return what we want
    {
        char done = 0;
     
        MyVal = 0;          //Start on 0
        while(done == 0){
          input_sw = WaitForInput(0);
           
          switch(input_sw){
            case 1:
                done = 0xff;            //This tells us the user finished entering
                lcd_goto_L1();
                lcd_puts("      OK       "); //home screen message (line 1)
                break;
            case 3:
                if(MyVal < MyMaxVal)
                    MyVal++;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            case 4:
                if(MyVal > MyMinVal)
                    MyVal--;
                EnterScreen();
                ShowDigits(MyVal);
                break;
            default:
                break;
          }
         
        }
        DelayMs(250);
        DelayMs(250);
        return MyVal;
    }

    void home_screen(void){
        mnuPOS = 0;
        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)
     
        input_sw = 0;           //Reset the value

        while(input_sw != 1)    //Wait until enter is pressed
            input_sw = WaitForInput(0);

        userMenu(0);
        DelayMs(2);             //shorter delay
        height = user_input();  //The HEIGHT var will have the myVal

        userMenu(1);
        DelayMs(2);             //shorter delay
        range = user_input();   //The HEIGHT var will have the myVal

        userMenu(2);
        DelayMs(2);             //shorter delay
        area = user_input();    //The HEIGHT var will have the myVal
    //
        userMenu(3);
        DelayMs(2);             //shorter delay
        input_sw = 0;           //Reset the value

    //Waits for user to press ENTER to show home screen
    /*
    "enter height"
    call enter/settings (which is now user input function in new code)
    height=MyVal

    "enter range"
    call user_input
    range=MyVal

    "enter surface area"
    call user_input
    area=MyVal
    */
    }
     
    //*********************************************************
    /*  Junebug_Serial4.c    RomanBlack.com 19th July 2009.

        uses "zero error 1 second timer"
        system to generate a 2 second interval, then every
        2 seconds it reads an analog voltage from a
        Sharp GP2 distance sensor and converts it to decimal
        distance, then sends that data to a LCD

        Code for MikroC, config handled by MikroC compiler;
        _INTI02_OSC_1H
        _WDT_OFF_2H
        -MCLRE_ON_3H
        _LVP_OFF_4L
        _PWRT_ON_2L
    */
    //*********************************************************

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

     /*// wait for 2 seconds, uses TMR1 free running at 1Mhz
        while(!TMR1IF)  // wait for TMR1 overflow
        TMR1IF = 0;     // clear overflow flag

        bres += 65536;          // add 65536uS to bres value
        if(bres >= 2000000)     // if reached 2 seconds!
         {
            bres -= 2000000;    // subtract 2 seconds, keep error
               
            // read the ADC voltage RA1 (Sharp GP2 sensor)
            GODONE=1;   // initiate conversion on the channel 0
            while(GODONE) continue;  // Wait convertion done
            calc_distance();        // convert ADC value to distance
        //  LiquidLevel=height-;
        //  lcd_clear();                // Using the new menu you can erase or
        //  lcd_data(cm10 + '0');
        //  lcd_data(cm + '0');
         //   lcd_goto_L2();
           // lcd_puts("[cm] ");            //comment this out if you want
    */
     
         
           
                 
     
       }
    }

     
     
    Last edited: Sep 18, 2009
  19. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,160
    Likes:
    340
    Location:
    Brisbane Australia
    ONLINE
    The usual way to handle negative numbers is by doing something like,
    Code (text):

        if(value<0){        //if negative
            value=-value;   //negate it
            LcdPut('-')     //print minus character
        }else{              //if positive
            LcdPut(' ')     //print space to keep allignment
        }
     
    As you are doing the calcs in a function, you could set a flag in you code when you negate it.

    Mike.
     
  20. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    ok i will try the code....Thanx AtomSoft....

    Tried it & it works:):):):):):):)....

    *i will also write some code for calculating the volume of the liquid in the container....
    surface area X level of liquid

    Now later today im going to test this "IR LLD" on LIQUIDS:D:D:D How exciting lol....................I hope it works accurately.....



    For now im going to start learning for my exams:eek:
     
    Last edited: Sep 19, 2009
  21. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,233
    Likes:
    645
    Location:
    Ex Yorks' Hants UK
    Morning Miss f,

    IMO 'error/overflow' is misleading, sounds as though the 'tank' is over full.:)

    Pommie's method is often used to indicate less than zero values.
     

Share This Page