response to membrane switch is uneven

Discussion in 'Embedded Systems and Microcontrollers' started by harsha3842, Feb 26, 2014.

  1. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    the code below is for detecting switch signals from a membrane board and display it on an LCD
    everything works fine but the response for the switch pressed is skipped.
    i.e when ever a switch is pressed a warning is displayed for certain conditions but these are not activated sometimes, every 2 to 3 presses a switch gives an output. this has to be reduced to every single time the switch is pressed

    below is the code:

    {
    if(WHL==1) //Work head lock clear field
    {
    lcdcomm(0x97); //Blank message
    lcdmsg(" ");
    }
    if(SPHL==1) //Sphere lock blank
    {
    lcdcomm(0xA2); //Blank message
    lcdmsg(" ");
    }
    if(WHUL==1) //Work head unlock clear field
    {
    reg1=0; //Switch status
    lcdcomm(0x97); //Blank message
    lcdmsg(" ");
    }
    if(SPHUL==1) //Sphere unlock clear field
    {
    reg2=0; //Switch status
    lcdcomm(0xA2); //Blank message
    lcdmsg(" ");
    }
    if(WHL==0) //Work head lock ON status
    {
    reg1=0; //Switch status
    reg=1; //Switch status
    lcdcomm(0x97); //Lock message
    lcdmsg("Lock");
    }
    if(WHUL==0) //Work head unlock ON status
    {
    reg1=1; //Switch status
    reg=1; //Switch status
    lcdcomm(0x97); //Unlock message
    lcdmsg("UnLock");
    }
    if(SPHL==0) //Sphere lock ON status
    {
    reg2=0; //Switch status
    reg=1; //Switch status
    lcdcomm(0xA2); //Lock message
    lcdmsg("Lock");
    }
    if(SPHUL==0) //Sphere unlock ON status
    {
    reg2=2; //Switch status
    reg=1; //Switch status
    lcdcomm(0xA2); //Unlock message
    lcdmsg("UnLock");
    }
    swt=reg1+reg2; //Switch status
    if(SPON==0) //Spindle ON status
    {
    reg=2; //Switch status
    Code ( (Unknown Language)):
    1.   if(WH_UL==0 || SPH_UL==0)                //Check WH & SPH unlock status
    2.         {
    3.             reg=6;                                //Switch status
    4.         }
    this is when the switch has to be detected for the error msg
    }
    else
    if(SPON==1) //Spindle OFF status
    {
    reg=1; //Switch status
    Code ( (Unknown Language)):
    1.    if(SP_ON==0)                            //Check spindle ON status
    2.         {
    3.             reg=2+swt;                            //Switch status
    4.         }
    5.  
    error msg for a different switch }
    if(SPJ==0) //Spindle JOG status
    {
    reg=7; //Switch status
    }
    if(SPL==0) //Spindle LOCK status
    {
    reg=8; //Switch status
    }
    switch(reg) //Switch
    {
    case 1: //Case 1 of switch
    lcdcomm(0xDC);
    lcdmsg(" ");
    lcdcomm(0xDC); //OFF message
    lcdmsg("OFF");
    break;
    case 2: //Case 2 of switch
    lcdcomm(0xDC);
    lcdmsg(" ");
    lcdcomm(0xDC); //ON message
    lcdmsg("ON");
    break;
    case 3: //Case 3 of switch
    buzz(); //Call buzz function
    clear(); //Work head warning message with blink and buzz
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x99);
    lcdmsg("Work Head");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x99);
    lcdmsg("Work Head");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x99);
    lcdmsg("Work Head");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    reg=0; //Switch status
    break;
    case 4: //Case 4 of switch
    buzz(); //Call buzz function
    clear(); //Sphere warning message with blink and buzz
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9B);
    lcdmsg("Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9B);
    lcdmsg("Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9B);
    lcdmsg("Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    reg=0; //Switch status
    break;
    case 5: //Case 5 of switch
    buzz(); //Call buzz function
    clear(); //WH & SPH warning message with blink and buzz
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x95);
    lcdmsg("Work Head & Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x95);
    lcdmsg("Work Head & Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x95);
    lcdmsg("Work Head & Sphere");
    lcdcomm(0xDA);
    lcdmsg("UnLocked");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    reg=0; //Switch status
    break;
    case 6: //Case 6 of switch
    buzz(); //Call buzz function
    clear(); //Spindle warning message with blink and buzz
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9A);
    lcdmsg("Spindle");
    lcdcomm(0xDD);
    lcdmsg("ON");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9A);
    lcdmsg("Spindle");
    lcdcomm(0xDD);
    lcdmsg("ON");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    lcdcomm(0xC6);
    lcdmsg("CAUTION!");
    lcdcomm(0x9A);
    lcdmsg("Spindle");
    lcdcomm(0xDD);
    lcdmsg("ON");
    buzz();
    Delay10KTCYx(200);
    clear();
    buzz();
    reg=0; //Switch status
    break;
    case 7:
    lcdcomm(0xDC);
    lcdmsg(" ");
    lcdcomm(0xDC); //Jog message
    lcdmsg("JOG");
    break;
    case 8:
    lcdcomm(0xDC);
    lcdmsg(" ");
    lcdcomm(0xDC); //Lock message
    lcdmsg("LOCK");
    break;
    }
    return;
    }


    switch statement is used for error msg

    is this because the switch cannot be detected while the processor is scanning each signal in an order? if so how to over come this error?
     
  2. alfacliff

    Well-Known Member

    Dec 13, 2013
    2,449
    428
    if your system accepts interupts, use them to get better response from switches.
     
    harsha3842 likes this.
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Below is TOO MUCH code. Besides (mostly) lacking code tags so your code remains readable you've just got a jumble there.

    Did you write all that before testing the switch reading code? That should have been your first (earlier at least) step: write the code to read the switch and display the output in a simple direct way. That step insures you have a good read routine that doesn't miss or double presses.

    I suggest you back up and perform that crucial step.

    Do post again if you have troubles, and to save time post your schematic as well.
     
    harsha3842 likes this.
  4. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    no interrupts for the pins used.

    the code works for everything else, tried by checking for the switch action first and then other checks yet the same problem.
    tried checking switch between every other check and still the same

    pins used for each signal
    Code ( (Unknown Language)):
    1. #define    lcdport LATB            //LCD Data PORT assignment
    2. #define    E LATDbits.LATD7        //LCD Enable bit
    3. #define    RS LATDbits.LATD6        //LCD Register select bit
    4. #define    WHL PORTCbits.RC0        //Work Head Lock LED signal
    5. #define    WHUL PORTCbits.RC1        //Work Head UnLock LED signal
    6. #define    SPHL PORTCbits.RC2        //Sphere Lock LED signal
    7. #define    SPHUL PORTCbits.RC3        //Sphere UnLock LED signal
    8. #define    SP_ON PORTCbits.RC4        //Spindle ON Switch signal
    9. #define    WH_UL PORTCbits.RC5        //Work Head UnLock Switch signal
    10. #define    SPH_UL PORTCbits.RC6    //Sphere UnLock Switch signal
    11. #define    SPON PORTDbits.RD0        //Spindle ON LED signal
    12. #define    PBAR PORTDbits.RD1        //Pressure Indication signal
    13. #define    SPJ PORTDbits.RD2        //Spindle JOG LED signal
    14. #define    SPL PORTDbits.RD3        //Spindle LOCK LED signal
    15. #define    BUZZ LATDbits.LATD4        //Buzzer for pressure indication
    16.  
    other functions used
    Code ( (Unknown Language)):
    1. void lcdbuild(unsigned char,unsigned char *);    //Function to customize LCD characters
    2. void lcdmsg(const rom char *);                    //Function to display message
    3. void lcdstr(unsigned char *);                    //Function to display string
    4. void lcdcomm(unsigned char);                    //Function for LCD command
    5. void lcddata(unsigned char);                    //Function for LCD data
    6. void lcdout(unsigned char);                        //Function to give LCD output
    7. void dispchar(void);                            //Function for creating multiple customized characters
    8. void animate(void);                                //Function for logo animation
    9. void animate1(void);                            //Function for logo animation
    10. void animate2(void);                            //Function for logo animation
    11. void animate3(void);                            //Function for logo animation
    12. void animate4(void);                            //Function for logo animation
    13. void lcdinit(void);                                //Function to initialize LCD
    14. void buzz(void);                                //Function for Buzzer pattern
    15. void clear(void);                                //Function to clear screen(2nd,3rd & 4th rows only)
    16. void loop(void);                                //Function for all operations which to be repeated
    17. void adc(void);                                    //Function for analog to digital conversion
    18. void ERROR_MSG(void);
    19.  
    switch checking code
    Code ( (Unknown Language)):
    1.  
    2.     if(!SP_ON || !WH_UL || !SPH_UL)                //Check ERROR status
    3.         {
    4.             while(swt==1)
    5.             {
    6.                 reg=reg1+reg2;
    7.                 ERROR_MSG();
    8.                 break;
    9.             }
    10.             while(swt==2)
    11.             {
    12.                 reg=4;
    13.                 ERROR_MSG();
    14.                 break;
    15.             }
    16.         }
    17.  
    the switch press checking code is repeated after every other check still when the switch is pressed it doesnt react immediately, some times for 2 presses some times for 3 and sometimes just for 1 press
    i want it for just one press.
     
  5. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    does using a debounce code speed up the process or slow it down?
    because it uses some delay in itself

    sample debounce code
    Code ( (Unknown Language)):
    1.  
    2. unsigned char is_sw1_pressed(void)
    3. {
    4.      if (PORTBbits.RB3==0)        // is SW1 pressed?
    5.      {                            //yes
    6.          delay_ms(10);            // wait 10mS for debounce.
    7.          if (LATBbits.LATB3==0)    // is SW1 still has pressed status after 10mS delay?
    8.          {                        // yes, we have key press
    9.              return 1;
    10.          }
    11.      }
    12.      return 0;// if key is not pressed,
    13.  return 0
    14.  }
    15.  
     
  6. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    The debounce code I use has little effect on code speed.

    Your code has a huge effect on the speed of your code... to the point where I wonder how you have any time at all to do anything useful and still read the buttons.

    Perhaps that is your response problem.

    The debounce routine I use checks the buttons every 25 mS, and if they are the same pronounce the buttons stable. "Buttons" as I check up to 8 at one time; could be more but I'm saving them in byte variables.

    The interval is provided by a timer. The timer trips an interrupt, and the interrupt is where my button code resides.
     
    harsha3842 likes this.
  7. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    a simple while loop for the switches solved the problem
    thanx for all the assists :)
     
  8. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    ADC() is delaying the process now
    if i put adc out of the loop its working fine but if adc inside the loop it slows the switch error, how to run adc() and the condition check sequence parallelly?????
     
  9. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Exactly! Start the ADC on a conversion and "periodically" check if it is complete.

    Don't wait for it to complete, start it, then immediately go on to other tasks.

    You can even use the same routine: when called and there is a complete conversion it processes the result, then starts another conversion before it returns, or better, reads the result, starts the next, then processes the result.

    If the routine detects no new data available it just returns. Note you may need a flag for "no data this time mate."
     
  10. harsha3842

    Thread Starter New Member

    Jul 5, 2013
    24
    0
    adc() function is built in for mplab ide c18
    Code ( (Unknown Language)):
    1.  
    2. #include <adc.h>                //ADC Files
    3. unsigned int adc_out=0;                //Initializations
    4. float adc_rpm=0;
    5.  
    6.  void main(void)
    7.      OpenADC(ADC_FOSC_32 &                        //ADC module initialization parameters
    8.             ADC_RIGHT_JUST &
    9.             ADC_4_TAD,ADC_CH0 &
    10.             ADC_INT_OFF &
    11.             ADC_VREFPLUS_VDD &
    12.             ADC_VREFMINUS_VSS,7);
    13.      adc();
    14.      CloseADC();  
    15.  }
    16.  
    17.  void adc(void)                                    //Function for analog to digital conversion
    18. {
    19.     SetChanADC (ADC_CH0);                        //Select ADC channel to be used
    20.     Delay10KTCYx(10);
    21.     lcdcomm(0xD1);                                //Clear field to display value
    22.     lcdmsg("   ");
    23.     ConvertADC();                                //Convert analog value to digital
    24.     while(BusyADC());                            //ADC busy status
    25.     adc_out=ReadADC();                            //ADC raw output collected in a register
    26.     adc_rpm=(adc_out*500.0)/1024;                //Raw value converted into RPM using formula
    27.     itoa(adc_rpm,convolt);                        //Convert float value to string
    28.     lcdcomm(0xD1);                                //Display RPM value on LCD
    29.     lcdstr(convolt);
    30.     Delay10KTCYx(1000);                            //Delay
    31. }
    32.  
    is the flow of adc function
     
  11. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Software is not like a bunch of parts you throw into a box and they all work together. It does not work like your car does, where each part advances some cause with the others all at the same time.

    Software is like a song where there are verses and a chorus and maybe a bridge and certainly an intro and an outro too. It is linear, it progresses. Your job even before you write the code is to make an outline of how and when things will react.

    You must start as a conductor and not a songwriter.

    Some function ABC() may be built into package XYZ but that does not mean you need use it. You are always free to write your own ABC2() routine: you know your app better then someone who never saw it.

    Your ADC2() routine should strive to eliminate any delays such as you have:

    Code ( (Unknown Language)):
    1.  
    2.  void adc(void)                                    //Function for analog to digital conversion
    3. {
    4.     SetChanADC (ADC_CH0);                        //Select ADC channel to be used
    5.     [B]Delay10KTCYx(10);[/B]
    6.     lcdcomm(0xD1);                                //Clear field to display value
    7.     lcdmsg("   ");
    8.     ConvertADC();                                //Convert analog value to digital
    9.     [B]while(BusyADC());                            //ADC busy status[/B]
    10.     adc_out=ReadADC();                            //ADC raw output collected in a register
    11.     adc_rpm=(adc_out*500.0)/1024;                //Raw value converted into RPM using formula
    12.     itoa(adc_rpm,convolt);                        //Convert float value to string
    13.     lcdcomm(0xD1);                                //Display RPM value on LCD
    14.     lcdstr(convolt);
    15.    [B] Delay10KTCYx(1000);                            //Delay[/B]
    16. }
    17.  
    The while(BusyADC()); delay may be the longest but there is a sneaky delay in there:

    adc_rpm=(adc_out*500.0)/1024

    I see no need to use floating point numbers where ints will work. Floats add no accuracy but do ass great time and code size.
     
    harsha3842 likes this.
Loading...