response to membrane switch is uneven

Thread Starter

harsha3842

Joined Jul 5, 2013
24
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
Rich (BB code):
  if(WH_UL==0 || SPH_UL==0)                //Check WH & SPH unlock status
        {
            reg=6;                                //Switch status
        }
this is when the switch has to be detected for the error msg
}
else
if(SPON==1) //Spindle OFF status
{
reg=1; //Switch status
Rich (BB code):
   if(SP_ON==0)                            //Check spindle ON status
        {
            reg=2+swt;                            //Switch status
        }
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?
 

ErnieM

Joined Apr 24, 2011
8,377
below is the code:
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.
 

Thread Starter

harsha3842

Joined Jul 5, 2013
24
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
Rich (BB code):
#define    lcdport LATB            //LCD Data PORT assignment
#define    E LATDbits.LATD7        //LCD Enable bit
#define    RS LATDbits.LATD6        //LCD Register select bit
#define    WHL PORTCbits.RC0        //Work Head Lock LED signal
#define    WHUL PORTCbits.RC1        //Work Head UnLock LED signal
#define    SPHL PORTCbits.RC2        //Sphere Lock LED signal
#define    SPHUL PORTCbits.RC3        //Sphere UnLock LED signal
#define    SP_ON PORTCbits.RC4        //Spindle ON Switch signal
#define    WH_UL PORTCbits.RC5        //Work Head UnLock Switch signal
#define    SPH_UL PORTCbits.RC6    //Sphere UnLock Switch signal
#define    SPON PORTDbits.RD0        //Spindle ON LED signal
#define    PBAR PORTDbits.RD1        //Pressure Indication signal
#define    SPJ PORTDbits.RD2        //Spindle JOG LED signal
#define    SPL PORTDbits.RD3        //Spindle LOCK LED signal
#define    BUZZ LATDbits.LATD4        //Buzzer for pressure indication
other functions used
Rich (BB code):
void lcdbuild(unsigned char,unsigned char *);    //Function to customize LCD characters
void lcdmsg(const rom char *);                    //Function to display message
void lcdstr(unsigned char *);                    //Function to display string
void lcdcomm(unsigned char);                    //Function for LCD command
void lcddata(unsigned char);                    //Function for LCD data
void lcdout(unsigned char);                        //Function to give LCD output
void dispchar(void);                            //Function for creating multiple customized characters
void animate(void);                                //Function for logo animation
void animate1(void);                            //Function for logo animation
void animate2(void);                            //Function for logo animation
void animate3(void);                            //Function for logo animation
void animate4(void);                            //Function for logo animation
void lcdinit(void);                                //Function to initialize LCD
void buzz(void);                                //Function for Buzzer pattern
void clear(void);                                //Function to clear screen(2nd,3rd & 4th rows only)
void loop(void);                                //Function for all operations which to be repeated
void adc(void);                                    //Function for analog to digital conversion
void ERROR_MSG(void);
switch checking code
Rich (BB code):
    if(!SP_ON || !WH_UL || !SPH_UL)                //Check ERROR status
        {
            while(swt==1)
            {
                reg=reg1+reg2;
                ERROR_MSG();
                break;
            }
            while(swt==2)
            {
                reg=4;
                ERROR_MSG();
                break;
            }
        }
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.
 

Thread Starter

harsha3842

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

sample debounce code
Rich (BB code):
unsigned char is_sw1_pressed(void) 
{
     if (PORTBbits.RB3==0)        // is SW1 pressed?
     {                            //yes
         delay_ms(10);            // wait 10mS for debounce.
         if (LATBbits.LATB3==0)    // is SW1 still has pressed status after 10mS delay?
         {                        // yes, we have key press
             return 1;
         }
     }
     return 0;// if key is not pressed,
 return 0
 }
 

ErnieM

Joined Apr 24, 2011
8,377
does using a debounce code speed up the process or slow it down?
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.
 

Thread Starter

harsha3842

Joined Jul 5, 2013
24
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?????
 

ErnieM

Joined Apr 24, 2011
8,377
how to run adc() and the condition check sequence parallelly?????
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."
 

Thread Starter

harsha3842

Joined Jul 5, 2013
24
adc() function is built in for mplab ide c18
Rich (BB code):
#include <adc.h>                //ADC Files
unsigned int adc_out=0;                //Initializations
float adc_rpm=0;
  
 void main(void)
     OpenADC(ADC_FOSC_32 &                        //ADC module initialization parameters
            ADC_RIGHT_JUST &
            ADC_4_TAD,ADC_CH0 &
            ADC_INT_OFF &
            ADC_VREFPLUS_VDD &
            ADC_VREFMINUS_VSS,7);
     adc();
     CloseADC();  
 }
  
 void adc(void)                                    //Function for analog to digital conversion
{
    SetChanADC (ADC_CH0);                        //Select ADC channel to be used
    Delay10KTCYx(10);
    lcdcomm(0xD1);                                //Clear field to display value
    lcdmsg("   ");
    ConvertADC();                                //Convert analog value to digital
    while(BusyADC());                            //ADC busy status
    adc_out=ReadADC();                            //ADC raw output collected in a register
    adc_rpm=(adc_out*500.0)/1024;                //Raw value converted into RPM using formula
    itoa(adc_rpm,convolt);                        //Convert float value to string
    lcdcomm(0xD1);                                //Display RPM value on LCD
    lcdstr(convolt);
    Delay10KTCYx(1000);                            //Delay
}
is the flow of adc function
 

ErnieM

Joined Apr 24, 2011
8,377
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:

Rich (BB code):
 void adc(void)                                    //Function for analog to digital conversion
{
    SetChanADC (ADC_CH0);                        //Select ADC channel to be used
    Delay10KTCYx(10);
    lcdcomm(0xD1);                                //Clear field to display value
    lcdmsg("   ");
    ConvertADC();                                //Convert analog value to digital
    while(BusyADC());                            //ADC busy status
    adc_out=ReadADC();                            //ADC raw output collected in a register
    adc_rpm=(adc_out*500.0)/1024;                //Raw value converted into RPM using formula
    itoa(adc_rpm,convolt);                        //Convert float value to string
    lcdcomm(0xD1);                                //Display RPM value on LCD
    lcdstr(convolt);
    Delay10KTCYx(1000);                            //Delay
}
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.
 
Top