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. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Hello Ericgibbs......Yeah you right lol THATS Y I edited that post and removed what i said lol-but u beat me to it
     
  2. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    heh since its unsigned you cant check a < 0 am i right because it would be > 0 anyway cuz the roll over stuff
    Try
    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 posneg;
    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
    //[b]
                        if(posneg == 'p')
                            lcd_data('+');
                        else
                            lcd_data('-');
    //[/b]
                        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 tmp;
    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.
        //This will check if negative
        LiquidLevel=height-math;   

    //[b]
        posneg = 'p';
            if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
            LiquidLevel = -LiquidLevel ;
            posneg = 'n';
        }
    //[/b]
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
          //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 19, 2009
  3. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Yeah it displays + numbers when the height > liquid level:)

    it displays - numbers when the height < liquid level:)
     
  4. dave

    Dave New Member

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


     
  5. fantabulous68

    fantabulous68 Member

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

    This should help reduce fluctuations. Increase the shift value to increase noise rejection, but it will slow the response.
    Code (text):

    Code:

    typdef struct filter_type
    {
       Uint16 accumulator;
       Uint16 output;
       Uint8 shift_value;
       Uint8 initialized;
    };

    filter_type adc_filter;

    [COLOR="Red"]void Init_Filter( filter_type *filter, Uint8 shift )[/COLOR]
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    [COLOR="Red"]void Update_Filter( filter_type *filter, Uint16 new_value )[/COLOR]
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }
     
    Whenever you read your adc, just call Update_Filter( &adc_filter, adc_value ). Wherever you perform a calculation on the ADC value, use adc_filter.output instead.

    I haven't read your code, so I'm not positive that this is in any way helpful at all.

    This is from Noggin....

    I included it in the code below in red highlight...but
    Yikes i dont know how to do the type declaration.....for
    void Init_Filter( filter_type *filter, Uint8 shift )
    void Update_Filter( filter_type *filter, Uint16 new_value )
    ;
    please tell me how to do it.......



    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 posneg;
    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;
    }//

    [COLOR="Red"]
    typdef struct filter_type
    {
       Uint16 accumulator;
       Uint16 output;
       Uint8 shift_value;
       Uint8 initialized;
    };

    filter_type adc_filter;

    void Init_Filter( filter_type *filter, Uint8 shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( filter_type *filter, Uint16 new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }



    [/COLOR]



    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
    //
                        if(posneg == 'p')
                            lcd_data('+');
                        else
                            lcd_data('-');
    //
                        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 tmp;
    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.
        //This will check if negative
        LiquidLevel=height-math;   

    //
        posneg = 'p';
            if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
            LiquidLevel = -LiquidLevel ;
            posneg = 'n';
        }
    //
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
          //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
    */
     
         
           
                 
     
       }
    }
     
     
  6. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    The code compiles successfully until i added the code in red below.....its giving alot of compile errors. What am i doing wrong....?????im not very familiar with structures and pointers...i think my header declarations are wrong.....

    Code (text):
    #include <pic.h>
    #include "pic.h"
    #include "delay.h"
    #include "math.h"
    #include <stdio.h>
    #include <stdlib.h>
    [COLOR="Red"]
    typdef struct filter_type
    {
       Uint16 accumulator;
       Uint16 output;
       Uint8 shift_value;
       Uint8 initialized;
    };

    filter_type adc_filter;[/COLOR]

    [COLOR="Red"]void Init_Filter( filter_type *filter, Uint8 shift );
    void Update_Filter( filter_type *filter, Uint16 new_value );[/COLOR]

    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 posneg;
    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;
    }//



    [COLOR="Red"]
    void Init_Filter( filter_type *filter, Uint8 shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( filter_type *filter, Uint16 new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }
    [/COLOR]







    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
    //
                        if(posneg == 'p')
                            lcd_data('+');
                        else
                            lcd_data('-');
    //
                        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 tmp;
    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.
        //This will check if negative
        LiquidLevel=height-math;   

    //
        posneg = 'p';
            if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
            LiquidLevel = -LiquidLevel ;
            posneg = 'n';
        }
    //
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
          //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
    */
     
         
           
                 
     
       }
    }
     
  7. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    You have to convert that code to Hi-Tech heh

    Im no good with structures but you can change:
    Code (text):

    void Init_Filter( filter_type *filter, Uint8 shift );
    void Update_Filter( filter_type *filter, Uint16 new_value );
     
    to
    Code (text):

    void Init_Filter( filter_type *filter, unsigned char shift );
    void Update_Filter( filter_type *filter, unsigned int new_value );
     
    and

    Code (text):

    void Init_Filter( filter_type *filter, Uint8 shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( filter_type *filter, Uint16 new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }

     
    To:
    Code (text):

    void Init_Filter( filter_type *filter, unsigned char shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( filter_type *filter, unsigned int new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }

     
    As for the
    Code (text):

    typdef struct filter_type
    {
       Uint16 accumulator;
       Uint16 output;
       Uint8 shift_value;
       Uint8 initialized;
    };

    filter_type adc_filter;

     
    To something like:
    Code (text):

    typdef struct filter_type
    {
       unsigned int accumulator;
       unsigned int output;
       unsigned char shift_value;
       unsigned char initialized;
    };

    filter_type adc_filter;

     
     
    Last edited: Sep 20, 2009
  8. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Look through this code. I didnt bold or red it./ you should be able to see what i did here:

    Code (text):

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

    #define FALSE 0
    #define TRUE  1
    struct filter_type {
       unsigned int accumulator;
       unsigned int output;
       unsigned char shift_value;
       unsigned char initialized;
    } ;

    struct filter_type adc_filter;

    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 posneg;
    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 Init_Filter( struct filter_type *filter, unsigned char shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( struct filter_type *filter, unsigned int new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }







    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
    //
                        if(posneg == 'p')
                            lcd_data('+');
                        else
                            lcd_data('-');
    //
                        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 tmp;
    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.
        //This will check if negative
        LiquidLevel=height-math;   

    //
        posneg = 'p';
            if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
            LiquidLevel = -LiquidLevel ;
            posneg = 'n';
        }
    //
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
          //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
    */
     
         
           
                 
     
       }
    }

     
     
  9. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    to understand structures in any language i suggest you open up a header file like time.h or delays.h or something and there will usually be a structure in some headers and you can see how to use em from there.
     
  10. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Yeah i see what you did........
    I'll definitely look into that......
     
  11. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    it still doesnt compile...it says arguments redeclared
     
  12. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    Are you using other header files?
    I compiled it and i get:

    Code (text):

    Build D:\Micro\PIC\help01\main for device 16F690
    Using driver C:\Program Files\HI-TECH Software\PICC\PRO\9.65\bin\picc.exe

    Make: The target "D:\Micro\PIC\help01\ssome.p1" is out of date.
    Executing: "C:\Program Files\HI-TECH Software\PICC\PRO\9.65\bin\picc.exe" --pass1 D:\Micro\PIC\help01\ssome.c -q --chip=16F690 -P --runtime=default --opt=default -D__DEBUG=1 -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
    Executing: "C:\Program Files\HI-TECH Software\PICC\PRO\9.65\bin\picc.exe" -omain.cof -mmain.map --summary=default --output=default ssome.p1 --chip=16F690 -P --runtime=default --opt=default -D__DEBUG=1 -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
    HI-TECH C PRO for the PIC10/12/16 MCU family (Lite)  V9.65PL1
    Copyright (C) 1984-2009 HI-TECH SOFTWARE
    (1273) Omniscient Code Generation not available in Lite mode (warning)
    Warning [765] D:\Micro\PIC\help01\ssome.c; 466. degenerate unsigned comparison

    Memory Summary:
        Program space        used   6D0h (  1744) of  1000h words   ( 42.6%)
        Data space           used    3Fh (    63) of   100h bytes   ( 24.6%)
        EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
        Configuration bits   used     0h (     0) of     1h word    (  0.0%)
        ID Location space    used     0h (     0) of     4h bytes   (  0.0%)

    Running this compiler in PRO mode, with Omniscient Code Generation enabled,
    produces code which is typically 52% smaller than in Lite mode.
    The HI-TECH C PRO compiler output for this code could be 906 words smaller.
    See http://microchip.htsoft.com/portal/pic_pro for more information.

    Loaded D:\Micro\PIC\help01\main.cof.

    ********** Build successful! **********
     
     
  13. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    i only have pic.h and delay.h in the folder were im saving all my code.....
     
  14. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    This is very very weird...
    I have 2 folders irMPLAB

    1 on my desktop and another on my flash-they duplicates

    The 1 from on my desktop with the code you posted does not compile

    i pasted the same code to the FLASH folder and ran and it compiled successfully.

    Actually all my desktop code i saved are not compiling successfully anymore and they were b4....



    Code (text):
    Clean: Deleting intermediary and output files.
    Clean: Deleted file "F:\irMPLAB\ctest.obj".
    Clean: Deleted file "F:\irMPLAB\ctest.sdb".
    Clean: Deleted file "F:\irMPLAB\ctest.rlf".
    Clean: Deleted file "F:\irMPLAB\ctest.lst".
    Clean: Deleted file "F:\irMPLAB\ctest.cof".
    Clean: Deleted file "F:\irMPLAB\ctest.hex".
    Clean: Deleted file "F:\irMPLAB\ctest.sym".
    Clean: Deleted file "F:\irMPLAB\ctest.map".
    Clean: Deleted file "F:\irMPLAB\ctest.hxl".
    Clean: Deleted file "F:\irMPLAB\startup.lst".
    Clean: Deleted file "F:\irMPLAB\startup.rlf".
    Clean: Done.
    Build F:\irMPLAB\ctest for device 16F690
    Using driver C:\Program Files\HI-TECH Software\PICC\lite\9.60\bin\picc.exe

    Executing: "C:\Program Files\HI-TECH Software\PICC\lite\9.60\bin\picc.exe" -C F:\irMPLAB\ctest.c -q --chip=16F690 -P --runtime=default --opt=default -D__DEBUG=1 -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
    Warning [176] F:\irMPLAB\ctest.c; 214.0 missing newline
    Executing: "C:\Program Files\HI-TECH Software\PICC\lite\9.60\bin\picc.exe" -octest.cof -mctest.map --summary=default --output=default ctest.obj --chip=16F690 -P --runtime=default --opt=default -D__DEBUG=1 -g --asmlist "--errformat=Error   [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
    HI-TECH PICC-Lite COMPILER (Microchip PICmicro) V9.60
    Copyright (C) 1984-2006 HI-TECH SOFTWARE

    Memory Usage Map:

    Program space:
        CODE                 used   443h (  1091) of   800h words   ( 53.3%)
        CONST                used     0h (     0) of   800h words   (  0.0%)
        ENTRY                used    16h (    22) of   800h words   (  1.1%)
        STRING               used    1Fh (    31) of   800h words   (  1.5%)

    Data space:
        BANK0                used    23h (    35) of    60h bytes   ( 36.5%)
        BANK1                used     0h (     0) of    50h bytes   (  0.0%)
        COMBANK              used     0h (     0) of    10h bytes   (  0.0%)

    EEPROM space:
        EEDATA               used     0h (     0) of   100h bytes   (  0.0%)

    ID Location space:
        IDLOC                used     0h (     0) of     4h bytes   (  0.0%)

    Configuration bits:
        CONFIG               used     0h (     0) of     1h word    (  0.0%)

    Summary:
        Program space        used   478h (  1144) of   800h words   ( 55.9%)
        Data space           used    23h (    35) of    B0h bytes   ( 19.9%)
        EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
        ID Location space    used     0h (     0) of     4h bytes   (  0.0%)
        Configuration bits   used     0h (     0) of     1h word    (  0.0%)

    Loaded F:\irMPLAB\ctest.cof.

    ********** Build successful! **********
     
     
    Last edited: Sep 21, 2009
  15. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    heh thats weird but glad to see it compiled :D
     
  16. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    yeah me as well...gonna do some exam learning now...cya around:)
    Shipping charges for LCDs from here would be too much hehe
     
  17. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    I was advised by Noggin:
    I added the code in RED Highlight below...I just want to know if im using it in the correct place...

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

    #define FALSE 0
    #define TRUE  1
    struct filter_type {
       unsigned int accumulator;
       unsigned int output;
       unsigned char shift_value;
       unsigned char initialized;
    } ;

    struct filter_type adc_filter;

    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 posneg;
    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;

    unsigned char height=50;
    unsigned char range=10;
    unsigned char area;


    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 Init_Filter( struct filter_type *filter, unsigned char shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( struct filter_type *filter, unsigned int new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }







    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)
                        [COLOR="DarkOrchid"][B]//   Whenever you read your adc, just call Update_Filter( &adc_filter, adc_value ).[/B][/COLOR]
                        GODONE=1;                   // initiate conversion on the channel 0
                        while(GODONE) continue;     // Wait convertion done
                        [COLOR="Red"][B]Update_Filter( &adc_filter, adc_value );[/B][/COLOR]
                        calc_distance();            // convert ADC value to distance

                        lcd_goto_L2();              //Only change line 2
    //
                        if(posneg == 'p')
                            lcd_data('+');
                        else
                            lcd_data('-');
    //
                        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 tmp;
    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

    [COLOR="DarkOrchid"][B]//Wherever you perform a calculation on the ADC value, use adc_filter.output instead.[/B][/COLOR]
       
    //  math = ADRESH;
       [COLOR="Red"][B] math=adc_filter.output;[/B][/COLOR]
        math = (math * 256);
    //  math += ADRESL;
        [COLOR="Red"][B]math +=adc_filter.output;[/B][/COLOR]


        // 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.
        //This will check if negative
        LiquidLevel=height-math;   

    //
        posneg = 'p';
            if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
            LiquidLevel = -LiquidLevel ;
            posneg = 'n';
        }
    //
        //if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
          //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


    }
     
    //*********************************************************
    /*  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();


           
                 
     
       }
    }
     


    Im a bit unsure about:


    Code (text):
    [COLOR="DarkOrchid"][B]//Wherever you perform a calculation on the ADC value, use adc_filter.output instead.[/B][/COLOR]
       
    //  math = ADRESH;
       [COLOR="Red"][B] math=adc_filter.output;[/B][/COLOR]
        math = (math * 256);
    //  math += ADRESL;
        [COLOR="Red"][B]math +=adc_filter.output;[/B][/COLOR]

    Can adc_filter.output be broken up into a high & low value then assigned to math?
    OR do i assign adc_filter output directly to math as is??
     
  18. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    What is adc_value? You might need to replace that. I hate structures heh
    The issue is you do math on 2 parts Low and Hi. Not sure what the structure accomplishes heh
     
  19. fantabulous68

    fantabulous68 Member

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



    i tested the project on liquids & responded:

    ME:The readings are fluctuating.....not very stable especially for water....



    Noggin:This should help reduce fluctuations. Increase the shift value to increase noise rejection, but it will slow the response.



    Code (text):
    Code:

    typdef struct filter_type
    {
       Uint16 accumulator;
       Uint16 output;
       Uint8 shift_value;
       Uint8 initialized;
    };

    filter_type adc_filter;

    void Init_Filter( filter_type *filter, Uint8 shift )
    {
       filter->initialized = FALSE;
       filter->shift_value = shift;
    }

    void Update_Filter( filter_type *filter, Uint16 new_value )
    {
       if (filter->initialized != TRUE)
       {
          filter->output = new_value;
          filter->accumulator = new_value << filter->shift_value;
          filter->initialized = TRUE;
       }
       else
       {
          filter->accumulator -= filter->output;
          filter->accumulator += new_value;
          filter->output = filter->accumulator >> filter->shift_value;
       }
    }





    MR RB:


    The output of the sensor(the distance to the surface of the liquid) is an analogue voltage.....So we do ADC on that....& thats the ADC value

    load ADC value in 16bit math var---->So ADRESH and ADRESL contain the adc values im sure.
     
  20. AtomSoft

    AtomSoft Well-Known Member

    Joined:
    Feb 7, 2008
    Messages:
    5,670
    Likes:
    41
    Location:
    Brooklyn, NY US
    To average the readings you should make a nice simple variable like:

    unsigned int adc_temp[3];

    Then take about 3 readings placing the data in each var using a loop with a delay..

    Code (text):

    for(x=0;x<3;x++){
        GODONE=1;
        while(GODONE) continue;
        adc_temp[x] = (ADRESH << 4) | ADRESL;
        DelayMs(100);
    }

    //Now average the readings
    adc_actual = (adc_temp[0] + adc_temp[1] + adc_temp[2]) / 3;
     
     
    Last edited: Sep 22, 2009
  21. fantabulous68

    fantabulous68 Member

    Joined:
    Feb 20, 2007
    Messages:
    323
    Likes:
    0
    Ok that seems like a more simple way to average the readings...I will try it out later tonight on the sensor...Thanks AtomSoft
     

Share This Page