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

Need help with a simple logic switch...

Discussion in 'Microcontrollers' started by EvilGenius, Aug 13, 2017.

  1. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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.
     

    Attached Files:

  2. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,060
    Likes:
    520
    Location:
    Cleveland, OH, USA
    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
     
  3. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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
     
  4. dave

    Dave New Member

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


     
  5. BobW

    BobW Active Member

    Joined:
    Apr 28, 2010
    Messages:
    521
    Likes:
    54
    Location:
    Canada

    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.
     
  6. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    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.
     
  7. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    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 (text):

    ;******************************************************************
    ;
    ; /*
    ;  *  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: Aug 13, 2017
  8. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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?
     
  9. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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.
     
  10. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    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?
     
  11. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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
     
  12. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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: Aug 13, 2017
  13. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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?
     

    Attached Files:

  14. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    That will work but not without pullups. Either the internal ones or something like 50k resistors across the LEDs.

    Mike.
     
  15. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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: Aug 13, 2017
  16. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    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: Aug 13, 2017
  17. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    10,161
    Likes:
    340
    Location:
    Brisbane Australia
    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.
     
  18. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    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?
     
  19. jpanhalt

    jpanhalt Well-Known Member Most Helpful Member

    Joined:
    Jun 21, 2006
    Messages:
    6,060
    Likes:
    520
    Location:
    Cleveland, OH, USA
    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
     
  20. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,642
    Likes:
    109
    Location:
    Michigan, USA
    Cool... I just hooked up to RA2 and it's working. Here's the 12F1822 test code;

    Code (text):

    ;******************************************************************
    ;                                                                 *
    ;   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: Aug 15, 2017
  21. EvilGenius

    EvilGenius Member

    Joined:
    Jan 8, 2008
    Messages:
    323
    Likes:
    6
    Location:
    Florida
    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?
     

Share This Page