Automating measurements from an RFID reader using Python

In the last blog about communicating with the Intelleflex FMR-6000 RFID reader over a TCP/IP connection, I had a Python script sending a string and then printing the reader’s response. This opened up a lot of possibilities for doing interesting things like automating data readings and graphs. For an experiment, I wanted to place one tag in front of the reader’s antenna at a certain position and continue to try and read the tag whilst lowering the transmit antenna’s output power. After this is done the tag is moved to a different position in front of the antenna and the experiment is repeated. The reader accepts commands in XML format, like in the example below:

find_tags.xml:

<findTags>
	<loop>0</loop>
	<roSpec>
		<Qval>3</Qval>
		<txAnt>1</txAnt>
		<RFProfile>2</RFProfile>	 
		<protocol>4</protocol>  	
		<power>30</power>
	</roSpec>
</findTags>

It sends data back in XML format also, it looks something like this:
tag_data.xml:

<findTagsReply>
	<errorReport>
		<numErrors>0</numErrors>
	</errorReport>
	<tag>
		<time>2014-03-19 13:16:41.402770 +0000</time>
		<roSpecID>0</roSpecID>
		<type>C1G2</type>
		<epc>e2003411b802011412255232</epc>
		<channel>1</channel>
		<slot>4</slot>
		<dbm>-43.63</dbm>
		<count>1</count>
		<rssi>65841</rssi>
	</tag>
	<nextChannel>0</nextChannel>
	<collisions>39</collisions>
</findTagsReply>

Here is the python script:

# Program written by Shane Ormonde 19th March 2014
# This script automates reducing the power level from 30dB - 0dB, taking measurements every 1dB
# plots transmit power vs received tag signal strength

import socket
import xml.etree.ElementTree as ET
import matplotlib.pyplot as plt

TCP_IP = '192.168.0.113'
TCP_PORT = 80
BUFFER_SIZE = 4028

#Variables
tags = []
r_power = []
t_power = []
Tr_power = []
epc = 0


def send_xml_get_data():
	f = open('find_tags.xml','r+') ## open xml file to send to reader
	data = f.read() ## read it as a string into variable data
	f.close()

	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # set up socket connection
	s.connect((TCP_IP,TCP_PORT))
	s.send(data) ## send the xml file

	rdata = s.recv(BUFFER_SIZE) # xml file returned by the reader
	s.close()

	f = open('tag_data.xml','w') 
	f.write(rdata)# write it to a file called tag_data.xml
	f.close()
	
	
def parse_xml(): # this function opens the xml file from the reader and gets the data we want from it
	tree = ET.parse('tag_data.xml')## load the received xml file for parsing
	root = tree.getroot()
	
	for tag in root.findall('tag'): # find the child called 'tag'
		
		epc = tag.find('epc').text ## within that child get the epc number of the tag
		power = tag.find('dbm').text ## also ge the tag signal strength
		if epc == 'e2003411b802011412255232': # this is just to ensure that no other tags are accidentaly read
		   r_power.append(power)
	
	   
def decrement_power(): #opens the xml file and overwrites the number in the 'power' tag
	tree = ET.parse('find_tags.xml')
	root = tree.getroot()
	for roSpec in root.findall('roSpec'): # read back this new power level and print to screen
		power = roSpec.find('power').text
		print "t_power = " + power
		t_power.append(power)
	
	for power in root.iter('power'):  ## set a new transmit power level
	   new_power = int(power.text) - 1 # decrease the power by one dB 
	   power.text = str(new_power)

	

	tree.write('find_tags.xml') # write the changes to the file
	
def set_power_max(): # opens the command xml file being send to the reader and sets the power to 30dB
	tree = ET.parse('find_tags.xml')
	root = tree.getroot()
	for power in root.iter('power'):  ## set a new transmit power level
	   new_power = 30
	   power.text = str(new_power)
	
	tree.write('find_tags.xml')
	 
def plot(): # plots transmitted power versus received tag power
	plt.plot(t_power,r_power, 'r', linewidth = 2)
	plt.gca().invert_xaxis() # this makes 30dB at the origin
	plt.grid(True)
	plt.ylabel('Receive Power (dBm)')
	plt.xlabel('Transmit Power(dBm)')
	plt.show()  
	

set_power_max() ## in case the last program failed whilst running and the power is not already at max

for i in range(30): 
	send_xml_get_data() # send the command xml, get readers response
	parse_xml() # open the xml file and get the wanted data
	decrement_power() # decrease the reader transmit power by 1

set_power_max() ## reset reader power to max

g = len(r_power)  # if the tag cannot be read, the r_power list will have less than 30 elements, this makes the both the same length
t_power = t_power[0:g]

plot()





Download script

This is what happens when I run the script, notice that there is no tag signal strength near the end. This is because the transmit power went too low to get a read:

terminal

terminal

This is a plot output, just from looking at the graph I know that 14 dB is the absolute minimum, but if some margin is needed, 20dB should be enough to get consistent reads.

Plot of Transmit power vs tag signal strength

Plot of Transmit power vs tag signal strength

Just to clarify what the program actually does: The python script sends the find_tags.xml file over to the reader. The reader then sends back an xml file that I called tag_data.xml (examples of these can be seen above). This file contains the tag epc and signal strength amongst other things. The Python script parses the tag_data.xml file to extract the epc and signal strength from it. The script then opens up the find_tags.xml file and it changes the reader transmit power parameter ( it decreases it by one ). The process then repeats, this file is sent off, reader data is retrieved etc. This happens 30 times from 30dBm down to 0dBm. In each pass through the loop the reader transmit power and the tag signal strength are appended to lists. When the loop is finished the results are plotted using matplotlib.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s