I have a QR code scanner that uses wiegand protocol, have used this code for it, it worked fine for physical pins, but now I have another board onto the Pi, an extender board that uses i2c protocol, and I am trying to make it work with it. The board I got uses this library

For reading, it works like below, it uses the BUS address, 0x20, and the pin, let's say 12, and it reads the value.

def main():
    Main program function
    iobus1 = IOPi(0x20)

    # We will read the inputs 1 to 16 from the I/O bus so set Port 0 and
    # Port 1 as inputs and enable the internal pullup resistors
    iobus1.set_port_direction(0, 0xFF)
    iobus1.set_port_pullups(0, 0xFF)

    iobus1.set_port_direction(1, 0xFF)
    iobus1.set_port_pullups(1, 0xFF)


And this is the code I used for reading from the GPIO pins, it uses 2 pins, DATA 0 and DATA 1, in the code being gpio_0 and gpio_1, these are the pins I need to replace with the i2c pins that use the BUS.

import pigpio

class decoder:

   def __init__(self, pi, gpio_0, gpio_1, callback, relay, bit_timeout=5):

      self.pi = pi
      self.relay = relay
      self.gpio_0 = gpio_0
      self.gpio_1 = gpio_1

      self.callback = callback

      self.bit_timeout = bit_timeout

      self.in_code = False

      self.pi.set_mode(gpio_0, pigpio.INPUT)
      self.pi.set_mode(gpio_1, pigpio.INPUT)

      self.pi.set_pull_up_down(gpio_0, pigpio.PUD_UP)
      self.pi.set_pull_up_down(gpio_1, pigpio.PUD_UP)

      self.cb_0 = self.pi.callback(gpio_0, pigpio.FALLING_EDGE, self._cb)
      self.cb_1 = self.pi.callback(gpio_1, pigpio.FALLING_EDGE, self._cb)

   def _cb(self, gpio, level, tick):

      if level < pigpio.TIMEOUT:

         if self.in_code == False:
            self.bits = 1
            self.num = 0

            self.in_code = True
            self.code_timeout = 0
            self.pi.set_watchdog(self.gpio_0, self.bit_timeout)
            self.pi.set_watchdog(self.gpio_1, self.bit_timeout)
            self.bits += 1
            self.num = self.num << 1
         if gpio == self.gpio_0:
            self.code_timeout = self.code_timeout & 2 # clear gpio 0 timeout
            self.code_timeout = self.code_timeout & 1 # clear gpio 1 timeout
            self.num = self.num | 1


         if self.in_code:

            if gpio == self.gpio_0:
               self.code_timeout = self.code_timeout | 1 # timeout gpio 0
               self.code_timeout = self.code_timeout | 2 # timeout gpio 1

            if self.code_timeout == 3: # both gpios timed out
               self.pi.set_watchdog(self.gpio_0, 0)
               self.pi.set_watchdog(self.gpio_1, 0)
               self.in_code = False
               self.callback(self.bits, self.num, self.relay)

Could I get some help on how to adapt it? I mostly worked with PHP and this is a bit over my head.

1 Answer 1


As I understand it, you have connected the Wiegand reader to the I2C io board.

I don't think this is possible. The timing of the wiegand protocol is quite strict and the I2C transaction to the IO expander will take longer than the bits on the wiegand protocol.

The original code uses callbacks to ensure that the short pulses from the Wiegand protocol are not missed, but for the IO board this is not possible since you only have one interrupt line and you need to access the I2C bus to determine which IO pin is low. By that time it is too late.

You can choose to connect the Wiegand sensor directly to spare IO pins of the Pi, or find a specialized Wiegand to I2C or serial converter.

  • I see, have looked at this board: rfideas-shop.com/en/… Any idea if is it possible to connect more than one QR scanner to it? Or we need one for each Wiegand device? Have searched the internet for Wiegand to I2C or serial converter and I could find only a few to none of these boards.
    – Martzy
    Commented Aug 1, 2023 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.