HID R10 / R15 Desktop RFID Reader Arduino and Metro Mini code (separate microcontrollers)

I see this all the time in Deviant Ollams videos and i wanted to try my hand at making it.



Parts

Case - https://www.thingiverse.com/thing:6823704
HID R10 Multi-class reader - Find these on Ebay for around 20-50$ used
USB-C Header breakout cable - Amazon.com: 15PCS Type-C Female 2Pin USB Connector Type-C Waterproof with Female Socket Fast Charging Jack Charging Port USB-C Charger Plug Socket : Cell Phones & Accessories
Adafruit Metro Mini (or Arduino Uno) - Amazon.com: HiLetgo 3pcs Nano 3.0 ATmega328P Type-C USB CH340 Controller Board Compatible to Arduino Nano CH340 USB Driver Nano V3.0 ATmega328 : Electronics
Arduino Breakout Board - Amazon.com: Teyleten Robot Nano V3.0 Adapter Expansion Board Module Nano IO Shield Nano IO Expansion Board for Arduino Nano 5pcs : Electronics
I2c 128x64 Oled (Made for Adafruit Stemma Oled) - Amazon.com: Hosyond 5 Pcs 0.96 Inch OLED I2C IIC Display Module 12864 128x64 Pixel SSD1306 Mini Self-Luminous OLED Screen Board Compatible with Arduino Raspberry Pi(Blue and Yellow) : Electronics
5v dc-dc Stepdown module - Amazon.com: ACEIRMC 6pcs High Efficiency Output 5V 5A mini560 Step Down DC-DC Converter Voltage Regulator Buck Stabilized Power Supply Module : Electronics

Secure R10 to top of case with screw and nut
Secure arduino to breakout board and breakout board to bottom case. Secure Stepdown module to bottom case

Connect USB-C Power to Stepdown input, then jumper stepdown output to Arduino at USB in and Ground.

Wire up i2c screen on 5v of arduino and ground as well as the rest of the I2c Pins.

Wire HID R10 to arduino. Secure with screws.

Code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wiegand.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1  // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
WIEGAND wg;

// Define the allowed card number
const uint32_t allowedCardNumber = 12345678;

void setup() {
  delay(500);
  Serial.begin(115200);
 	while (!Serial) delay(10);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);

  // Initialize Wiegand reader
  wg.begin();

  displayData("Ready to Read", "", "", "");
}
//void(* resetFunc) (void) = 0;

void loop() {
  delay(500);
  if (wg.available()) {
    //resetFunc();
    uint32_t cardData = wg.getCode();  // Get Wiegand code
    
    // Try to get bit length, set to 0 if unavailable
    uint8_t bitLength = 24;
    #ifdef wg_getBitCount
      bitLength = wg.getBitCount();
    #endif

    bool pass = validateCard(cardData);  // Validate card
    String cardType = detectCardType(bitLength);  // Determine card type

    displayData(String(cardData), String(bitLength), pass ? "Pass" : "Fail", cardType);

    // Print to Serial Monitor
    Serial.print("Data: ");
    Serial.println(cardData);
    Serial.print("Bit Length: ");
    Serial.println(bitLength);
    Serial.print("Pass/Fail: ");
    Serial.println(pass ? "Pass" : "Fail");
    Serial.print("Card Type: ");
    Serial.println(cardType);
  }
}

// Function to validate card based on specific allowed card number
bool validateCard(uint32_t data) {
  // Check if the card data matches the allowed card number
  return data == allowedCardNumber;
}

// Function to detect card type based on bit length
String detectCardType(uint8_t bitLength) {
  if (bitLength == 26) {
    return "Standard 26-bit";
  } else if (bitLength == 34) {
    return "Corporate 1000";
  } else {
    return "Unknown Type";
  }
}

// Function to display data on OLED screen
void displayData(String data, String bitLength, String passFail, String cardType) {
  delay(50);
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("Wiegand Data:");
  display.setCursor(0, 10);
  display.print("Data: ");
  display.print(data);
  display.setCursor(0, 20);
  display.print("Bit Length: ");
  display.print(bitLength);
  display.setCursor(0, 30);
  display.print("Pass/Fail: ");
  display.print(passFail);
  display.setCursor(0, 40);
  display.print("Card Type: ");
  display.print(cardType);
  display.display();
}

I want to change the code to more reflect how @DeviantOllam does his. With different modes of use (theres a card read mode, and then an access controller mode that makes it function like a door reader. However i want to actually make it a door reader with a mag striker and relay), however i am not THAT great at arduino code. if anyone is please reach out id love to bounce my ideas off of you. I wish his code was opensourced but i dont think he wants to release that IP.

I wanted to get this out to everyone because it really is a cool project and it didnt take too long to spin up. You can turn it wireless by adding a ESPKey to it and then just use a powerbank to power it off of the port.

If there is interest i will do a full write-up and pinout.

R15 to Stepdown Module To Arduino Pinout

HID Reader to Arduino Uno

Black  => Gnd
Green  => D2
White  => D3
Brown  => D5
Orange => D6
Yellow => A3

OLED to Arduino
VCC => 5v
GND => Ground
SCL => A5
SDA => A4

POWER IN TO STEPDOWN
BLACK => - IN
RED   => + IN

STEPDOWN to Arduino
- out  => GND
+ out => VIN

this needed to be seperate than the above, since the above was using an Adafruit Metro with a Stemma connector to OLED.

Current Arduino Code

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wiegand.h>
#include <EEPROM.h>

#define SIGNAL_PIN 13    
#define BEEPER_PIN A3    

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1  
#define SCREEN_ADDRESS 0x3C 

#define MAX_CARDS 20  

#define EEPROM_CARD_COUNT_ADDR 0              // EEPROM address to store the card count
#define EEPROM_CARD_DATA_ADDR  4              // Starting address for card data
#define CARD_SIZE              sizeof(uint32_t) // Size of each card entry (4 bytes for uint32_t)

#define RED_LED_PIN 5     // Define red LED pin
#define GREEN_LED_PIN 6   // Define green LED pin

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
WIEGAND wg;

uint32_t authorizedCards[MAX_CARDS];
uint8_t cardCount = 0;

const uint32_t modeCards[4] = {1001, 1002, 1003, 1004}; 
uint8_t currentMode = 1;

// Function to count total bits in card data
uint8_t countBits(uint32_t data) {
  uint8_t count = 0;
  while (data) {
    data >>= 1;
    count++;
  }
  return count;
}

// Extract facility code (assuming 26-bit format)
uint8_t getFacilityCode(uint32_t data) {
  return (data >> 16) & 0xFF;
}

// Extract card number (assuming 26-bit format)
uint16_t getCardNumber(uint32_t data) {
  return data & 0xFFFF;
}

// Load authorized cards from EEPROM with validation
void loadAuthorizedCardsFromEEPROM() {
  cardCount = EEPROM.read(EEPROM_CARD_COUNT_ADDR);

  // Check if the card count is valid; if not, assume no cards are stored
  if (cardCount > MAX_CARDS) {
    cardCount = 0;  // Reset to 0 if invalid count
    return;         // Skip loading if there are no valid cards
  }

  // Load each card from EEPROM into the authorizedCards array
  for (uint8_t i = 0; i < cardCount; i++) {
    uint32_t cardData = 0;
    for (uint8_t j = 0; j < CARD_SIZE; j++) {
      cardData |= EEPROM.read(EEPROM_CARD_DATA_ADDR + i * CARD_SIZE + j) << (8 * j);
    }
    authorizedCards[i] = cardData;
  }
}
// Save authorized cards to EEPROM
void saveAuthorizedCardsToEEPROM() {
  EEPROM.write(EEPROM_CARD_COUNT_ADDR, cardCount);
  for (uint8_t i = 0; i < cardCount; i++) {
    uint32_t cardData = authorizedCards[i];
    for (uint8_t j = 0; j < CARD_SIZE; j++) {
      EEPROM.write(EEPROM_CARD_DATA_ADDR + i * CARD_SIZE + j, (cardData >> (8 * j)) & 0xFF);
    }
  }
}

void setup() {
  delay(50);
  Serial.begin(9600);

  // Load cards from EEPROM
  loadAuthorizedCardsFromEEPROM();

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS, OLED_RESET)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);  
  }
  display.clearDisplay();
  display.display();  // Ensure display is clear
  display.setTextSize(2);
  display.setTextColor(WHITE);

  wg.begin();

  pinMode(SIGNAL_PIN, OUTPUT);
  digitalWrite(SIGNAL_PIN, LOW);

  pinMode(BEEPER_PIN, OUTPUT);
  digitalWrite(BEEPER_PIN, HIGH);  // Ensure beeper is off initially

  // Set LED pins as output and turn them off initially
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  digitalWrite(RED_LED_PIN, HIGH);   // Turn off red LED initially
  digitalWrite(GREEN_LED_PIN, HIGH); // Turn off green LED initially

  // Display "Read Mode" directly on startup
  display.clearDisplay();
  display.setCursor(13, 0);
  display.print("Read Mode");
  display.display();
}

void loop() {
  if (wg.available()) {
    uint32_t cardData = wg.getCode();  
    uint8_t bitLength = countBits(cardData);  // Manually calculate bit length
    uint8_t facilityCode = getFacilityCode(cardData);  // Get facility code
    uint16_t cardNumber = getCardNumber(cardData);  // Get card number

    // Debugging: Print card data, bit length, and facility code to Serial Monitor
    Serial.print("Card Data: ");
    Serial.println(cardData);
    Serial.print("Bit Length: ");
    Serial.println(bitLength);
    Serial.print("Facility Code: ");
    Serial.println(facilityCode);
    Serial.print("Card Number: ");
    Serial.println(cardNumber);

    // Beep to indicate card read
    beep();

    // Check if the scanned card is a mode-changing card
    for (uint8_t i = 0; i < 4; i++) {
      if (cardData == modeCards[i]) {
        currentMode = i + 1;
        displayMode();
        return;
      }
    }

    // Perform actions based on the current mode
    switch (currentMode) {
      case 1:  // Read Mode
          display.clearDisplay();
          display.setCursor(13, 0);
          display.setTextSize(2);
          display.print("Read Mode");

          display.setTextSize(1);
          display.setCursor(0, 22);
          display.print("Card #: ");
          display.print(cardNumber);  // Show only the card number part

          display.setCursor(0, 32);
          display.print("FC: ");
          display.print(facilityCode);

          display.setCursor(0, 42);
          display.print("Bit Len: ");
          display.print(bitLength);

          display.setCursor(0, 52);
          display.print("Raw Data: ");
          display.print(cardData);

          display.display();
          break;
      case 2:  // Door Mode
        if (isAuthorized(cardData)) {
          digitalWrite(SIGNAL_PIN, LOW);  
          delay(50);                      
          digitalWrite(SIGNAL_PIN, HIGH);   
          displayData("Door Mode", "Authorized", "", "");
        } else {
          displayData("Door Mode", "Denied", "", "");
        }
        break;

      case 3:  // Add Card Mode
        addCard(cardData);
        displayData("Add Card Mode", "Card Added", "Card Data: " + String(cardData), "");
        break;

      case 4:  // Remove Card Mode
        removeCard(cardData);
        displayData("Remove Card Mode", "Card Removed", "Card Data: " + String(cardData), "");
        break;
    }
  }
}

// Function to produce a short beep sound
void beep() {
  digitalWrite(BEEPER_PIN, LOW);  
  delay(50);                     
  digitalWrite(BEEPER_PIN, HIGH);  
}

// Function to display the current mode on the OLED screen and control LEDs
void displayMode() {
  String modeText = "";

  // Set the LED state based on current mode
  if (currentMode == 3) {          // Add Card Mode
    digitalWrite(GREEN_LED_PIN, LOW);  // Turn on green LED
    digitalWrite(RED_LED_PIN, HIGH);   // Turn off red LED
    modeText = "Add Card Mode";
  } else if (currentMode == 4) {   // Remove Card Mode
    digitalWrite(RED_LED_PIN, LOW);   // Turn on red LED
    digitalWrite(GREEN_LED_PIN, HIGH); // Turn off green LED
    modeText = "Remove Card Mode";
  } else {
    // Turn off both LEDs for other modes
    digitalWrite(GREEN_LED_PIN, HIGH); // Turn off green LED
    digitalWrite(RED_LED_PIN, HIGH);   // Turn off red LED

    // Set mode text
    switch (currentMode) {
      case 1: modeText = "Read Mode"; break;
      case 2: modeText = "Door Mode"; break;
    }
  }

  displayData(modeText, "", "", "");
}

// Function to display text lines on the OLED
void displayData(String mode, String line1, String line2, String line3) {
  display.clearDisplay();   // Clear display buffer
  display.setTextSize(2);

  display.setCursor(13, 0);
  display.setTextColor(WHITE);
  display.print(mode);

  display.setTextSize(1);
  display.setCursor(0, 20);
  display.print(line1);
  display.setCursor(0, 30);
  display.print(line2);
  display.setCursor(0, 40);
  display.print(line3);

  display.display();        // Refresh display to show updated content
}

// Function to check if a card is authorized
bool isAuthorized(uint32_t data) {
  for (uint8_t i = 0; i < cardCount; i++) {
    if (authorizedCards[i] == data) {
      return true;
    }
  }
  return false;
}
// Function to add a card to the authorized list
void addCard(uint32_t data) {
  if (cardCount < MAX_CARDS && !isAuthorized(data)) {
    authorizedCards[cardCount] = data;
    cardCount++;
    saveAuthorizedCardsToEEPROM(); // Save changes to EEPROM
  }
}

// Function to remove a card from the authorized list
void removeCard(uint32_t data) {
  for (uint8_t i = 0; i < cardCount; i++) {
    if (authorizedCards[i] == data) {
      for (uint8_t j = i; j < cardCount - 1; j++) {
        authorizedCards[j] = authorizedCards[j + 1];
      }
      cardCount--;
      saveAuthorizedCardsToEEPROM(); // Save changes to EEPROM
      break;
    }
  }
}
8 Likes

What ideas do you have in-mind for the code?

1 Like

I have some basic code from another git that allows you to make the reader operate in different modes.

But I want to adapt it to be how Deviant has his. His I believe functions like this:

One for just basic card reading where it decrypts the wiegand data and displays it by bit length, facility, and ID.

the other mode is door access control. Displays Authorized, unotherized and the card key info.

the third mode is to add cards. So you scan a card, it puts it into add card mode. Then you can scan 2-3 more cards and it adds it to the authorized card list.

the fourth mode is just like the 3rd but it removes cards.

Modes are all selected by scanning different configuration cards.

1 Like

And you want to integrate that code or duplicate the functionality?

1 Like

You must have replied before my edit went through.

The sample I has shows that it’s possible to do different modes with card scans, but I want to do it as outlined which I believe is how Deviant set it up.

I can do it, but it will take time for me to learn. Which I don’t mind, I just have other things I’m working on in tandem

2 Likes

Ah gotcha, makes sense. I have a good bit of experience coding arduinos and such. Unfortunately I don’t have much free time currently so I can’t lead dev efforts, but I’m more than happy to help how I can

3 Likes

That’s all I need, someone to check my code and tell me why I’m an idiot rather than just confirming what my wife reinforces

6 Likes

You should take a look at GitHub - evildaemond/doorsim: An Open-Source Door Simulator for RFID/PACS Training they have an interesting firmware with a similar project.

2 Likes

I made a similar setup but for home automation using Home Assistant.

You could use do the same thing with your reader and have a desktop reader that integrates with Home Assistant

2 Likes

I love that idea. Is the code for an esp32 easily moved to an Arduino?

Nevermind I just read the git.

Yeah you could easily add a espkey in line and use both. I know nothing about programming esp32

2 Likes

Esp32’s support arduino. You need to add them as a board in the arduino ide but then the code is pretty much the same

3 Likes

Alright I may look into this. I know nothing about them other than using wiled and espkey

3 Likes

I use them frequently, I’m happy to answer any questions you run into

2 Likes

@Jammyjellyfish

Havent dipped into the ESP32 yet. because i dont have a plethora of them currently.

But can you review what i currently have. I added some features like pulling out Card # and Facility code from the Wiegand data, and i added the mode cases for adding a card, removing a card, and setup a pin to send a signal for a relay for a door access.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wiegand.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1  
#define SCREEN_ADDRESS 0x3C 

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
WIEGAND wg;

#define MAX_CARDS 20  
uint32_t authorizedCards[MAX_CARDS];
uint8_t cardCount = 0;

const uint32_t modeCards[4] = {1, 2, 3, 4}; 
uint8_t currentMode = 1;

uint8_t countBits(uint32_t data) {
  uint8_t count = 0;
  while (data) {
    data >>= 1;    // Right shift by 1 to move through each bit
    count++;       // Count each shift as a bit
  }
  return count;
}

uint8_t getFacilityCode(uint32_t data) {
  return (data >> 16) & 0xFF;  // Extract the top 8 bits as facility code
}

uint16_t getCardNumber(uint32_t data) {
  return data & 0xFFFF;  // Extract the lower 16 bits as the card number
}
#define SIGNAL_PIN 13    
#define BEEPER_PIN 12     

void setup() {
  delay(500);
  Serial.begin(9600);

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS, OLED_RESET)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);  
  }
  display.clearDisplay();
  display.display();  // Ensure display is clear
  display.setTextSize(2);
  display.setTextColor(WHITE);

  wg.begin();

  pinMode(SIGNAL_PIN, OUTPUT);
  digitalWrite(SIGNAL_PIN, LOW);

  pinMode(BEEPER_PIN, OUTPUT);
  digitalWrite(BEEPER_PIN, LOW);  // Ensure beeper is off initially

  // Display "Read Mode" directly on startup
  display.clearDisplay();
  display.setCursor(13, 0);
  display.print("Read Mode");
  display.display();
}

void loop() {
  if (wg.available()) {
    uint32_t cardData = wg.getCode();  
    uint8_t bitLength = countBits(cardData);  // Manually calculate bit length
    uint8_t facilityCode = getFacilityCode(cardData);  // Get facility code
    uint16_t cardNumber = getCardNumber(cardData);  // Get card number

    // Debugging: Print card data, bit length, and facility code to Serial Monitor
    Serial.print("Card Data: ");
    Serial.println(cardData);
    Serial.print("Bit Length: ");
    Serial.println(bitLength);
    Serial.print("Facility Code: ");
    Serial.println(facilityCode);
    Serial.print("Card Number: ");
    Serial.println(cardNumber);

    // Beep to indicate card read
    beep();

    // Check if the scanned card is a mode-changing card
    for (uint8_t i = 0; i < 4; i++) {
      if (cardData == modeCards[i]) {
        currentMode = i + 1;
        displayMode();
        return;
      }
    }

    // Perform actions based on the current mode
    switch (currentMode) {
      case 1:
          display.clearDisplay();
          display.setCursor(13, 0);
          display.setTextSize(2);
          display.print("Read Mode");

          display.setTextSize(1);
          display.setCursor(0, 22);
          display.print("Card #: ");
          display.print(cardNumber);  // Show only the card number part

          display.setCursor(0, 32);
          display.print("FC: ");
          display.print(facilityCode);

          display.setCursor(0, 42);
          display.print("Bit Len: ");
          display.print(bitLength);

          display.setCursor(0, 52);
          display.print("Raw Data: ");
          display.print(cardData);

          display.display();
          break;

      case 2:
        if (isAuthorized(cardData)) {
          digitalWrite(SIGNAL_PIN, HIGH);  
          delay(500);                      
          digitalWrite(SIGNAL_PIN, LOW);   
          displayData("Door Mode", "Authorized", "", "");
        } else {
          displayData("Door Mode", "Denied", "", "");
        }
        break;

      case 3:
        addCard(cardData);
        displayData("Add Card Mode", "Card Added", "Card Data: " + String(cardData), "");
        break;

      case 4:
        removeCard(cardData);
        displayData("Remove Card Mode", "Card Removed", "Card Data: " + String(cardData), "");
        break;
    }
  }
}

void beep() {
  digitalWrite(BEEPER_PIN, HIGH);  
  delay(50);                     
  digitalWrite(BEEPER_PIN, LOW);  
}

void displayMode() {
  String modeText = "";
  switch (currentMode) {
    case 1: modeText = "Read Mode"; break;
    case 2: modeText = "Door Mode"; break;
    case 3: modeText = "Add Card Mode"; break;
    case 4: modeText = "Remove Card Mode"; break;
  }
  displayData(modeText, "", "", "");
}

void displayData(String mode, String line1, String line2, String line3) {
  display.clearDisplay();   // Clear display buffer
  display.setTextSize(2);

  display.setCursor(13, 0);
  display.setTextColor(WHITE);
  display.print(mode);

  display.setTextSize(1);
  display.setCursor(0, 20);
  display.print(line1);
  display.setCursor(0, 30);
  display.print(line2);
  display.setCursor(0, 40);
  display.print(line3);

  display.display();        // Refresh display to show updated content
}

bool isAuthorized(uint32_t data) {
  for (uint8_t i = 0; i < cardCount; i++) {
    if (authorizedCards[i] == data) {
      return true;
    }
  }
  return false;
}

void addCard(uint32_t data) {
  if (cardCount < MAX_CARDS && !isAuthorized(data)) {
    authorizedCards[cardCount] = data;
    cardCount++;
  }
}

void removeCard(uint32_t data) {
  for (uint8_t i = 0; i < cardCount; i++) {
    if (authorizedCards[i] == data) {
      for (uint8_t j = i; j < cardCount - 1; j++) {
        authorizedCards[j] = authorizedCards[j + 1];
      }
      cardCount--;
      break;
    }
  }
}
2 Likes

i also added the RP15 case design so you have 2 options for cases.

Rp15 Bottom.stl (359.1 KB)
Rp15 Top.stl (135.4 KB)
R10 Case bottom.stl (347.2 KB)
R10 Case Top.stl (139.9 KB)

i ended up buying a lot of RP15’s because it was cheaper than buying them individually, so if someone wants to build this i have a few i can sell. 20$ each

3 Likes

Looks like a good start!

Some quick code style comments:

  • You don’t need the delay on line 41
  • When organizing code, I personally like all my defines up right under the includes lines
  • modeCards could be an enum, it will help a lot with code readability (or at least a comment with what the modes mean :grin: )
  • not a big deal in this case, but the 50ms delay in beep() is blocking, that’s pretty long if the code needs to do other things

I’d recommend taking a look at the eeprom library next, it will allow you to save the card arrays to non-volatile memory, so you don’t lose them when you turn the system off

Run into any pain points while getting it this far?

4 Likes

Awesome! How’s the scan performance? I may get one or two from you =)

2 Likes

Its needed for the OLED. you need to add a delay for the screen to process the information. otherwise it wont turn on at start, but will turn on at the first card read.

Im not a coder, so i assumed i seem to have just added them as needed. Be happy i comment to the best of my ability. Ill move them.

I have no idea what this means or entails.

I am having issues with the beep. It may be the reader, but the reader itself doesnt beep when scanned like the R10. running the beep circuit it has a brain melting low beep hum non-stop even with the code setting the pin to low. so currently beep isnt functioning correctly.

I would really like to do this but my time to work on this project is starting to dwindle as my free-time has to switch focus to my FTJ. if you want to send me some documentation regarding on how to switch this ill look at it as my freetime frees up again.

The biggest pain-point i had was in regards to displaying the wiegand data correctly. for some reason i had a hell of a time counting the bit-length.

Actually really good. I like the R10 more just because of it’s form-factor but it has great performance. however i cannot get it to read either my Xmagic or my Xsiid. it wont even light the Xsiid but the R10 did just fine.

4 Likes

You may want to look into adding a pullup or pulldown to on the beeper pin. Most wiegand readers I’ve dealt with grounding the beep pin made it beep so if it’s kind of floating it can cause these issues.

I might spin up a copy of the hardware here with your code for testing :slight_smile:

3 Likes

This explains a lot. I’ll add my in line.

edit: did not work for me, suspecting i have a bad internal beeper on this unit as it works perfectly fine on the R10

Edit2: Placing a Repeater sticker on the RP15 in this location allows it to read Xsiid’s perfectly fine.

5 Likes