Shop OBEX P1 Docs P2 Docs Learn Events
Best way to check multiple pins. HIGH OR LOW? 0 OR 1? — Parallax Forums

Best way to check multiple pins. HIGH OR LOW? 0 OR 1?

Hello! for the BS2. What's the fastest way to check the status of multiple pins? Example: I need to know if PIN 1 to PIN 14 are HIGH or LOW and output a string like: 10010001000100
Where 0 is Low and 1 is HIGH. I need to SEROUT that info to TX (I'm using pin 15 to send data).

Thanks in advance!

Comments

  • JonnyMacJonnyMac Posts: 8,974
    edited 2023-07-29 19:42

    If you really want to send a string of 15 bytes (versus 2 of data), maybe something like this:

      pinStates = INS
      FOR x = 14 TO 0 STEP -1
        outByte = pinStates.BIT14 + "0"             ' get msb from bit14
        pinStates = pinStates << 1                  ' prep for next bit
        SEROUT TX, Baud, [outByte]                  ' send it
      NEXT
    

    Edit: Fixed a copy/paste error -- I shouldn't suggest code at 2 in the morning....

  • Hi JonnyMac!
    I get a bunch of error, how should I declare all de variables? pinstate? outBite? is BIT a varable to? I get an error: "variable modifier is out of range"

    @JonnyMac said:
    If you really want to send a string of 15 bytes (versus 2 of data), maybe something like this:

      pinStates = INS
      FOR x = 14 TO 0 STEP -1
        outByte = pinStates.BIT14 + "0"             ' get msb from bit14
        pinStates = pinStates << 1                  ' prep for next bit
        SEROUT TX, Baud, [outByte]                  ' send it
      NEXT
    

    Edit: Fixed a copy/paste error -- I shouldn't suggest code at 2 in the morning....

  • JonnyMacJonnyMac Posts: 8,974
    edited 2023-07-30 03:21

    I get a bunch of error...

    It's not a whole program -- it's just an example of what you asked for. Of course, you have to declare the variables used. Logically, pinStates is a Word because it needs 15 bits; x and outByte can be bytes. I have 0 as the ending pin for the loop. That should be 1.

  • Like this?
    pinStates VAR Word
    x VAR Byte
    outByte VAR Byte

    pinStates = INS
    FOR x = 14 TO 1 STEP -1
    outByte = pinStates.BIT14 + "0" ' get msb from bit14
    pinStates = pinStates << 1 ' prep for next bit
    SEROUT TX, Baud, [outByte] ' send it
    NEXT

    How about if I want to Debug for testing purposes? if I use:
    DEBUG outByte istead of SEROUT all I get is 1.

    Thanks for your help!

    @JonnyMac said:

    I get a bunch of error...

    It's not a whole program -- it's just an example of what you asked for. Of course, you have to declare the variables used. Logically, pinStates is a Word because it needs 15 bits; x and outByte can be bytes. I have 0 as the ending pin for the loop. That should be 1.

  • My mistake (which you should have caught) -- remove STEP -1 from the FOR-NEXT loop. In the BS2, the direction of step is automatic.

  • @JonnyMac said:
    My mistake (which you should have caught) -- remove STEP -1 from the FOR-NEXT loop. In the BS2, the direction of step is automatic.

    I noticed. I was testing you :) . JK thanks JhonnyMac. I'm creating a protocol to send the state of all pins (button press). Example: DATA011100001111.
    Some how only send the info if there is a change. Maybe I will save into a variable to compare before sending. The receiver will check each character to determine if the buttons are pressed or not.

  • Sending a packet from one XBee to another is easy. I think you said your project involves several senders and one receiver. For this reason alone I would suggest you:
    -- change XBee baud to 38400 since the BS2 can handle it (4x the speed of 9600)
    -- use a two-byte packet
    -- use hardware flow-control on RX end (will cost you a pin in the BS2)

    I've been through this. I work for a laser-tag company that can have up to 400 units operating at once. Of course, not all are transmitting at the same time, but traffic can be quite busy. I have the advantage of using the Propeller which can buffer packets in software -- the BS2 cannot. By using HW flow control the XBee can do the buffering, especially if the packets are very small.

    While I wouldn't use a BS2 for this project, if I was forced to try, this is what I'd do on the receiver end.

      SERIN RX\FC, BAUD, [WAIT("ROW"), row, seats.HIGHBYTE, seats.LOWBYTE] 
    

    FC is the flow-control pin (connects to XBee CTS [through resistor or voltage divider]), row _is Byte for the row number (ID of the device), and _seats is a Word that contains the active seat bits.

  • Thanks for the advice, cleaver!
    Unfortunately I already have all PCB board and I don’t want to change the layout.
    For now what I need to figure out is how the BS2 can avoid sending data is there are not changes on the pins. I was thinking to store all ceros and ones into one variable so I can compare with a second variable but I could not figure out yet how. Or other method to check if the pins still the same way checked as the last data sent.
    Example:
    If was 1000100001 and after checking again is 000001100 then send data again. Otherwise don’t send anything to avoid traffic.
    The problem is I can find a formula to do that or store all ceros and ones together in a variable so I can compare:
    If data1 = data2 Then senddata
    Any ideas?

    @JonnyMac said:
    Sending a packet from one XBee to another is easy. I think you said your project involves several senders and one receiver. For this reason alone I would suggest you:
    -- change XBee baud to 38400 since the BS2 can handle it (4x the speed of 9600)
    -- use a two-byte packet
    -- use hardware flow-control on RX end (will cost you a pin in the BS2)

    I've been through this. I work for a laser-tag company that can have up to 400 units operating at once. Of course, not all are transmitting at the same time, but traffic can be quite busy. I have the advantage of using the Propeller which can buffer packets in software -- the BS2 cannot. By using HW flow control the XBee can do the buffering, especially if the packets are very small.

    While I wouldn't use a BS2 for this project, if I was forced to try, this is what I'd do on the receiver end.

      SERIN RX\FC, BAUD, [WAIT("ROW"), row, seats.HIGHBYTE, seats.LOWBYTE] 
    

    FC is the flow-control pin (connects to XBee CTS [through resistor or voltage divider]), row _is Byte for the row number (ID of the device), and _seats is a Word that contains the active seat bits.

  • If you were serious about BS2 program (grin), you'd download a PDF copy of my book, StampWorks from Parallax (written before I changed my name). Inside you'll find a section on looking for specific state changes in bits, so you could look for changes 0-to-1 changes to initiate a reporting event.

    Here's how you do it:

      nBtns = INS * $7FFE                           ' scan P14..P1
      xBtns = oBtns ^ nBtns & nBtns                 ' detect 0->1 changes
      oBtns = nBtns                                 ' save for next scan
    

    The variable called xBtns has a 1 in every bit that changed between this scan and the previous.

  • Luis_PLuis_P Posts: 246
    edited 2023-07-31 21:41

    I download the book you wrote. Excellent. Works but I have question, I have to send the pins info like this (pin0, button pressed):
    SEROUT Tx, Baud, ["PYC1A",?IN0,?IN1,?IN2,?IN3,?IN4,?IN5,?IN6,?IN7,?IN8,?IN9,?IN10,?IN11,?IN12]
    Xbee receives:
    PYC1AIN0 = 1
    IN1 = 0
    IN2 = 0
    IN3 = 0
    IN4 = 0
    IN5 = 0
    IN6 = 0
    IN7 = 0
    IN8 = 0
    IN9 = 0ÿýÿ <== RF Noise, how to get rid of garbage?
    IN10 = 0
    IN11 = 0
    IN12 = 0
    Because if I send it like this:
    SEROUT Tx, Baud, ["PYC1A",IBIN13 btns]
    Xbee shows pin 1,2 and 3 are pressed. Only Pin1 is pressed, this is what I get:
    PYC1A0000000001110.
    Maybe my code is checking the wrong pins? I'm using IN0 thru IN12
    my code :
    ' -----[ I/O Definitions ]-------------------------------------------------
    BtnBus VAR INA ' four inputs, pins 0 - 12

    'scan all pins
    btns = %1111111111111 ' enable 13 four inputs
    FOR idx = 1 TO 14
    btns = btns & ~BtnBus ' test inputs
    PAUSE 5 ' delay between tests
    NEXT
    input1 = btns

    @JonnyMac said:
    If you were serious about BS2 program (grin), you'd download a PDF copy of my book, StampWorks from Parallax (written before I changed my name). Inside you'll find a section on looking for specific state changes in bits, so you could look for changes 0-to-1 changes to initiate a reporting event.

    Here's how you do it:

      nBtns = INS * $7FFE                           ' scan P14..P1
      xBtns = oBtns ^ nBtns & nBtns                 ' detect 0->1 changes
      oBtns = nBtns                                 ' save for next scan
    

    The variable called xBtns has a 1 in every bit that changed between this scan and the previous.

  • JonnyMacJonnyMac Posts: 8,974
    edited 2023-08-01 00:55

    I have been away from the BS2 for so long that I forgot about the BIN output formatter. If you're dead set on sending the state of you inputs as a string, use that as it will take less code -- but it creates a problem on the other side. The other side now has a instead of digital values so you convert that back which will take a bunch of code. Why bother?

    Scan inputs 0..12 like this

    Scan_Buttons:
      btns = $1FFF                                  ' enable pins 12..0
      FOR x = 1 TO 5                                ' debounce for 25ms
        PAUSE 5
        btns = btns & INS                           ' update active inputs
      NEXT
      RETURN
    

    Note that I made it a subroutine. It's easier in the beginning to do things in a very modular fashion.

    Now you can send the inputs from the slave to the master:

      SEROUT TX, BAUD, ["ID:", DEV_ID, btns.LOWBYTE, btns.HIGHBYTE]
    

    ...where DEV_ID is the unit number (a constant between 0 and 255) programmed into the BS2. Now you're sending a lot less information -- less likely to have an issue.

    On the other side you only have to receive 3 bytes after the WAIT condition is satisfied:

      SERIN RX, BAUD, [WAIT("ID:"), devID, pins.LOWBYTE, pins.HIGHBYTE]
    

    You can look at the data coming in with

    DEBUG "ID = ", DEC devID, "  BTNS = ", IBIN btns
    

    I've said before, you might get this working with one remote and the master, but I have serious doubts it's going to be reliable at all with multiple remotes and no way for you to throttle the serial data coming into the master; I suspect traffic is going to be missed and could get out of alignment. This is why I suggest using the WAIT modifier of SERIN. You may miss packets, but that should keep the ones you get in sync.

  • I found way using IBIN btns. I have a question regarding the Xbee incoming Data ( I may open another discussion). Is there any way to avoid all these garbage unwanted data on the Xbee settings? (see picture) or this is normal and cannot be avoided? remember my Xbee coordinator does not have any Bs2 connected. Only the Device End has a BS2 to Serout IBIN btns.

    @JonnyMac said:
    I have been away from the BS2 for so long that I forgot about the BIN output formatter. If you're dead set on sending the state of you inputs as a string, use that as it will take less code -- but it creates a problem on the other side. The other side now has a instead of digital values so you convert that back which will take a bunch of code. Why bother?

    Scan inputs 0..12 like this

    Scan_Buttons:
      btns = $1FFF                                  ' enable pins 12..0
      FOR x = 1 TO 5                                ' debounce for 25ms
        PAUSE 5
        btns = btns & INS                           ' update active inputs
      NEXT
      RETURN
    

    Note that I made it a subroutine. It's easier in the beginning to do things in a very modular fashion.

    Now you can send the inputs from the slave to the master:

      SEROUT TX, BAUD, ["ID:", DEV_ID, btns.LOWBYTE, btns.HIGHBYTE]
    

    ...where DEV_ID is the unit number (a constant between 0 and 255) programmed into the BS2. Now you're sending a lot less information -- less likely to have an issue.

    On the other side you only have to receive 3 bytes after the WAIT condition is satisfied:

      SERIN RX, BAUD, [WAIT("ID:"), devID, pins.LOWBYTE, pins.HIGHBYTE]
    

    You can look at the data coming in with

    DEBUG "ID = ", DEC devID, "  BTNS = ", IBIN btns
    
                                       
    

    I've said before, you might get this working with one remote and the master, but I have serious doubts it's going to be reliable at all with multiple remotes and no way for you to throttle the serial data coming into the master; I suspect traffic is going to be missed and could get out of alignment. This is why I suggest using the WAIT modifier of SERIN. You may miss packets, but that should keep the ones you get in sync.

Sign In or Register to comment.