Hello!
So, I recently started using Arduino Nano because I had a fantastic project I wanted to test out.
To get RFID data to my server and respond with the proper sound on the output buzzer, I used serial communication with the Arduino on my Raspberry Pi.
/*
* -----------------------------------------------------------------------------------------
* Typical pin layout used:
* -----------------------------------------------------------------------------------------
* MFRC522 Arduino Arduino Arduino Arduino Arduino
* Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
* Signal Pin Pin Pin Pin Pin Pin
* -----------------------------------------------------------------------------------------
* RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
* SPI SS SDA(SS) 10 53 D10 10 10
* SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
* SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
* SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
*
* More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
*/
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
#define GREEN_LED 8
#define YELLOW_LED 7
#define RED_LED 6
byte nuidPICC[4];
int buzzerPin = 2;
void printHex(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
void ReadRFID(){
if ( ! mfrc522.PICC_IsNewCardPresent())
return;
if ( ! mfrc522.PICC_ReadCardSerial())
return;
if (mfrc522.uid.uidByte[0] != nuidPICC[0] || mfrc522.uid.uidByte[1] != nuidPICC[1] || mfrc522.uid.uidByte[2] != nuidPICC[2] || mfrc522.uid.uidByte[3] != nuidPICC[3] ) {
// Store NUID into nuidPICC array
for (byte i = 0; i < 4; i++) {
nuidPICC[i] = mfrc522.uid.uidByte[i];
}
printHex(mfrc522.uid.uidByte, mfrc522.uid.size);
Serial.println();
} else {
Serial.write("Card read previously.\n");
}
}
void Version(){
Serial.write("version\n");
}
void SerialParser(void) {
char readChar[64];
Serial.readBytesUntil(33,readChar,64);
String read_ = String(readChar);
//Serial.println(readChar);
int idx1 = read_.indexOf('%');
int idx2 = read_.indexOf('$');
// separate command from associated data
String cmd = read_.substring(1,idx1);
String data = read_.substring(idx1+1,idx2);
ReadRFID();
if (cmd == "version") {
Version();
} else if (cmd == "success"){
digitalWrite(GREEN_LED, HIGH);
tone(buzzerPin, 440, 1000);
} else if (cmd == "failed") {
digitalWrite(RED_LED, HIGH);
for (int i = 0; i < 2; i = i + 1) {
tone(buzzerPin, 261, 500);
delay(1000);
}
} else if (cmd == "offline") {
digitalWrite(YELLOW_LED, HIGH);
for (int i = 0; i < 3; i = i + 1) {
tone(buzzerPin, 349, 500);
delay(1000);
}
} else if (cmd == "idle"){
delay(1000);
digitalWrite(GREEN_LED, LOW);
digitalWrite(RED_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
}
}
void setup() {
Serial.begin(38400);
SPI.begin(); // Initiate SPI bus
mfrc522.PCD_Init(); // Initiate MFRC522
pinMode(buzzerPin, OUTPUT);
}
void loop() {
SerialParser();
}
Python Communication
import re
import itertools
import platform
import requests
import serial
import time
from serial.tools import list_ports
if platform.system() == 'Windows':
import winreg
else:
import glob
URL = "http://127.0.0.1:6969/api/v1/rfid"
def internet_connection():
try:
requests.get('http://1.1.1.1/') #Python 3.x
return True
except: return False
def enumerate_serial_ports():
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
except WindowsError: raise Exception
for i in itertools.count():
try:
val = winreg.EnumValue(key, i)
yield (str(val[1])) # , str(val[0]))
except EnvironmentError: break
def build_cmd_str(cmd, args=None):
if args: args = '%'.join(map(str, args))
else: args = ''
return "@{cmd}%{args}$!".format(cmd=cmd, args=args)
def get_version(sr):
cmd_str = build_cmd_str("version")
try:
sr.write(cmd_str.encode())
sr.flush()
except Exception: return None
return sr.readline().decode().strip()
def find_port(baud, timeout):
if platform.system() == 'Windows': ports = enumerate_serial_ports()
elif platform.system() == 'Darwin': ports = [i[0] for i in list_ports.comports()]
else: ports = glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*")
for p in ports:
print('[+] Found {0}, testing...'.format(p))
try: sr = serial.Serial(p, baud, timeout=timeout)
except (serial.serialutil.SerialException, OSError) as e:
print(str(e))
continue
time.sleep(2)
version = get_version(sr)
if version != 'version':
print('[+] Bad version {0}. This is not a Shrimp/Arduino!'.format(version))
sr.close()
continue
print('[+] Using port {0}.'.format(p))
if sr:
return sr
return None
def send_cmd(sr, cmd):
cmd_str = build_cmd_str(cmd).encode()
try:
sr.write(cmd_str)
sr.flush()
except Exception: return None
return sr.readline().decode().strip()
class IO_RFID():
def __init__(self, baud=38400):
self.baud = baud
self.serial = find_port(self.baud, timeout=1)
def read_tag(self):
with self.serial as serial:
regex = r'[0-9A-F]{2} [0-9A-F]{2} [0-9A-F]{2} [0-9A-F]{2}'
while True:
line = serial.readline().decode().strip()
if re.match(regex, line):
tag = line.split(" ")[::-1]
tag = ''.join(tag)
tag = int(tag, 16)
print(f"[+] TAG: {tag}")
if internet_connection():
try:
response = requests.get(URL, params={"rfid": tag})
if response.json()['status_code'] == 3:
send_cmd(self.serial, "success")
send_cmd(self.serial, "idle")
elif response.json()['status_code'] in [1, 2, 4, 5, 6, 7, 8]:
send_cmd(self.serial, "failed")
send_cmd(self.serial, "idle")
elif response.json()['status_code'] == 9:
send_cmd(self.serial, "offline")
send_cmd(self.serial, "idle")
except:
send_cmd(self.serial, "offline")
send_cmd(self.serial, "idle")
else:
send_cmd(self.serial, "offline")
send_cmd(self.serial, "idle")
if __name__ == '__main__':
obj = IO_RFID(38400)
obj.read_tag()