RFID tags and antenas are a cost effective and efficient method for determining the location of a robot along its track. CANOpen RFID reader/writers are a challenge to interface directly to a motor controller. This is because CANOpen is a master/slave architecture and both the RFID antena and the motor controller are slave devices. In a typical system, a CANOpen master (a PLC for example) must fetch data from the antena and send it to the controller.
Thanks to scripting and the RawCAN protocol, a Roboteq motor controller can be made to operate as simple CANOpen master, enable the RFID antena, and then capture and parse the data sent. RawCAN is a very low-level implementation for manipulating CAN data using scripting commands.
This example shows how to interface a DTC510 RF ID sensor from IFM Electronics work and communicate with our motor controller. It is a CANOpen slave device. So in order to communicate with it we configured the motor controller as RawCAN with listen Node ID as 0. Listening to node ID 0 disables the node address filter so that the controller can see all frames on the CAN bus (the controller acts like a CAN sniffer)
By default the Node id of the RFID sensor is 32 and the bit rate is 125kb/sec. These can be changed using SDOs.
The script in the controller first constructs and send the CANOpen NMT message in order to set the DTC510 state to operational. Then at each status change the sensor sends TPDO1 which holds the device status (VAR 2), including the info whether there is tag detected or not (VAR 2).
When a tag is detected the sensor sends TPDOs 2, 3, 4 with the 40 first bytes of the tag's tag id.
We can also write data to each tag. We implemented in the script the write and erase (set 0) the tag id. For more details check the script's Header comments.
'DTC510 Reader
'Created by Roboteq Inc.
'The script can:
' * Read the 40 first bytes of the tag ID
' * Write the first 8 bytes of the tag ID and
' * Erase the first 8 bytes of the tag ID.
'VAR 1: 0 Reads the tags
' 1 Writes to the 0 - 8 bytes of the tags specific tag id, only if the tag id is 0.
' 2 Erases the tag id
'VAR 2: Displays the Device Status of DTC510
'VAR 3: Displays 1 if a tag is detected, 0 if not.
'VAR 4: Displays the 0 - 4 bytes of the tag id.
'VAR 5: Displays the 4 - 8 bytes of the tag id.
'VAR 6: Displays the 8 - 16 bytes of the tag id.
'VAR 7: Displays the 16 - 24 bytes of the tag id.
'VAR 8: Displays the 24 - 32 bytes of the tag id.
'VAR 9: Displays the 32 - 40 bytes of the tag id.
Option Explicit
#define DTC510_NODEID 32 'default to be changed with SDO indexes 0x20F0, 0x20F1
#define DTC510_BITRATE 4 'default 125kbits/s to be changed with SDO indexes 0x20F2, 0x20F3
'define TAGID_BYTE1 WriteCounter
#define TAGID_BYTE2 0x00
#define TAGID_BYTE3 0x00
#define TAGID_BYTE4 0x00
#define TAGID_BYTE5 0x00
#define TAGID_BYTE6 0x00
#define TAGID_BYTE7 0x00
#define TAGID_BYTE8 0x00
#define READ_DATA 0
#define WRITE_DATA 1
#define ERASE_DATA 2
Dim WriteCounter As Integer
Dim TriggerCounter As Integer
Dim Action As Integer
Dim Header As Integer
Dim DeviceStatus As Integer
Dim Present As Integer
Dim PrevPresent As Integer
Dim OkToWrite As Integer
Dim NewTagState As Integer
Dim tag[5] As Integer
WriteCounter = 0
TriggerCounter = 0
'Set Node to Operational Node
setcommand(_CS, 1, 0) 'Header of NMT messages is 0
setcommand(_CS, 3, 1) 'Go to operational
setcommand(_CS, 4, DTC510_NODEID)
setcommand(_CS, 2, 2)
top:
'print(Action,"\t",WriteCounter,"\t",TriggerCounter,"\t",Present,"\t",tag[0],"\t",tag[1],"\r")
wait(100)
Action = getvalue(_VAR,1)
while(getvalue(_CF) <> 0)
Header = getvalue(_CAN,1)
if(Header = 0x180 + DTC510_NODEID)
DeviceStatus = getvalue(_CAN,3) + (getvalue(_CAN,4) << 8) + (getvalue(_CAN,5) << 16) + (getvalue(_CAN,6) << 24)
if(DeviceStatus and 0x0004)
Present = 1
else
if(Present = 1)
NewTagState = 1
end if
Present = 0
end if
setcommand(_VAR, 2, DeviceStatus)
setcommand(_VAR, 3, Present)
elseif(Header = 0x280 + DTC510_NODEID)
tag[0] = getvalue(_CAN,3) + (getvalue(_CAN,4) << 8) + (getvalue(_CAN,5) << 16) + (getvalue(_CAN, 6) << 24)
tag[1] = getvalue(_CAN,7) + (getvalue(_CAN,8) << 8) + (getvalue(_CAN,9) << 16) + (getvalue(_CAN,10) << 24)
setcommand(_VAR, 4, tag[0])
setcommand(_VAR, 5, tag[1])
if(Present <> PrevPresent)
NewTagState = 1
end if
elseif(Header = 0x380 + DTC510_NODEID)
tag[2] = getvalue(_CAN,3) + (getvalue(_CAN,4) << 8) + (getvalue(_CAN,5) << 16) + (getvalue(_CAN, 6) << 24)
tag[3] = getvalue(_CAN,7) + (getvalue(_CAN,8) << 8) + (getvalue(_CAN,9) << 16) + (getvalue(_CAN,10) << 24)
setcommand(_VAR, 6, tag[2])
setcommand(_VAR, 7, tag[3])
elseif(Header = 0x480 + DTC510_NODEID)
tag[4] = getvalue(_CAN,3) + (getvalue(_CAN,4) << 8) + (getvalue(_CAN,5) << 16) + (getvalue(_CAN, 6) << 24)
tag[5] = getvalue(_CAN,7) + (getvalue(_CAN,8) << 8) + (getvalue(_CAN,9) << 16) + (getvalue(_CAN,10) << 24)
setcommand(_VAR, 8, tag[4])
setcommand(_VAR, 9, tag[5])
end if
'print(Header,"\t",Present,"\t",PrevPresent,"\t",DeviceStatus,"\r")
end while
if(NewTagState = 1)
if(Present = 1)
print("Tag Found With Tag Id = ", tag[0],"\r")
else
print("Tag Not Detected\r")
end if
NewTagState = 0
OkToWrite = 1
PrevPresent = Present
else
OkToWrite = 0
end if
if(Action <> 0 and Present = 1 and OkToWrite)
'Write Data
setcommand(_CS, 1, 0x300 + DTC510_NODEID) 'Header of RPDO 2
if(Action = WRITE_DATA and tag[0] = 0)
WriteCounter = getvalue(_VAR,10)
'Here you can play with the tag ids you want to use
setcommand(_CS, 4, TAGID_BYTE2) 'SetData
setcommand(_CS, 5, TAGID_BYTE3) 'SetData
setcommand(_CS, 6, TAGID_BYTE4) 'SetData
setcommand(_CS, 7, TAGID_BYTE5) 'SetData
setcommand(_CS, 8, TAGID_BYTE6) 'SetData
setcommand(_CS, 9, TAGID_BYTE7) 'SetData
setcommand(_CS, 10,TAGID_BYTE8) 'SetData
print("Tag written\r")
elseif(Action = ERASE_DATA)
WriteCounter = 0
setcommand(_CS, 4, 0) 'SetData
setcommand(_CS, 5, 0) 'SetData
setcommand(_CS, 6, 0) 'SetData
setcommand(_CS, 7, 0) 'SetData
setcommand(_CS, 8, 0) 'SetData
setcommand(_CS, 9, 0) 'SetData
setcommand(_CS, 10,0) 'SetData
print("Tag erased\r")
else
goto top
end if
setcommand(_CS, 3, WriteCounter) 'SetData
setcommand(_CS, 2, 8)
if(TriggerCounter = 1)
TriggerCounter = 0
else
TriggerCounter = 1
end if
setcommand(_CS, 1, 0x200 + DTC510_NODEID) 'Header of RPDO 1
setcommand(_CS, 3, TriggerCounter) 'SetData
setcommand(_CS, 4, 0) 'SetData
setcommand(_CS, 5, 0) 'SetData
setcommand(_CS, 6, 0) 'SetData
setcommand(_CS, 7, 0) 'SetData
setcommand(_CS, 8, 0) 'SetData
setcommand(_CS, 9, 0) 'SetData
setcommand(_CS, 10,0) 'SetData
setcommand(_CS, 2, 8)
end if
goto top