This tutorial describes how to use the Codatex RFID Sensor with pbLua. The RFID sensor is really useful in all kinds of applications. If your robot moves along a line, you can place the RFID tags to help locate waypoints along the path. If you put the tags into containers, you can identify them easily and take action on them.
By the end of this tutorial, you'll be able to use the Codatex RFID sensor just as easily as any other I2C based sensor that interfaces with the Mindstorms NXT.
The Codatex RFID Sensor is a third party sensor that connects to an I2C port on the bottom of the NXT. You may want to familiarize yourself with the pbLua I2C API and read over the pbLua I2C Tutorial for detailed examples of how it's used.
To get started, plug your RFID sensor into Port 1 and run the following example code to verify that you can communicate with the IRLink.
-- setupI2C() - sets up the specified port to handle an I2C sensor function setupI2C(port) nxt.InputSetType(port,2) nxt.InputSetDir(port,1,1) nxt.InputSetState(port,1,1) nxt.I2CInitPins(port) end -- Now put the standard I2C messages into the nxt table nxt.I2Cversion = string.char( 0x02, 0x00 ) nxt.I2Cproduct = string.char( 0x02, 0x08 ) nxt.I2Ctype = string.char( 0x02, 0x10 ) nxt.I2Ccontinuous = string.char( 0x02, 0x41, 0x02 ) nxt.I2Cdata = string.char( 0x02, 0x42 ) -- waitI2C() - sits in a tight loop until the I2C system goes idle function waitI2C( port ) while( 0 ~= nxt.I2CGetStatus( port ) ) do end end -- Put it all together in a function that prints out a report of which -- sensor is connected to a port function checkI2C(port) setupI2C(port) nxt.I2CSendData( port, nxt.I2Cversion, 8 ) waitI2C( port ) print( "Version -> " .. nxt.I2CRecvData( port, 8 ) ) nxt.I2CSendData( port, nxt.I2Cproduct, 8 ) waitI2C( port ) print( "Product ID -> " .. nxt.I2CRecvData( port, 8 ) ) nxt.I2CSendData( port, nxt.I2Ctype, 8 ) waitI2C( port ) print( "SensorType -> " .. nxt.I2CRecvData( port, 8 ) ) end
And then verify that it's working:
-- And use it - make sure you specify the port you have plugged the -- IR Link in to: checkI2C(1) -- Gives these results: -- Version -> V1.0 -- Product ID -> CODATEX -- SensorType -> RFID
This example sets up the sensor for a single reading. If an RFID tag is read, then the sensor goes back to sleep immediately. If there is no RFID tag ready to be read, the sensor goes to sleep about 500 msec after the command is issued.
-- Turn on the RFID sensor and take a single reading, then print the result
singleRead = string.char( 0x02, 0x41, 0x01 )
-- And this is the test function
function ReadRFID(port,delay)
-- Do a single reading
nxt.I2CSendData( port, singleRead, 0 )
waitI2C( port )
-- wait delay msec ...
t = nxt.TimerRead()
while t+delay > nxt.TimerRead() do
-- This space intentionally left blank!
end
nxt.I2CSendData( port, nxt.I2Cdata, 6 )
waitI2C( port )
result = nxt.I2CRecvData( port, 6 )
-- Break the resulting string into 6 bytes and print them
c1,c2,c3,c4,c5,c6 = string.byte(result,1,6)
print( string.format( "Result: %02x %02x %02x %02x %02x %02x",
c1, c2, c3, c4, c5, c6 ) )
end
-- And using the function
ReadRFID(1,300)
The results with this example are mixed, you may have to experiment with the delay setting for best results. This code is best used in situations where you know that an RFID tag is ready to read.
The RFID sensor also has a mode where it reads tags continuously, and makes the results avaialble as they appear. Ater about 2 seconds of I2C inactivity (you have stopped polling for results) the sensor goes to sleep to conserve power.
The following code example is example sets up the sensor for continuous reads with a delay between polling the device for new data. If the result data strings are empty or the same between polls, then no results are printed.
-- Turn on the RFID sensor and take continuous readings, then print results
-- if consecutive readings are different and non-null...
contRead = string.char( 0x02, 0x41, 0x02 )
-- These strings represent bad RFID results
emptyRFID = string.char( 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF )
nullRFID = string.char( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
-- And this is the test function
function ReadRFID(port,delay)
-- Do continuous reading
nxt.I2CSendData( port, contRead, 0 )
waitI2C( port )
result = ""
repeat
oldResult = result
nxt.I2CSendData( port, nxt.I2Cdata, 6 )
waitI2C( port )
result = nxt.I2CRecvData( port, 6 )
-- print results if valid and different from previous
if ((result ~= emptyRFID) and (result ~= nullRFID) and (result ~= oldResult)) then
-- Break the resulting string into 6 bytes and print them
c1,c2,c3,c4,c5,c6 = string.byte(result,1,6)
print( string.format( "Result: %02x %02x %02x %02x %02x %02x",
c1, c2, c3, c4, c5, c6 ) )
-- wait delay msec ...
t = nxt.TimerRead()
while t+delay > nxt.TimerRead() do
-- This space intentionally left blank!
end
end
until( 8 == nxt.ButtonRead() )
end
-- And using the function
ReadRFID(1,50)
And here are some typical results. Again, you may have to fiddle with the delay parameters to get good data for your application.
> ReadRFID(1,50) Result: 21 db a6 a0 86 ff Result: 21 db a6 a0 86 ff Result: 21 db ff ff ff ff Result: 21 db a6 a0 86 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff Result: 04 16 1d 6e 78 ff
The RFID sensor is easy to use with pbLua, but getting reliable results can take a bit of tuning. It's not clear to me yet if it's possible to validate the data, which would make the whole reading process much more reliable.