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:
<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:
<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()
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:
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.
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.