Buffer Flooding When Reading is Delayed in Python

Hi there. Very new to arduinos, so my apologies if I'm missing some obvious steps here. I'm working on a project where an RFID-RC522 reader reads an RFID card, pulls that read number in, and relays in out via serial. The code for that is as follows:

#include <SPI.h>
#include <RFID.h>
#define SS_PIN 10
#define RST_PIN 9

RFID rfid(SS_PIN, RST_PIN);
String rfidCard;
void setup() {
  Serial.begin(9600);
  //Serial.println("Starting the RFID Reader...");
  SPI.begin();
  rfid.init();
}
void loop() {
  if (rfid.isCard()) {
    if (rfid.readCardSerial()) {
      rfidCard = (String(rfid.serNum[0]) + String(rfid.serNum[1]) + String(rfid.serNum[2]) +  String(rfid.serNum[3]));
      Serial.print(rfidCard);
    }
    rfid.halt();
  }
}

That part works great. On the python side, the following code runs on my computer and reads everything in fine:

import serial
import time
connected = False
#This port below is specific to my usb port I think
port = '/dev/cu.usbserial-14620'
baud = 9600


serial_port = serial.Serial(port, baud, timeout=0)

while True:

   reading = serial_port.readline().decode()
   if reading != '':
         print(reading)

So the end result when I plug in the RFID reader to my arduino Nano, and the Nano into my computer, and run the Python code is: When I put an RFID card up to the reader, it continuously prints the number, and when I pull it away, it prints nothing. Looks like this:

786179181
786179181
786179181
786179181
786179181
786179181

Exactly what I want.

Here's where the problems start. I want to introduce a period of time in the python script where it won't read anything. A sort of delay where the RFID reader is essentially not useable. This code is a minimally reproducible example of the effect I'm trying to get:

i = 5

while i > 0:

   print(i)
   time.sleep(1)
   i-=1 

When I add this code right before the Serial initialization line, it prints a countdown from 5 to 1, and then opens the port and starts reading and printing. But it looks like if I place the card on the reader before the countdown is up, it adds all that it reads to a buffer, and then spams it all at once, once the port is allowed to print again. What's most strange to me is that it actually begins to spam it in a loop, even when I take the card away. And from here on out, the arduino is now stuck in this state of spamming the data - even if I terminate the python script and rerun it, and dont put any card up to the reader, it's still spamming that old data in an infinite loop. It Looks more like this, stacking into one line at times:

786179181786179181786179181786179181
786179181
786179181786179181786179181786179181786179181

Ive tried using commands like "flush(), "reset_input_buffer()", and "reset_output_buffer()", but they don't seem to do what I want, or maybe I don't completely understand how they work. I'm not entirely sure if my problem lies in the arduino code output or the python code input.

If anyone could help me find a solution, and even better understand why this occurs, that would be awesome. Thanks in advance!

I would have thought that the problem is at the Arduino end because this part never stops sending data. So this is filling up the buffer.

One way round this is to send a request from the PC to Arduino to read one card and send it. It should do nothing else unless told to take another reading.

Thanks for the reply. The strange thing is the code works fine unless it has to use that buffer, then is just sort of spams in that loop.

This solution could work I think. So my python script would send a command that says to the arduino after a delay period "start reading for RFIDs continuously", and then I could theoretically later send a command that says "Stop reading again" and so on? What would be the best way to accomplish this, sending serial data the other way?

Something like
in setup()
Serial.setTimeout(100);

void loop() {
  if (rfid.isCard()) {
    if (rfid.readCardSerial()) {
       if (Serial.available()) {   // skip until Python sends something
         Serial.readString(); // clear the input Python has sent
         // send the output  skip the String + stuff
         Serial.print(rfid.serNum[0]); Serial.print(rfid.serNum[1]); Serial.print(rfid.serNum[2]); Serial.print(rfid.serNum[3])
       }
    }
    rfid.halt();
  }
}

Thanks for the advice. I've been trying to get this to work, with "if (Serial.available())" and with "if (Serial.available()>0)". It seems like no matter what I do, I get no response while the RFID tag is on the reader. Then, after a few seconds, I get a large one time concatenation of a bunch of consecutive reading, and then, nothing again. For some reason this line prevents it from reading continuously.

I'm trying to break this down to the simplest example. Here I removed all the RFID stuff. My arduino code simply sends a string "reading" if it's getting data from Python:

#include <SPI.h>

void setup() {
  Serial.begin(9600);
  SPI.begin();
}
void loop() {
  while (Serial.available()) {

      Serial.print("Reading");
  }
}

My python code sends continuous data to the arduino, and reads every line it receives:

import serial
port = '/dev/cu.usbserial-14620'
baud = 9600

serial_port = serial.Serial(port, baud, timeout=1)

while True:

   serial_port.write(b'1') 

   reading = serial_port.readline().decode()

   if reading != '':
         print(reading)

When I run this code, nothing prints for a while, and then again a large chunk of concatenated, repeated data is printed all at once, and then nothing again. I'm sure this is just a lack of understanding on how this works on my part, but why would it not print continuously, one word per line at a time?

You don't send a line, you just send 7 characters without a line-ending.

I'm not a python programmer, but I guess that readLine reads till a line-ending is received. As you don't send a line-ending, it probably waits for a timeout.

@sterretje it's amazing how obvious something can seem after it's been explained. Thank you for that humbling explanation :sweat_smile:

Alright, I was able to get this to work after some syntax corrections on my side thanks to @sterretje. I've marked it as the solution. Thank you everyone for your help! I'm new to arduinos, and it's nice to know theres a good support community behind it.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.