Continue to Site

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.

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

Need help with a simple logic switch...

Status
Not open for further replies.

EvilGenius

Member
Hello
I am working on a PIC based board and having logic issues reading switches.
uController: PIC16F628A
Language:Assembly
I am utilizing all the inputs/outputs of this chip.
PortA: 1, 2, 3 are setup as inputs
SWS: is a 3 position SW, displayed here as 3 separate switches. Only one switch can be ON at one time, Common anode.
Function: If Sw is in position 1, LED1 is turned on, and PortA,1 is set high. When PIC reads the logic of all 3 SW's, sees this as logic "1" on PortA,1 and does something. Same true for other SW positions..... PortA,2 and 3...
When SW is closed, PIC sees logic 1. No problem. When SW is open, PIC still sees LED Diode voltage. (not logic "0")
This is enough voltage to keep port status high and fail logic zero test. Any suggestions to overcome this issue?
Thanks in advance for your suggestions.
 

Attachments

  • INPUT_3SWS.jpg
    INPUT_3SWS.jpg
    46.6 KB · Views: 203
I believe that Port A is all Schmitt Trigger. The microchip switching levels are 0.2 and 0.8 x VDD .

Have you considered putting a relatively high value resistor (10 k to 50 k) in parallel with the diode or diode/resistor. That will ensure a positive pull-down without the diode drop without greatly affecting the on current available..


John
 
I believe that Port A is all Schmitt Trigger. The microchip switching levels are 0.2 and 0.8 x VDD .

Have you considered putting a relatively high value resistor (10 k to 50 k) in parallel with the diode or diode/resistor. That will ensure a positive pull-down without the diode drop without greatly affecting the on current available..
John

Hi John
I did consider that. If I have to, then will do. I am keeping the PCB real estate tight. But can manage 3 resistors in there somewhere.
I was hoping there is an internal feature of uC that when a pin is set as an input an internal pull-down resistor can be activated. Not sure if that is the case!
I also thought about setting the pins to zero (BCF PORTA,1 for example) before reading status of the SW. But it seems that it does not make any difference.

Regards,
Rom
 
How about low side switching? Connect the LED's from Vcc to the switch and the switch to ground. You'd have to invert the logic in the PIC.
 
If you use port B and invert the logic then you can use the internal weak pullups of the chip. Some of the newer pin compatible pics have WPUs on port A too.

Mike.
 
What does your code look like, ROM? I've done something similar before but I was using active low push button switches and active high LEDs (to emulate lighted toggle switches). I believe I used something like the code below;

Cheerful regards, Mike

Code:
;******************************************************************
;
; /*
;  *  Lighted Push Button Switches (emulated toggle switches)
;  *
;  *  swnew  ____---____-----___   sample active lo switches
;  *  swold  _____---____-----__   switch state latch
;  *  swnew  ____-__-___-____-__   changes, press or release
;  *  swnew  ____-______-_______   filter out 'release' bits
;  *  flags  _____-------_____--   toggle flag bits for main
;  *  trisa  -----_______-----__   toggle tris bits for LEDs
;  */
;
;  while(1)
;  { delay_ms(25);              // sample at 25-ms intervals
;    trisa |= 0b00000111;       // set RA2-RA0 pins to input
;    swnew = ~porta;            // sample active lo switches
;    swnew &= 0b00000111;       // only RA2-RA0 switch pins
;    swnew ^= swold;            // changes, press or release
;    swold ^= swnew;            // update switch state latch
;    swnew &= swold;            // filter out 'release' bits
;    flags ^= swnew;            // toggle flag bits for main
;    porta &= 0b11111000;       // set output latches to '0'
;    trisa ^= flags;            // light only active sw LEDs
;
;    if(swnew)                  // on any "new press"
;      beep();                  // task a "new press" beep
;
;    if(swnew.0)                // if sw RA0 'new press'
;    {                          //
;    }                          //
;    if(swnew.1)                // if sw RA1 'new press'
;    {                          //
;    }                          //
;    if(swnew.2)                // if sw RA2 'new press'
;    {                          //
;    }                          //
;  }
;
loop
        DelayCy(25*msecs)       ; sample at 25 msec intervals     |B0
        movlw   TRISA           ;                                 |B0
        movwf   FSR             ; FSR = &TRISA                    |B0
        movlw   0x07            ; wreg = 1<<RA2|1<<RA1|1<<RA0     |B0
        iorwf   INDF,F          ; TRISA |= 0x07 (RA0-RA2 inputs)  |B0
        comf    PORTA,W         ; sample active lo switches       |B0
        andlw   0x07            ; on the RA2..RA0 pins only       |B0
        xorwf   swold,W         ; changes, press or release       |B0
        xorwf   swold,F         ; update switch state latch       |B0
        andwf   swold,W         ; filter out 'release' bits       |B0
        movwf   swnew           ; save 'new press' bits           |B0
        xorwf   flags,F         ; toggle flag bits for main       |B0
        movlw   b'11111000'     ; mask off RA0-RA2 bits           |B0
        andwf   PORTA,F         ; keep switch latch bits '0'      |B0
        movf    flags,W         ; trisa ^= flags                  |B0
        xorwf   INDF,F          ; light only active LEDs          |B0
;       movf    swnew,W         ; any 'new press' bits?           |B0
;       skpnz                   ; yes, skip, else                 |B0
        goto    loop            ; loop                            |B0
 
Last edited:
How about low side switching? Connect the LED's from Vcc to the switch and the switch to ground. You'd have to invert the logic in the PIC.
Wow thank you for the responses. I try to answer them one by one. I could do low side switching (not a problem). But does PORTA have pull-up resistors internally? If not, I would have the same problem. How about using the comparator function to force the pin low?
 
If you use port B and invert the logic then you can use the internal weak pullups of the chip. Some of the newer pin compatible pics have WPUs on port A too.

Mike.
Hi Pommie
I need PORTB for my sequencing. If I have to, I can rearrange pins and invert the logic, but rather not if possible.
 
I wonder if the LEDs & current limiting resistor would work as a pull-up?

Also, if only one LED is lighted at a time, couldn't you use a single current limiting resistor?
 
What does your code look like, ROM? I've done something similar before but I was using active low push button switches and active high LEDs (to emulate lighted toggle switches). I believe I used something like the code below;
Cheerful regards, Mike
[/code]
Hello Mike
This is a controller for a standby generator along with the automatic transfer switch.
The main loop code looks like this:
;Begin Define Ports
GenPower Equ PORTB
SWS Equ PORTA
Starter Equ 0
Spark Equ 1
Fuel Equ 2
Boost Equ 3
Rotor Equ 4
DPE Equ 5
Gen Equ 6
ATS Equ 7
;--------------------
Util Equ 0
OSW Equ 1
MSW Equ 2
ASW Equ 3
E2T Equ 6
N2T Equ 7
;End Define Ports

org 0x000

movlw 0x07 ;Disable comparators
movwf CMCON
bank1
movlw b'00111111' ;Set A6 & A7 as Outputs, the rest inputs
movwf TRISA
clrf TRISB ;Set B0-B7 as Outputs
bank0
clrf PORTA ;Initialize Ports
clrf PORTB
;
;--------------------------------------------------------------------
; Main Loop |
;--------------------------------------------------------------------
Loop ;Infinite Loop for Testing SW Position :OFF, MANU, AUTO
BTFSC PORTA,OSW
call Off_Mode
BTFSC PORTA,MSW
call Man_Mode
BTFSC PORTA,ASW
call Auto_Mode
goto Loop
 
I wonder if the LEDs & current limiting resistor would work as a pull-up?

Also, if only one LED is lighted at a time, couldn't you use a single current limiting resistor?
I could since all use a 1k series resistor.

Edit: Not sure where the placement of single resistor is the best. If I put it after +5v and before switches, it might interfere with the logic reading. I could place it after common cathode of the LED's and before ground.
Edit2: If I use a single resistor on top as a pull-up, I still will have an issue with logic zero when switch is off. LED is not pulling down!
 
Last edited:
I think this is what you fine gentlemen are suggesting. We call this version Common Anode. Vs. Previous version being common cathode. Would this work?
 

Attachments

  • Input_3SWS_CA.jpg
    Input_3SWS_CA.jpg
    43.3 KB · Views: 201
That will work but not without pullups. Either the internal ones or something like 50k resistors across the LEDs.

Mike.
 
That will work but not without pullups. Either the internal ones or something like 50k resistors across the LEDs.

Mike.
So you don't think LED and resistor will provide logic "1" with all switches open?

Edit: I m thinking when pic pin is used as an input, it sees a high impedance (100k-1M). So the voltage divider (diode plus resistor being Rx) and internal high impedance Ry. PIC pin would sense 5 x Ry/(Rx+Ry) =~ 5 x (100k/105k)= 4.7 volts?!
 
Last edited:
Rom. Your "common anode" diagram is correct.

Gentlemen, I just tested some code on a little 8-pin 12F1822 and it's working fine without internal or external pull-ups. I should probably check to see what type of inputs on the 12F1822.
 
Last edited:
I'm assuming (dangerous, I know) that the leakage on the pin is able to cause a forward voltage drop on the LED that is higher than 1V and so the pin doesn't reach the 4V required for a schmitt input.

Mike.
 
Ah... I think you're right. I measure 3.8v on RA0 with the switch and LED off. That's plenty for the high level on the 12F1822 'TTL' input but not quite high enough for a Schmidt Trigger input to register as a high level.

Is there a chance my multi-meter is introducing additional current and an additional voltage drop at the RA0 input? Perhaps I should try this code on a device with ST inputs like Rom's 16F628A?
 
High Mike (K8LH),

RA2 is ST on that chip. Since you are already set-up, maybe just switch pins to see if that is the problem.

John
 
Cool... I just hooked up to RA2 and it's working. Here's the 12F1822 test code;

Code:
;******************************************************************
;                                                                 *
;   Filename: 12F1822_Test.asm                                    *
;     Author: Mike McLaren, K8LH                                  *
;       Date: 13-Aug-2017                                         *
;                                                                 *
;   12F1822 experiment                                            *
;                                                                 *
;                                                                 *
;      MPLab: 8.92    (tabs=8)                                    *
;      MPAsm: 5.51                                                *
;                                                                 *
;******************************************************************

        include "P12F1822.INC"
        errorlevel -302
        list st=off
        radix dec

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _IESO_OFF & _FCMEN_OFF
  __CONFIG _CONFIG2, _BORV_19 & _LVP_OFF & _PLLEN_OFF
;
; _MCLRE_ON     default
; _PWRTE_OFF    default
; _CP_OFF       default
; _CPD_OFF      default
; _BOREN_ON     default
; _CLKOUTEN_OFF default
;
; _WRT_OFF      default
; _STVREN_ON    default
;

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  variables                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        cblock  0x20            ; 0x20..0x6F, bank 0
swold                           ;
swnew                           ;
flags                           ;
delayhi                         ; DelayCy() function variable
        endc

        cblock  0x70            ; 0x70..0x7F common all banks

        endc

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  constants                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem macro generates four instructions     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        radix dec
clock   equ     16              ; 4, 8, 12, 16, 20 (MHz), etc.
usecs   equ     clock/4         ; cycles/microsecond multiplier
msecs   equ     usecs*1000      ; cycles/millisecond multiplier
dloop   equ     5               ; loop size, 5 to 8 cycles
;
;  -- loop --  -- delay range --  -- memory overhead ----------
;  5-cyc loop, 11..327690 cycles,  9 words (+4 each macro call)
;  6-cyc loop, 11..393226 cycles, 10 words (+4 each macro call)
;  7-cyc loop, 11..458762 cycles, 11 words (+4 each macro call)
;  8-cyc loop, 11..524298 cycles, 12 words (+4 each macro call)
;
DelayCy macro   cycles          ; range, see above
    if (cycles<11)|(cycles>(dloop*65536+10))
        error " DelayCy range error "
    else
        movlw   high((cycles-11)/dloop)+1
        movwf   delayhi
        movlw   low ((cycles-11)/dloop)
        call    uLoop-((cycles-11)%dloop)
    endif
        endm

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  reset vector                                                   ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x0000
v_reset
        goto    setup           ;

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  interrupt vector                                               ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x004

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main setup                                                     ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

setup
        banksel ANSELA          ; bank 3                          |03
        clrf    ANSELA          ; set digital I/O                 |03
        banksel TRISA           ; bank 01                         |01
        movlw   b'00000111'     ;                                 |01
        movwf   TRISA           ;                                 |01
;
;  setup INTOSC
;
        banksel OSCCON          ; bank 1                          |01
        movlw   b'01111010'     ;                                 |01
        movwf   OSCCON          ; setup 16-MHz INTOSC             |01
waitfs  btfss   OSCSTAT,HFIOFS  ; stable? yes, skip, else         |01
        bra     waitfs          ; branch and wait                 |01

        banksel PORTA           ; bank 0                          |00
        clrf    swold           ;                                 |00
        clrf    flags           ;                                 |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  main loop                                                      ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; /*
;  *  Lighted Push Button Switches (emulated toggle switches)
;  *
;  *  swnew  ____---____-----___   sample active lo switches
;  *  swold  _____---____-----__   switch state latch
;  *  swnew  ____-__-___-____-__   changes, press or release
;  *  swnew  ____-______-_______   filter out 'release' bits
;  *  flags  _____-------_______   toggle flag bits for main
;  *  trisa  -----_______-------   toggle tris bits for LEDs
;  */
;
;  while(1)
;  { delay_ms(25);              // sample at 25-ms intervals
;    trisa |= 0b00000111;       // set RA2-RA0 pins to input
;    swnew = ~porta;            // sample active lo switches
;    swnew &= 0b00000111;       // only RA2-RA0 switch pins
;    swnew ^= swold;            // changes, press or release
;    swold ^= swnew;            // update switch state latch
;    swnew &= swold;            // filter out 'release' bits
;    flags ^= swnew;            // toggle flag bits for main
;    porta &= 0b11111000;       // set output latches to '0'
;    trisa ^= flags;            // light only active sw LEDs
;
;    if(swnew)                  // on any "new press"
;      beep();                  // task a "new press" beep
;
;    if(swnew.0)                // if sw RA0 'new press'
;    {                          //
;    }                          //
;    if(swnew.1)                // if sw RA1 'new press'
;    {                          //
;    }                          //
;    if(swnew.2)                // if sw RA2 'new press'
;    {                          //
;    }                          //
;  }
;

loop
        DelayCy(25*msecs)       ; sample at 25 msec intervals     |00
;
;  K8LH parallel switch state logic and "new press" filter
;
;   wreg  ____---____-----_____   inverted active lo sample
;  swold  _____---____-----____   switch state latch
;   wreg  ____-__-___-____-____   changes, press or release
;   wreg  ____-______-_________   filter out 'release' bits
;  flags  _____-------_________   toggle flag bits for main
;
        banksel TRISA           ; bank 1                          |01
        movlw   b'00000111'     ;                                 |01
        iorwf   TRISA,F         ; set RA2..RA0 pins to inputs     |01
        banksel PORTA           ; bank 0                          |00
        comf    PORTA,W         ; sample active lo switches       |00
        xorwf   swold,W         ; changes, press or release       |00
        xorwf   swold,F         ; update switch state latch       |00
        andwf   swold,W         ; filter out 'release' bits       |00
        movwf   swnew           ; save 'new press' bits           |00
        skpz                    ; new switch? no, skip, else      |00
        movwf   flags           ; update 'on' flags (1 of n)      |00
;       xorwf   flags,F         ; toggle 'on' flags (n of n)      |00
;
;  light LEDs for switches with an 'on' flag
;
        movlw   b'11111000'     ; mask off RA2-RA0 bits           |00
        andwf   PORTA,F         ; set output latches to '0'       |00
        movf    flags,W         ; pickup sw2..sw0 states          |00
        banksel TRISA           ; bank 1                          |01
        xorwf   TRISA,F         ; trisa ^= flags (light LEDs)     |01
        banksel PORTA           ; bank 0                          |00
;
;  check for "new" switch position change
;
        btfsc   swnew,0         ; RA0 on? no, skip, else          |00
        call    off_mode        ;                                 |00

        btfsc   swnew,1         ; RA1 on? no, skip, else          |00
        call    man_mode        ;                                 |00

        btfsc   swnew,2         ; RA2 on? no, skip, else          |00
        call    auto_mode       ;                                 |00

        goto    loop            ;                                 |00

off_mode
man_mode
auto_mode
        return                  ;                                 |00

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  K8LH DelayCy() subsystem 16-bit uDelay subroutine              ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

a = dloop-1
    while a > 0
        nop                     ; (cycles-11)%dloop entry points  |00
a -= 1
    endw
uLoop   addlw   -1              ; subtract 'dloop' loop time      |00
        skpc                    ; borrow? no, skip, else          |00
        decfsz  delayhi,F       ; done?  yes, skip, else          |00
        goto    uLoop-dloop+5   ; do another loop                 |00
        return                  ;                                 |00
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        end
 
Last edited:
Thanks all for your input.
Pommie I am not sure if Vd exceeds 1V on SW-open. I do see your concern though.
If it is more than 1V then I have another problem: The LED would be partially lit (dim but never-the-less ON)
The Red LED does not take much volts and amps to lite up!
I might just bench the common anode with 16F628A and check how the chip does.

Mike: Thank you for the code. Given my switch is not a push switch but rather slide-lock to one position (switch status change is long), could it simplify the code a bit since we are not worried about debounce and time delay sampling switches?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top