Grove RFID 125 khz using Seeeduino and base board

My first post here.

I have Seeduino 4.3 with base board and two Grove 125 khz RFID readers. The main board is ok connected as Arduino Uno in the IDE. I have followed the basic steps given at Grove - 125KHz RFID Reader | Seeed Studio Wiki using the sketch given there. I have tried 25mm ‘paper’ tags, keyfob tag and card. Nothing triggers the softserial.

All the lights are on. The Seeduino responds e.g. Setup() runs; Loop() iterates; it echoes Serial Monitor input. I have tried using default SoftSerial(2,3) and added another reader as SoftSerial2(5,6) - nothing happens. I started with the sketch as supplied and modified slightly while trying to see if this is a software or hardware problem.

Full code:

/*

link between the computer and the SoftSerial Shield

at 9600 bps 8-N-1

Computer is connected to Hardware UART

SoftSerial Shield is connected to the Software UART:D2&D3

*/

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial1(2,3); // RX/TX = D2 on base shield

SoftwareSerial SoftSerial2(5,6); // RX/TX = D5 on base shield

unsigned char buffer[64]; // buffer array for data receive over serial port

int count = 0; // counter for buffer array

int n = 0;

void setup()

{

SoftSerial1.begin(9600);     // the SoftSerial baud rate

SoftSerial2.begin(9600);     // the SoftSerial baud rate

Serial.begin(9600);          // the Serial port of Arduino baud rate.

Serial.println("hello from seeeduino");

}

void loop()

{

// if data is coming from a software serial port ==> data is coming from SoftSerial shield

if (SoftSerial1.available())              

{

    Serial.println("data on SoftSerial1");

    while(SoftSerial1.available())               // reading data into char array

    {

        buffer\[count++\] = SoftSerial1.read();      // writing data into array

        if(count == 64)break;

    }

    Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port

    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array

    count = 0;                      // set counter of while loop to zero

}



if (SoftSerial2.available())              

{

    Serial.println("data on SoftSerial2");

    while(SoftSerial2.available())               // reading data into char array

    {

        buffer\[count++\] = SoftSerial2.read();      // writing data into array

        if(count == 64)break;

    }

    Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port

    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array

    count = 0;                      // set counter of while loop to zero

}



if (Serial.available())             // if data is available on hardware serial port ==> data is coming from PC or notebook

{

    Serial.println("data received on serial port: ");



    while(Serial.available())               // reading data into char array

    {

        buffer\[count++\] = Serial.read();      // writing data into array

        if(count == 64)break;

    }

    //Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port

    Serial.write(buffer, count);

    Serial.print("\\nchars rcvd: ");

    Serial.println(count);

    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array

    count = 0;                      // set counter of while loop to zero

    //SoftSerial.write(Serial.read());    // write it to the SoftSerial shield

}



n++;

}

void clearBufferArray() // function to clear buffer array

{

// clear all index of array with command NULL

for (int i=0; i<count; i++)

{

    buffer\[i\]=NULL;

}

Serial.println("\\ncleared buffer");              

}

Any ideas please?

Update: I realised from Serial User Guide for Arduino Boards | Seeed Studio Wiki that the board can only listen to one softserial at a time, so added SoftSerial1.listen(); and SoftSerial2.listen(); before the relevant code sections.

Still not picking anything up. Any help appreciated!

1 Like

Hi there,

And Welcome here…

SO you need to use the code tags when posting code “</>” paste it in there.
I gave it an edit. and It does compile. but it is missing some key parts?
You create two SOFTserials but never call them? and SoftwareSerial defaults to the last one that was started (or last one that called listen()), and the other will silently miss data.
Even worse: with two readers, you must explicitly switch which one is listening, e.g. poll like:

SoftSerial1.listen();
if (SoftSerial1.available()) ...
SoftSerial2.listen();
if (SoftSerial2.available()) ...

if you expect both to trigger independently, they won’t.
SoftwareSerial(rx, tx) means first pin is RX (Arduino receives on that pin).
RFID reader modules usually output serial data on their TX pin. That must go to Arduino RX.

So wiring must be:

  • Reader TX → Arduino pin 2 (SoftSerial1 RX)
  • Arduino pin 3 (SoftSerial1 TX) → Reader RX (often not even needed)
// RX/TX = D2 on base shield

this :backhand_index_pointing_up:is nonsense. It’s not “RX/TX = D2”. It’s RX=D2, TX=D3.

On the Grove Base Shield for UNO-style boards, the UART socket is typically wired to D0/D1 (hardware serial), or there’s a switch/alternate port mapping depending on shield revision. If you are plugging the RFID reader into the shield’s UART port, but then using SoftwareSerial on D2/D3, your reading the wrong pins.
Verify the pins :+1:
This is the classic failure mode: everything “runs” but available() never fires because the signal isn’t on those pins,
Some 125 kHz readers output:
Wiegand D0/D1 pulses, or TTL UART at 9600, or RS232-level output (needs level shifting)

If Your specific Grove readers are not the UART-output type, SoftwareSerial will never see bytes. The Seeed “Grove 125kHz RFID Reader” module does output UART, but clones/variants exist.

a minor bug i see in the logic ,

You clear the buffer by looping only to count, but resets count=0 after clearing anyway
– fine but pointless.
buffer is unsigned char “[.. ]” and You use NULL instead of 0.

No delay() in loop: not required, but it will spam and burn CPU.
– Add a delay (small one)

You never print the raw bytes nicely; many RFID readers send CR/LF and/or binary framing
– still, you should at least see something.

Use code Tags :+1:

//  User posts 12/23/25 on SoftSerial.
// Xiaa Seeeduino..

#include <SoftwareSerial.h>
SoftwareSerial SoftSerial1(2,3); // RX/TX = D2 on base shield
SoftwareSerial SoftSerial2(5,6); // RX/TX = D5 on base shield
unsigned char buffer[64]; // buffer array for data receive over serial port
int count = 0; // counter for buffer array
int n = 0;
void setup()
{
SoftSerial1.begin(9600);     // the SoftSerial baud rate
SoftSerial2.begin(9600);     // the SoftSerial baud rate
Serial.begin(9600);          // the Serial port of Arduino baud rate.
Serial.println("hello from seeeduino");
}

void loop()
{
// if data is coming from a software serial port ==> data is coming from SoftSerial shield
if (SoftSerial1.available())              
{
    Serial.println("data on SoftSerial1");
    while(SoftSerial1.available())               // reading data into char array
    {
        buffer[count++] = SoftSerial1.read();      // writing data into array
        if(count == 64)break;
    }
    Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array
    count = 0;                      // set counter of while loop to zero
}

if (SoftSerial2.available())              
{
    Serial.println("data on SoftSerial2");
    while(SoftSerial2.available())               // reading data into char array
    {
        buffer[count++] = SoftSerial2.read();      // writing data into array
        if(count == 64)break;
    }
    Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port
    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array
    count = 0;                      // set counter of while loop to zero
}

if (Serial.available())             // if data is available on hardware serial port ==> data is coming from PC or notebook
{
    Serial.println("data received on serial port: ");
    while(Serial.available())               // reading data into char array
    {
        buffer[count++] = Serial.read();      // writing data into array
        if(count == 64)break;
    }
    //Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port
    Serial.write(buffer, count);
    Serial.print("\\nchars rcvd: ");
    Serial.println(count);
    clearBufferArray();             // call clearBufferArray function to clear the stored data from the array
    count = 0;                      // set counter of while loop to zero
    //SoftSerial.write(Serial.read());    // write it to the SoftSerial shield
}
n++;
}
void clearBufferArray() // function to clear buffer array
{
// clear all index of array with command NULL
for (int i=0; i<count; i++)
{
    buffer[i]=NULL;
}
Serial.println("\\ncleared buffer");              
}

I would have a Look at this posts, should see what you have missed.. :+1:
The theory is the same, make sure the pins you use are capable and you initialize them properly first. Also , be sure you DON’T have 3.3v and 5V mixed together.:crossed_fingers:

Try this;
Use only one SoftwareSerial and wire directly:

  • Reader TX → Arduino D2
  • Reader RX → Arduino D3 (optional; many readers don’t need it)
  • GND ↔ GND, VCC ↔ 5V (or 3.3V if required)

Minimal sketch;

#include <SoftwareSerial.h>
SoftwareSerial rfid(2, 3); // RX, TX

void setup() {
  Serial.begin(115200);
  rfid.begin(9600);
  rfid.listen();
  Serial.println("Ready");
}

void loop() {
  while (rfid.available()) {
    int c = rfid.read();
    Serial.write(c);
  }
}

if you get that going , then add the Second one;

SoftSerial1.listen();
read_if_any(SoftSerial1);

SoftSerial2.listen();
read_if_any(SoftSerial2);

And accept you can’t truly read both simultaneously, the Kitchen sink approach almost :grin: Never works. You are using the Grove UART ports, so you must confirm: what pins do those sockets map to on that shield revision. If it’s D0/D1, you should use Serial (hardware UART) not SoftwareSerial.

HTH
GL :santa_claus: PJ :v:
:christmas_tree:

Thanks for the comprehensive reply :grinning_face:

Most of the code is copied straight from the Seeed wiki page Grove - 125KHz RFID Reader | Seeed Studio Wiki , but I will attempt the edits you suggest. The connections I have used are as specified on that page. Just to be explicit, there are 3 components here: (1) the main board, Seeeduino 4.3 not Arduino Uno, but recognized by the IDE as Uno; (2) the Seeed base board plugged into the Seeeduino; (3) the RFID reader plugged into the base board (all as per the wiki page).

I think the pin identification is probably the problem here, somehow. The Seeed base board D2 socket has 4 pins in a connector block: RFID reader TX (yellow wire) into pin labelled “D2” (so presumably the base board RX), RFID RX (white) into “D3” (presumably base board TX), VCC (red) and GND (black). The RFID reader to base board is a Seeed proprietary connector with those wire colours and the socket only goes in one way for all 4 connections. This D2 is what the Seeed wiki says to use for starters using SoftSerial. (I only picked up later about using .listen(), see my update post.)

There is a UART socket on the Seeed base board, but I’d rather get SoftSerial working as I need multiple RFID readers into the base board. Or is the Seeed page wrong, and that is impossible?!

I tried your suggested minimal sketch but it did not detect anything.

I had previously tried RFID reader straight into Arduino Mega, but I was not convinced the DuPont jumpers were properly attaching to the proprietary Seeed connector block on the supplied cable. That never worked, hence trying the proprietary Seeed hardware.

I will have a go at further edits tomorrow, and welcome any further ideas where this is going wrong!

Philip

1 Like

PJ is the man!

He showed me how to read 2 GPS modules at the same time..

But I have to admit i forgot most of what i knew about it

I just add these links to show readers… but just to say the XIAO SAMD is also called Seeeduino XIAO… which is an old naming convention… We usually think in terms of XIAO units so I did not immediatly realize you were talking about an ATMEGA 16 and 32 based unit… i am sure you understand the code and hardware are in many cases completely different and selecting the correct BSP is important too

Nearly new year update… I finally remembered that the tags I had were from a previous (failed) attempt to use PN5180 RFID reader, so they were 13.56 MHz not 125 KHz!

So guess what, when I got some 125 KHz tags it all worked fine :grinning_face:

I can now prettify and optimise the code.

Thanks for your helpful suggestions.

Philip

2 Likes

thanks for the update!