Using an M302 RF ID Reader with Linux

I want to build a audio player for my little kids. CD and MP3 players are too fragile. Things I can buy are too expensive and too limited. For an example, there is the Toniebox which looks cute, but buying all our media again for 15€ a piece is too expensive. Also, I want to control the time when it is available. When the kids should sleep, the device shall refuse to play. Hopefully, the removes one source of drama since I personally don't have to take it away in the evening.

Primarily inspired by this project, now I want to build a Raspberry Pi powered media player. The device will be at least as expensive as the Toniebox in parts alone, but we can reuse all our media and I have unlimited control. Also, I can extend it in the future. Maybe add a screen. Maybe make it stream music from our homeserver. Maybe add buttons. Finally, this household does not have any Raspberry Pi yet.

The first hardware that arrived was the RFID reader. I paid 10.50€ (including shipping) on Ebay. It came with five RFID cards and five chips.

My M302 Mifare RF ID Reader

My first step was to get it running with my Ubuntu laptop. There is little documentation which is one reason I'm blogging this. The simplest way I found was this little Python2 script:

import serial

prot = {
    'enquiry_module': '\x03\x12\x00\x15',
    'enquiry_module_return': '\x02\x12\x14',
    'active_buzzer': '\x02\x13\x15',
    'enquiry_card': '\x03\x02\x00\x05',
    'enquiry_cards_return': '\x03\x02\x01\x06', # got valid card
    'enquiry_no_card_found': '\x02\x01\x03', # no card reachable or invalid
    'enquiry_all_cards': '\x03\x02\x01\x05',
    'anticollision' : '\x02\x03\x05\x00',
    'select_card' : '\x02\x04\x06',
}

ser = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
ser.write(prot['enquiry_card'])
resp =  ser.read(4)

if resp == prot['enquiry_no_card_found']:
    print "no valid card reachable"
elif resp == prot['enquiry_cards_return']:
    ser.write(prot['active_buzzer'])
    resp = ser.read(3)
    if resp == prot['active_buzzer']:
        print "found card, sending anticollision"
        ser.write(prot['anticollision'])
        resp = ser.read(7)
        header = resp.encode('hex')[:4]
        if header == "0603":
            print "Card Serial:" + resp[-5:].encode('hex')

ser.close()

It seems the RF ID reader tunnels a serial connection via USB, so we need the python-serial package.

apt install python-serial

If you plug in the M302 and execute this script (with sudo), it should print all the RFID tags you put on. For experimenting, try all the cards in your wallet and find out if they contain an RFID chip.

It also makes the reader beep, which is annoying and optional. The three lines about the active_buzzer do that. For my project, I will remove that. While I'm waiting for my Raspberry Pi to arrive, the next steps are to get some coding done.

How to get a cheap RF ID reader running with Ubuntu and Python